V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Loserzhu
V2EX  ›  程序员

MPEG-DASH 的好处有哪些?浏览器是如何加载普通.mp4 的?

  •  
  •   Loserzhu · 2022-11-30 14:07:16 +08:00 · 1367 次点击
    这是一个创建于 758 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求大部分是类似于游戏播片那种 2-3 min 的短视频。

    听说很多年前播放 mp4 只能等下载完了才能播放,所以都用 flash?(有没有年长的讲讲这段历史) 而现在 chrome 在播放 mp4 时是逐渐下载的。如果手动拖动进度条,加载的时间也不长。但是跳回已播放的部分貌似又要重新下载(至少从 network 上看是新请求)。这个是需要 server 配置还是浏览器的 feature ?

    最近在比较 DASH 技术和普通的 mp4 link 。非视频内容为主的业务,是不是不用把视频切成 ts/fmp4 这种的了?

    10 条回复    2022-12-01 14:07:11 +08:00
    tool2d
        1
    tool2d  
       2022-11-30 14:40:50 +08:00   ❤️ 1
    DASH 就是一堆不同分辨率 mp4 的合集嘛。

    不使用单一 mp4 还是有好处的,比如手机用移动流量看视频,高清 MP4 特别费流量。直接扔一个 mp4, 用户满意度就不会很高。
    okakuyang
        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 就会有不同的反应,有时候两种模式都可能会出现。
    Mohanson
        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 元信息挪到开头, 可以尽快开始播放
    hello2090
        4
    hello2090  
       2022-11-30 14:56:51 +08:00   ❤️ 1
    mp4 快速播放就是上面说的,把 moov atom 放到文件前面,那里面存了每一帧的位置和大小。主要区别是 mepg dash ,hls, flv 能播放 live 啊,也就是流。流是不可能先给你一个 moov atom 的。
    Loserzhu
        5
    Loserzhu  
    OP
       2022-11-30 20:00:12 +08:00
    感谢各位的回复
    edis0n0
        6
    edis0n0  
       2022-11-30 21:48:55 +08:00
    @Mohanson 不重编码的情况下能将元数据放到文件开头吗
    Mohanson
        7
    Mohanson  
       2022-11-30 21:53:35 +08:00
    @edis0n0 可以的, -c:v libx264 -c:a aac 替换成 -c copy
    hello2090
        8
    hello2090  
       2022-12-01 06:34:16 +08:00
    @edis0n0 可以的,FFMPEG 的那个命令-movflags faststart 应该就可以。
    Loserzhu
        9
    Loserzhu  
    OP
       2022-12-01 11:24:39 +08:00
    @hello2090 还有个问题想请教。像 hls ,每个 media chunk 都很小,浏览器可以缓存。如果是 mp4 ,浏览器会缓存吗?我从 network 面板上看不出,感觉每次加载、拖动进度条再跳回已经加载的,这些操作都是重新请求了 server 。。
    hello2090
        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 的图像,当然这也是有办法做的,只要你播放过你总能记录下来,但其实我觉得挺麻烦的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   998 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:01 · PVG 07:01 · LAX 15:01 · JFK 18:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.