使用ffmpeg进行飞速转码和HLS流式传输

问题描述 投票:0回答:1

我正在构建一个涉及服务各种视频内容的网络应用。对网络友好的音频和视频编解码器的处理没有任何问题,但我在设计传输不兼容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播放列表,因为格式是不言而喻的。网络应用会使用视频属性,如持续时间、分辨率和比特率(服务器已知)事先生成HLS主播放列表和VOD播放列表,并将主播放列表提供给客户端。然后客户端开始请求各个视频片段,这时服务器将单独对每个片段进行转码和生成,并提供给他们。寻求将是可能的,因为客户端已经有完整的VOD播放列表,它可以请求用户寻求的特定片段。在我看来,这样做的好处是,如果用户决定向前寻求并在中途播放视频,我的服务器将不必对整个文件进行转码。

现在,我试着手动创建片段(每段10秒),从我的 sample.mkv 使用以下命令

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

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

现在我的问题是:

  1. 为什么后续的片段不能播放?我到底做错了什么?

  2. 我的技术是否可行?由于只有在关键帧之后才能进行分段,所以预设分段的持续时间会不会有问题,以及ffmpeg是否能解决这个问题?

我在视频处理和生成方面的知识充其量也只是个小白。如果能给我一些建议,我将非常感激。

video ffmpeg http-live-streaming
1个回答
0
投票

这是可能的,但非常困难。我甚至认为用ffmpeg可能不可能。传输流有时间戳和连续性计数器,这些值应该在段的边界上被保留。-copyts标志可能会有一点帮助。在这种情况下,B帧是极难处理的,因为它们最终会在段外留下时间戳。音频也很难处理。当编码器初始化时,音频有初始化样本,这意味着你可能会有额外的样本,每段通过音频弹出。

TLDR,是可能的,但你需要了解的容器和底层编解码器的结构,并与他们的工作。

© www.soinside.com 2019 - 2024. All rights reserved.