我正在尝试构建一些自动化脚本来使用 ffmpeg 对视频进行转码,但当格式设置为 HLS 时,关键帧会出现在错误的位置。这种情况发生在不同的来源(例如 4k 版本的大雄兔)。我使用的是静态编译版本的John Vansickle 的 ffmpeg 4.1。
当我转码为 mp4/h264 时,关键帧处于预期的时间码中(每 2 秒)。这是我运行的命令:
ffmpegparams="-c:a aac -ar 22050 -c:v libx264 -profile:v high
-level 4.1 -crf 20 -r 30 -g 180 -keyint_min 30
-force_key_frames expr:gte(t,n_forced*2)"
ffmpeg -hide_banner -y -i video.mp4 \
-vf scale=w=640:h=360:force_original_aspect_ratio=decrease $ffmpegparams \
-b:v 400k -maxrate 428k -bufsize 600k -b:a 64k video-360p.mp4 \
-vf scale=w=854:h=480:force_original_aspect_ratio=increase $ffmpegparams \
-b:v 600k -maxrate 652k -bufsize 900k -b:a 64k video-480p.mp4 \
-vf scale=w=1280:h=720:force_original_aspect_ratio=decrease $ffmpegparams \
-b:v 1000k -maxrate 1070k -bufsize 1500k -b:a 96k video-720p.mp4
我运行来查看关键帧的命令是
ffprobe -v error -skip_frame nokey -show_entries frame=pkt_pts_time \
-select_streams v -of csv=p=0 video-360p.mp4
输出
0.000000
2.000000
4.000000
[...]
当我将同一视频转码为 ts/x264 (HLS) 时,关键帧会偏移 1.466 秒。这是我使用的命令(如果输出是分段的而不是在一个文件中,也会发生同样的问题)
ffmpegparams="-c:a aac -ar 22050 -c:v libx264 -profile:v high -level 4.1
-crf 20 -r 30 -g 180 -keyint_min 30
-force_key_frames expr:gte(t,n_forced*2) -hls_time 6
-hls_playlist_type vod -hls_flags single_file"
ffmpeg -hide_banner -y -i video.mp4 \
-vf scale=w=640:h=360:force_original_aspect_ratio=decrease $ffmpegparams \
-b:v 400k -maxrate 428k -bufsize 600k -b:a 64k \
-hls_segment_filename "video-360p.ts" video-360p.m3u8 \
-vf scale=w=854:h=480:force_original_aspect_ratio=increase $ffmpegparams \
-b:v 600k -maxrate 652k -bufsize 900k -b:a 64k \
-hls_segment_filename "video-480p.ts" video-480p.m3u8 \
-vf scale=w=1280:h=720:force_original_aspect_ratio=decrease $ffmpegparams \
-b:v 1000k -maxrate 1070k -bufsize 1500k -b:a 64k \
-hls_segment_filename "video-720p.ts" video-720p.m3u8
在任意文件上运行 ffprobe 后ts
,我得到关键帧的以下时间码:
1.466667
3.466667
5.466667
[...]
当我播放任何文件时,ts
前 1.46 秒图像就会冻结。
我想知道是否有人可以帮助我弄清楚发生了什么以及如何解决这个问题。