我正在另一台机器上运行 ffmpeg 以进行屏幕捕获。我希望能够远程停止录制。 FFMPEG 要求按 q 来停止编码,因为它必须执行一些最终操作才能干净地完成文件。我知道我可以用kill/killall杀死它,但这可能会导致视频损坏。
Press [q] to stop encoding
我在谷歌上找不到专门为此目的的任何内容,但有人建议回显到 /proc//fd/0 可以工作。
我已经尝试过这个,但它不会停止 ffmpeg。然而,q 显示在运行 ffmpeg 的终端中。
echo -n q > /proc/16837/fd/0
那么如何将字符发送到另一个现有进程,就像在本地输入一样?或者是否有另一种方法可以干净地远程停止 ffmpeg。
这是我在遇到这个问题时发现的一个巧妙的技巧:创建一个空文件(它不必是命名管道或任何东西),然后在停止记录时向其中写入“q”。
FFmpeg 停止,就好像它从终端 STDIN 获得“q”一样。
较新版本的 ffmpeg 不再使用“q”,至少在 Ubuntu Oneiric 上,而是说按 Ctrl+C 来停止它们。因此,使用较新的版本,您可以简单地使用“killall -INT”向它们发送 SIGINT 而不是 SIGTERM,并且它们应该干净地退出。
详细阐述 sashhoalm 的答案,我测试了这两种情况,结果如下:
killall --user $USER --ignore-case --signal INT ffmpeg
Exiting normally, received signal 2.
killall --user $USER --ignore-case --signal SIGTERM ffmpeg
Exiting normally, received signal 15.
所以看起来 ffmpeg 对于这两个信号都很好。
系统:Debian GNU/Linux 9(延伸),2020-02-28
这个问题已经在 Linux 上得到了解答,但是当我在寻找 Windows 等效项时它出现了,所以我将把它添加到答案中:
在 powershell 上,您可以像这样启动该过程:
$((Start-Process ffmpeg -passthru -argument "FFMPEG_ARGS").ID)
这会发回 FFMPEG 进程的 PID,您可以将其存储在变量或 echo 中,然后使用 taskkill 发送相当于 sigint (Ctrl + C) 的 Windows
taskkill /pid FFMPEG_PID
我尝试使用 Stop-Process(这是在 Google 上查找如何执行此操作时出现的结果),但它实际上杀死了该进程。 (是的,taskkill 不会杀死它,它会温和地要求进程停止......很好的命名:D)
你也可以尝试使用“expect”来自动执行和停止程序。您必须使用一些虚拟外壳(如
screen
、tmux
或 byobu
)来启动它,然后启动其中的 ffmpeg
。这样您就可以再次获得虚拟 shell 屏幕并给出“q”选项。
本地或远程启动虚拟 shell 会话,比如说“屏幕”。使用
-S
选项命名会话,例如 screen -S recvideo
然后您可以根据需要启动 ffmpeg。您可以选择使用 Ctrl+a + d 退出此会话。连接到屏幕内运行 ffmpeg 的机器(或 tmux 或其他)并重新连接到它:
screen -d -RR recvideo
,然后发送“q”要从脚本内部执行此操作,您可以使用expect,例如:
prompt="> "
expect << EOF
set timeout 20
spawn screen -S recvideo
expect "$prompt"
send -- "ffmpeg xxxxx\r"
set timeout 1
expect eof
EOF
然后,在另一个时刻或脚本点或另一个脚本中您可以恢复它:
expect << EOF
set timeout 30
spawn screen -d -RR recvideo
expect "$prompt"
send -- "q"
expect "$prompt"
send -- "exit\r"
expect eof
EOF
您还可以使用 Expect 来自动化整个
ssh
会话,传递一系列命令并“期望”执行您想要的操作。
在基于 Linux 的系统上,您可以发送
SIGQUIT
信号(例如 kill -3 [pid]
),如此处所述。
在 Windows 系统上没有
SIGQUIT
信号,所有其他建议的解决方案都会给我们留下损坏的视频文件。