需求大部分是类似于游戏播片那种 2-3 min 的短视频。
听说很多年前播放 mp4 只能等下载完了才能播放,所以都用 flash?(有没有年长的讲讲这段历史) 而现在 chrome 在播放 mp4 时是逐渐下载的。如果手动拖动进度条,加载的时间也不长。但是跳回已播放的部分貌似又要重新下载(至少从 network 上看是新请求)。这个是需要 server 配置还是浏览器的 feature ?
最近在比较 DASH 技术和普通的 mp4 link 。非视频内容为主的业务,是不是不用把视频切成 ts/fmp4 这种的了?
1
tool2d 2022-11-30 14:40:50 +08:00 1
DASH 就是一堆不同分辨率 mp4 的合集嘛。
不使用单一 mp4 还是有好处的,比如手机用移动流量看视频,高清 MP4 特别费流量。直接扔一个 mp4, 用户满意度就不会很高。 |
2
okakuyang 2022-11-30 14:43:25 +08:00 2
现在主要是两个阵营,chrome like 和 safari like 。
chrome 播放 mp4 一般发起一个请求下载整个文件的数据。 一边接收数据一边解析,如果达到可以播放的缓冲就开始播放。 快进的话会从视频帧对应文件位置请求。 safari like 播放 mp4 有两种模式,其中一种和 chrome 类似,只需要一个请求就开始播放。 但是这种模式出现的时机比较苛刻。 另外一种是彻底的 safari 模式。播放视频时候需要请求非常多次。 第一次会请求两个字节,要求服务器返回 mp4 文件长度。 接下来会: 第二次请求会请求文件全长度(服务器不一定会返回全部长度,可能只会传输几 M ) 第二次请求文件尾部几 MB 字节 (服务器应该返回这部分的全部长度) 因为 mp4 文件结构中视频信息在文件尾部,所以要先请求到这部分数据解析后播放。 之后 safari 会重复多次请求,一边播放一边请求接下来要播放的部分。 不同平台 webview 处理逻辑差异:例如 windows10 上的 webview 就会有不同的反应,有时候两种模式都可能会出现。 |
3
Mohanson 2022-11-30 14:50:32 +08:00 2
以前 mp4 文件的元数据放在文件末尾, 现在可以将元数据放到文件开头. 只要下载了元数据 mp4 就可以开始播放.
用 ffmpeg 带以下参数转码下视频, 就能在大多数播放器上播放(包括各种浏览器) -c:v libx264 -c:a aac -pix_fmt yuv420p -ac 2 -movflags faststart -pix_fmt yuv420p 是因为 chrome 只支持 yuv420p 像素格式, -ac 2 是因为 chrome android 只支持双声道 -movflags faststart 是把 mp4 元信息挪到开头, 可以尽快开始播放 |
4
hello2090 2022-11-30 14:56:51 +08:00 1
mp4 快速播放就是上面说的,把 moov atom 放到文件前面,那里面存了每一帧的位置和大小。主要区别是 mepg dash ,hls, flv 能播放 live 啊,也就是流。流是不可能先给你一个 moov atom 的。
|
5
Loserzhu OP 感谢各位的回复
|
9
Loserzhu OP @hello2090 还有个问题想请教。像 hls ,每个 media chunk 都很小,浏览器可以缓存。如果是 mp4 ,浏览器会缓存吗?我从 network 面板上看不出,感觉每次加载、拖动进度条再跳回已经加载的,这些操作都是重新请求了 server 。。
|
10
hello2090 2022-12-01 14:07:11 +08:00 1
@Loserzhu 我已经很久没做这个了,而且这和浏览器相关吧,所以我不了解。但你 SEEK, 也就是在进度条点击的时候,是 SEEK 到下一个 /或者上一个 KEY FRAME 的,至少本地的视频播放器是这样的。比如说电影一开头你就点到 1 小时那个地方,代码里会请求 SEEK(1 小时),这样 FFMPEG 内部会把读的指针设置好,这样你下一个 readframe 读出来的就是 1 小时附近的内容了。
你缓冲文件可以啊,你要取下一个文件之前看看本地有没有,本地有就用本地的,不要 REQUEST SERVER. 但我觉得视频播放器,那就是读一帧显示一帧,你把解好的帧存起来我是没见过。这个东西难做吧,视频播放器是一个 WHILE 循环,把数据读出来,放到解码器里,返回一个 VIDEO FRAME, 显示在屏幕上,有的时候你要放好几段数据解码器才会解出一个 VIDEO FRAME 的,而且你也是解出来了,才知道这帧的 TIMESTAMP 。 哦对,我想一般播放器是两个线程,一个声音,一个图像,因为声音是连续的,所以一般声音是基准。每放一点声音,比如说到了 1:20:30 了,看一下有没有图像在这之前的,有就把图像也显示出来,因为声音的 STEP 小,检查会比较频繁,所以每帧图像都会被显示出来。 所以实现肯定是可以的,但这个也很 TRICKY, 比如说你现在到 1:20:30 了,你缓存了 1:20:25 和 1:20:27 的图像,当然你要把他们显示出来,那中间会不会还有别的图像?有些是可变 FPS 的吧,所以可能你缓存的两帧之间有一帧漏掉了,你要调用 DECODE 把他拿出来,但是我说了你也不知道那块数据能解出 1:20:26 的图像,当然这也是有办法做的,只要你播放过你总能记录下来,但其实我觉得挺麻烦的 |