video - 使用 ffmpeg 进行动态转码和 HLS 流式传输

标签 video ffmpeg http-live-streaming

我正在构建一个涉及提供各种视频内容的 Web 应用程序。处理网络友好的音频和视频编解码器没有任何问题,但我在设计与 HTML5 视频播放器(如 mkv 容器或 H265)不兼容的视频文件的交付时遇到了麻烦。

到目前为止,我所做的是使用 ffmpeg 对服务器上的视频文件进行转码,并制作 HLS 主播放列表和 VOD 播放列表,并在前端使用 hls.js。然而,问题在于 ffmpeg 将播放列表视为实时流播放列表,直到整个文件的转码完成,然后它将播放列表更改为 VOD。因此,在转码结束之前用户无法搜索,并且如果用户决定在中途搜索视频文件,我的服务器已经不必要地对整个文件进行了转码。我正在使用以下 ffmpeg 命令行参数

ffmpeg -i sample.mkv \
       -c:v libx264 \
       -crf 18 \
       -preset ultrafast \
       -maxrate 4000k \
       -bufsize 8000k \
       -vf "scale=1280:-1,format=yuv420p" \
       -c:a copy -start_number 0 \
       -hls_time 10 \
       -hls_list_size 0 \
       -f hls \
file.m3u8

现在为了改进这个系统,我尝试通过我的应用程序而不是 ffmpeg 生成 VOD 播放列表,因为格式是不言自明的。 webapp 将使用视频属性(如持续时间、分辨率和比特率(服务器已知))预先生成 HLS 主播放列表和 VOD 播放列表,并将主播放列表提供给客户端。然后客户端开始请求各个视频片段,此时服务器将单独转码并生成每个片段并提供服务。由于客户端已经拥有完整的 VOD 播放列表,因此可以进行搜索,并且可以请求用户搜索的特定片段。如我所见,这样做的好处是,如果用户决定向前搜索并在中途播放视频,我的服务器将不必对整个文件进行转码。

现在我尝试从我的 sample.mkv 手动创建段(每个 10 段)使用以下命令
ffmpeg -ss 90 \
       -t 10 \
       -i sample.mkv \
       -g 52 \
       -strict experimental \
       -movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov \
       -c:v libx264 \
       -crf 18 \
       -preset ultrafast \
       -maxrate 4000k \
       -bufsize 8000k \
       -vf "scale=1280:-1,format=yuv420p" \
       -c:a copy \
fileSequence0.mp4

其他片段以此类推,VOD 播放列表为
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
fileSequence0.mp4
#EXTINF:10.0,
fileSequence1.mp4
...
... and so on 
...
#EXT-X-ENDLIST

它播放第一段很好,但不能播放后续段。

现在我的问题,
  • 为什么后面的片段不播放?我究竟做错了什么?
  • 我的技术是否可行?预设分段持续时间会有什么问题,因为分段只能在关键帧之后进行,ffmpeg 是否可以解决这个问题?

  • 我关于视频处理和生成的知识充其量只是适度的。我将不胜感激一些指示。

    最佳答案

    这是可能的,但非常困难。我什至会争辩说,使用 ffmpeg 可能是不可能的。传输流具有时间戳和连续性计数器,这些值应跨段边界保留。 -copyts 标志可能对此有所帮助。在这种情况下,B 帧非常难以处理,因为它们最终会带有段外的时间戳。音频也很困难。初始化编码器时,音频具有启动样本,这意味着您可能在每个片段中都有额外的样本,这些样本随着音频弹出而通过。

    TLDR 是可能的,但您需要了解容器和底层编解码器的结构,并使用它们。

    关于video - 使用 ffmpeg 进行动态转码和 HLS 流式传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61913288/

    相关文章:

    mediaelement.js - 用m3u8播放列表播放分段的hls流

    c# - 从视频文件中提取wav文件

    audio - 按键时的低延迟声音

    c++ - 均匀直方图和非均匀直方图有什么区别?

    jquery - 如何 : video will disappear after it's over and show another div

    ffmpeg - RTMP 上的 ffplay/ffmpeg,采用 H264 编码

    php - ffmpeg 在 php 或 python 中获取元数据

    android - 如何一起使用mobile-ffmpeg和共享库(.so)ffmpeg?

    audio - 能否在附加模式下使用 cat 命令组合 .ts 音频文件以获得 .mp3 文件

    audio - 从 mp3 创建 HLS 可流式音频文件