我发现 thread_queue_size 数值似乎适用于我的系统,但如果有人能提出建议,我会进行更多测试(或重复测试)以帮助解决问题。请提供意见。谢谢,马克。
thread_queue_size 24883200(避免“线程消息队列阻塞”)
命令行是 VapourSynth (VSPIPE) 管道原始帧加上 FFMPEG 从 VOB 的连接中获取音频和字幕,因此:
VSPIPE --y4m C:\AVout\VTS_04_1(210820-023517.49).mkv.vpy - | FFMPEG -thread_queue_size 24883200 -i pipe: -i "concat:h:\VIDEO_TS\VTS_04_1.VOB|h:\VIDEO_TS\VTS_04_2.VOB|h:\VIDEO_TS\VTS_04_3.VOB|h:\VIDEO_TS\VTS_04_4.VOB|h:\VIDEO_TS\VTS_04_5.VOB|h:\VIDEO_TS\VTS_04_6.VOB" -filter_complex "[0:v]settb=expr=1/120,setpts=expr=N,setdar=16/9,setsar=32/27[v];[1:a:0]atempo=1.001[a0];[1:a:1]atempo=1.001[a1];[1:a:2]atempo=1.001[a2];[1:a:3]atempo=1.001[a3];[1:a:4]atempo=1.001[a4]" -map "[v]" -map "[a0]" -map "[a1]" -map "[a2]" -map "[a3]" -map "[a4]" -map 1:s -codec:v libx265 -x265-params "crf=18:qcomp=0.80:sao=no:strong-intra-smoothing=no" -codec:a:0 ac3 -codec:a:1 ac3 -codec:a:2 ac3 -codec:a:3 ac3 -codec:a:4 ac3 -codec:s copy -r 120 C:\AVout\VTS_04_1(210820-023517.49).mkv
结果:
1,转码以大约speed=0.5进行。
2、运行时,VSPIPE 占据了 8 个线程(比 FFMPEG 大约高出 2 倍),并且“系统提交”(使用的 RAM + 使用的分页之和)在稳步上升后达到了最大值 126.3GB。
3、控制台输出的注释是“错误:写入帧:331449,平面 2,错误号:22 时,fwrite() 调用失败”。很难确定,但失败消息似乎确实在“系统提交”达到顶峰的同一时刻打印出来。在播放时,视频会在该精确点冻结:帧 331449(46:02.072)——应该有 939036 帧(2:10:25.305)。
线程队列大小 2048
命令行再次是 VapourSynth (VSPIPE) 管道原始帧等等(但这次使用“-thread_queue_size 2048”),因此:
VSPIPE --y4m C:\AVout\VTS_04_1(210820-042617.65).mkv.vpy - | FFMPEG -thread_queue_size 2048 -i pipe: -i "concat:h:\VIDEO_TS\VTS_04_1.VOB|h:\VIDEO_TS\VTS_04_2.VOB|h:\VIDEO_TS\VTS_04_3.VOB|h:\VIDEO_TS\VTS_04_4.VOB|h:\VIDEO_TS\VTS_04_5.VOB|h:\VIDEO_TS\VTS_04_6.VOB" -filter_complex "[0:v]settb=expr=1/120,setpts=expr=N,setdar=16/9,setsar=32/27[v];[1:a:0]atempo=1.001[a0];[1:a:1]atempo=1.001[a1];[1:a:2]atempo=1.001[a2];[1:a:3]atempo=1.001[a3];[1:a:4]atempo=1.001[a4]" -map "[v]" -map "[a0]" -map "[a1]" -map "[a2]" -map "[a3]" -map "[a4]" -map 1:s -codec:v libx265 -x265-params "crf=18:qcomp=0.80:sao=no:strong-intra-smoothing=no" -codec:a:0 ac3 -codec:a:1 ac3 -codec:a:2 ac3 -codec:a:3 ac3 -codec:a:4 ac3 -codec:s copy -r 120 C:\AVout\VTS_04_1(210820-042617.65).mkv
结果:
1,转码以 speed=1.0 左右的速度进行,并出现“线程消息队列阻塞;考虑提高 thread_queue_size 选项(当前值:2048)”。
2、当 VSPIPE 运行时,FFMPEG(而不是 VSPIPE)占据主导地位(比 VSPIPE 高出约 5 倍),并且“系统提交”增加,然后稳定在仅 5.9GB。
3、播放一切正常。
进一步的运行
我将错误的 thread_queue_size 减半为 12441600,然后再次减半为 6220800,等等,同时在每次运行中监控“系统提交”。每次运行时,当我降低 thread_queue_size 时,我都会看到“系统提交”和 CPU 利用率开始在 VSPIPE 和 FFMPEG 之间保持平衡。
结果
在“-thread_queue_size 48600”时,我再次开始收到“线程消息队列阻塞;考虑提高thread_queue_size选项(当前值:48600)”并且事情稳定下来:FFMPEG&VSPIPE扭转了对CPU利用率的主导地位(现在FFMPEG占主导地位)并且“系统提交”线性上升到28.5GB然后趋于平稳。
在我看来,“线程消息队列阻塞”是一件好事——管道长时间运行也不会溢出。除了摆弄thread_queue_size之外,还有其他更好的方法可以确保这一点吗?
还有一件事我不明白:为什么我会继续收到“由于时间戳而启动新集群”的通知 - 我认为这是从编码器发出的 - 当是我在写时间戳(通过“settb=expr=1/120,setpts=expr=N”)时?
注意:所有代码和文件均位于固态 RAID0、Windows10、4 个双核(8 个线程)、3.6 GHz、32GB RAM + 100GiB pagefile.sys 上。用于监控 CPU 利用率和“系统提交”的工具:Sysinternals、Process Explorer v16.21。
答案1
从https://ffmpeg.org/ffmpeg.html
-thread_queue_size size (input)
This option sets the maximum number of queued packets when reading from the file or device. With low latency / high rate live streams, packets may be discarded if they are not read in a timely manner; setting this value can force ffmpeg to use a separate input thread and read packets as soon as they arrive. By default ffmpeg only do this if multiple inputs are specified.
另一个线索是
While it ran, VSPIPE dominated the 8 threads (by a factor of ~2x over FFMPEG) and "System Commit" (sum of used RAM + used paging) maxed out at 126.3GB after rising steadily.
这是一个缓冲问题 - ffmpeg 无法以接收帧的速度处理它们。我们可以尝试 3 种解决方案。
a. 写入不同的 SSD/HDD 作为输入文件 SSD/HDD。这将排除写入速度作为故障参数。
b. 由于您使用的是 Windows - 启动您的进程如下
start /b /high "cmd"
c. 在 Windows 中,命名管道和匿名管道的速度差别很大。
从 -http://trac.ffmpeg.org/ticket/986
windows standard input is very slow. So I switched to named pipes. It's up to 10x faster then standart input (pipe:).
将匿名管道输入-
和替换-i pipe:
为
-i \\.\pipe\pipename out.mkv
Windows 没有官方的 cmd 实用程序 - 你可以使用它 - github.com/psmay/windows-named-pipe-utils