给女朋友做的视频播放平台,播放视频很卡,有几张方案解决

2023-09-21 18:06:56 +08:00
 KuAoaoaoao

1.首先,介绍场景:视频播放平台,系统使用 Springboot 和 Vue 编写。拥有前台和后台,前台进行视频播放,后台进行视频的上传,也可以上传音乐和图片,功能顺手都做了。

2.问题:浏览器播放视频卡顿。视频卡顿问题需要攻克 2 关。

3.解决过程: 1 )第一关:视频文件太大,浏览器加载时间长。采用后端对文件分块读取。 场景:编写完成文件的上传与下载接口,在浏览器使用<video>组件绑定 url 进行观看视频。按照以上步骤,浏览器是能正常播放视频的,但是我把项目发布到服务器后,就出现另一个情况了。我发现浏览器会一直加载视频,浏览器中心呈现转圈动画,进度条会一点一点增长,但是没有画面出现。直到进度条加载完,才会出现画面。 原因:后端的下载接口是把整个视频文件一下子发送到浏览器,所以浏览器一直在接收文件,接收完文件后,浏览器的 video 组件才能进行播放。 解决:后端接口使用 randomAccessFile 类读取文件,这个类取到 file 的信息后,你便可以设置从文件的哪个位置开始读取,读取多少字节,然后把数据响应到浏览器。 这样就解决了浏览器一直加载视频的问题。例子代码在末尾。 2 )第二关:服务器带宽太低,视频下载赶不上视频播放,造成视频播放卡顿。采用 ffmpeg 组件进行画质压缩。 场景:假如有一个 30 秒 90M 的视频(我手机录的),上传到服务器了,然后在浏览器进行播放,那么播放视频就会卡顿了。 原因:因为服务器的带宽是 1M/s ,每秒能传送 1M 文件到浏览器,但是浏览器要想流畅播放那个视频,浏览器需要每秒接收 3M 文件,90M 的视频,30 秒,每秒需要播放 3M ,所以这就造成视频播放卡顿了。 解决:使用 ffmepg 组件,把 90M 的视频压缩到 30M ,可以压缩视频的比率和分辨率,最好进行相同比例的压缩,不然画质会变糊。

代码: 1 )第一关: /** * 斷點播放 * @param request * @param response * @throws IOException */ public void play(HttpServletRequest request, HttpServletResponse response) throws IOException{ response.reset(); File file = new File("本地的一個視頻地址"); long fileLength = file.length(); // 随机读文件 RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");

    //获取从那个字节开始读取文件
    String rangeString = request.getHeader("Range");
    long range=0;
    if (StrUtil.isNotBlank(rangeString)) {
        range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
    }
    //获取响应的输出流
    OutputStream outputStream = response.getOutputStream();
    //设置内容类型
    response.setHeader("Content-Type", "video/mp4");
    //返回码需要为 206 ,代表只处理了部分请求,响应了部分数据
    response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
    // 移动访问指针到指定位置
    randomAccessFile.seek(range);
    // 每次请求只返回 1MB 的视频流
    byte[] bytes = new byte[1024 * 1024];
    int len = randomAccessFile.read(bytes);
    //设置此次相应返回的数据长度
    response.setContentLength(len);
    //设置此次相应返回的数据范围
    response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
    // 将这 1MB 的视频流响应给客户端
    outputStream.write(bytes, 0, len);
    outputStream.close();
    randomAccessFile.close();

// System.out.println("返回数据区间: ["+range+"-"+(range+len)+"] "); }

2 )第二关: ffmepg 依赖 <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.3</version> </dependency> 代码: /**

4809 次点击
所在节点    Java
48 条回复
fengci
2023-09-21 18:20:57 +08:00
视频切片。m3u8 ,然后你就不需要做其他任何处理了。
flyqie
2023-09-21 18:23:54 +08:00
@fengci #1

是的,楼主这个需求可以转画质后通过 m3u8 实现。。。
kiduu
2023-09-21 18:26:57 +08:00
判断一下视频时长,1 分钟以内的 MP4 直链,中长视频直接无脑切片就行。
Elissa
2023-09-21 18:48:21 +08:00
要不试试用 cdn 顶上?感觉是服务器带宽不够
chaoschick
2023-09-21 18:49:28 +08:00
如果使用 video 标签绑定 url 播放可以试试 videojs 这个库,但是这个有点问题就是视频不能过大 谷歌浏览器好像是不能超过 150MB
JensenQian
2023-09-21 18:52:02 +08:00
直接 emby ,plex
chaoschick
2023-09-21 18:52:46 +08:00
前端流式播放视频的技术 感觉还不太成熟,还没有统一,PC 端与安卓端现在大部分都是才用的不同技术,安卓那边一般是用 m3u8 ,PC 这边一般是 flv
leaflxh
2023-09-21 19:05:36 +08:00
b 站是转成 dash ,腾讯视频是 hls

不切片 1M 的小水管估计够呛,因为比如拖动进度条到第 60 秒,但上个关键帧是在第 30 秒,结果就是浏览器要从 30 秒的地方开始下载,这 30 秒的视频大小可能超过 10M ,这样就导致要等待 10 秒的时间才能开始播放第 60 秒的视频
KuAoaoaoao
2023-09-21 19:07:48 +08:00
@Elissa cdn 加速应该可以 但是需要付费哦,商业项目可以加
KuAoaoaoao
2023-09-21 19:10:34 +08:00
@chaoschick 如果只上传项目定位是只播放 150M 以下大小的视频 有机会试试
KuAoaoaoao
2023-09-21 19:11:00 +08:00
@fengci 知识盲区了 我去学习一下
KuAoaoaoao
2023-09-21 19:11:10 +08:00
@flyqie 我瞅瞅
KuAoaoaoao
2023-09-21 19:12:08 +08:00
@JensenQian 知识盲区了 俺学习下
KuAoaoaoao
2023-09-21 19:14:36 +08:00
@chaoschick 原来简简单单的文件下载 涉及到视频文件时便成了流式传输领域
KuAoaoaoao
2023-09-21 19:15:39 +08:00
@leaflxh 醍醐灌顶
ltyj2003
2023-09-21 20:00:07 +08:00
硬盘寄过去不好吗?
Maerd
2023-09-21 20:16:59 +08:00
你和我当时犯的错误一样,就是把视频通过后端处理然后返回给前端,这个对服务的影响其实蛮大的。楼上的几个老哥也说复杂了,实际上视频无论是 mp4 还是 flv ,套一层 nginx ,把静态链接丢给前端就可以流式播放了,不需要手动处理。另外就是,视频这种的大静态文件最好不要直接丢在服务器上
Bingchunmoli
2023-09-21 20:20:17 +08:00
直接对象存储 mp4 默认支持流式传输
herozzm
2023-09-21 20:26:27 +08:00
文件太大,不应该要压缩一下吗?光切片没啥用
KuAoaoaoao
2023-09-21 20:40:07 +08:00
@Maerd 需要考虑一下项目的定位,小项目小视频就放自己服务器。大项目可以采用 oss 提高用户体验。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/975960

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX