首页 > 解决方案 > 如何从分段的 mp4 创建一个没有声音缺陷的 http 直播流(广播)

问题描述

tl;dr - 将独立的短视频连接到 hls 播放列表会产生声音缺陷。连接点处的“滴答”声。我该如何避免呢?

我有一个每 3 秒发出 4 秒 MOV 视频的进程。这些 4s 视频是较长视频的片段。但它们是完全独立的。我希望能够在更长的视频存在之前播放它。为了实现这一点,我正在创建一个 HLS 甚至播放列表 hls 事件播放列表 ,我首先使用 ffmpeg 将第一个 4s 视频转换为 hls,方法是运行:

fmpeg -y -i  output0.mov -c:a aac -b:a 128000 -r:a 44100 -c:v libx264  -x264-params keyint=150:scenecut=0  -hls_flags omit_endlist -hls_playlist_type -b:t 800k -maxrate 2000k -bufsize 1200k -f hls -pix_fmt yuv420p -g 5 -hls_time 5 one.m3u8

这将创建一个 .ts 文件和一个 .m3u8 播放列表

#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-TARGETDURATION:4
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.00,
part1.ts

注意 :-hls_flags omit_endlist -hls_playlist_type event标志。他们确保播放列表是一个 EVENT 播放列表,并且EXT-X-ENDLIST列表末尾没有(这使播放器开始轮询 .m3u8 文件以“等待”新的 .ts 块被附加到播放列表)

当下一个 4s 视频可用时,我再次运行 ffmpeg 命令。然后将新的 .m3u8 文件“合并”到旧的 .m3u8 文件。通过将新的 .ts 文件附加到播放列表。

#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-TARGETDURATION:4
#EXT-X-VERSION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.00,
part1.ts <- first 4 seconds chunk
#EXTINF:4.00,
part2.ts <- second ( new ) 4 second chunk

因为播放器正在轮询 .m3u8 文件,所以当它更新时,它会获取第二个 .ts 文件(part2.ts)并播放它。

唯一的问题是声音缺陷。正好在两个视频的连接点。(在第二个 4 )在这个例子中。视频没有明显的缺陷。我怀疑这是因为编码问题而发生的。(每个 mov 视频都单独编码为 hls )但是我必须在 4 秒后播放视频。(不能等待整个持续时间准备好)

我究竟做错了什么 ?如何编码 hls 块以避免声音缺陷?

在 ffmpeg 文档中我看到: 分割输入文件,并创建一个 M3U8 实时播放列表(可用作实时 HLS 源):

ffmpeg -re -i in.mkv -codec copy -map 0 -f segment -segment_list playlist.m3u8 \
-segment_list_flags +live -segment_time 10 out%03d.mkv

我的问题是我没有完整的视频。它逐块生成。

标签: ffmpegvideo-streaminghttp-live-streamingvideo-encoding

解决方案


问题是 AAC 不是一种仅用于将单独编码的片段连接在一起的友好格式。AAC 始终是 1024 个样本的倍数。如果您的音频块恰好是 1025 个样本,则生成的编码被填充到 2048,最终得到 1023 个静音样本。通常你不知道有多少沉默。因此,您必须使所有块的 ffmpeg 编码过程保持活动状态。如果您在 Unix 上创建名称管道,请将您输入的视频通过管道传输到您的命名管道中,并让 ffmpeg 读取名称管道。

mkfifo my_pipe
cat my_file > my_pipe
ffmpeg -re -i my_pipe // and some more

推荐阅读