将 ffmpeg 输出通过管道传输到命名管道

Posted

技术标签:

【中文标题】将 ffmpeg 输出通过管道传输到命名管道【英文标题】:Pipe ffmpeg output to named pipe 【发布时间】:2015-06-18 18:21:37 【问题描述】:

我正在尝试将 ffmpegs 输出到命名管道,在那里我可以从另一个 shell 读取。我不需要通过管道传输视频流,只需以下信息即可获取转换过程的状态。我无法以任何方式实现管道行为,但我可以使用以下命令将数据写入文件:

ffmpeg -i vid.mov -vcodec h264 -acodec aac -strict -2 -y vid.mp4 > fflog.txt 2>&1

这导致 fflog.txt 中的以下输出

Stream mapping:
Stream #0:1 -> #0:0 (h264 (native) -> h264 (libx264))
Stream #0:0 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
frame=   50 fps=0.0 q=0.0 size=       0kB time=00:00:03.20 bitrate=   0.1kbits/s
frame=   73 fps= 70 q=28.0 size=     230kB time=00:00:04.05 bitrate= 465.4kbits/s
frame=  100 fps= 65 q=28.0 size=     462kB time=00:00:05.44 bitrate= 695.3kbits/s

之后我可以通过

tail -f -1 fflog.txt

文件外。但我认为,这些行没有正确转义。 Vi 向我展示了以下内容:

frame=   50 fps=0.0 q=0.0 size=       0kB time=00:00:03.20 bitrate=   0.1kbits/s
^Mframe=   73 fps= 70 q=28.0 size=     230kB time=00:00:04.05 bitrate= 465.4kbits/s
^Mframe=  100 fps= 65 q=28.0 size=     462kB time=00:00:05.44 bitrate= 695.3kbits/s
^Mframe=  125 fps= 61 q=28.0 size=     608kB time=00:00:06.48 bitrate= 767.5kbits/s

所以问题是:

    如何通过tail -n 将CRLF 转换为类似LF 的UNIX 以正确返回数据? 甚至更好:如何将 ffmpeg 结果正确地通过管道传输到 mkfifo 命名管道? 或者最笼统的说法:有没有其他方法可以更聪明地实现我的目标?

【问题讨论】:

【参考方案1】:

让我们先解决行尾问题。 ffmpeg 使用回车 ('\r') 将光标发送回行首,这样它就不会用进度消息填满终端。使用tr,修复很简单。

ffmpeg -i input.mov output.webm 2>&1 | tr '\r' '\n'

现在您应该可以分别看到每条进度线。如果我们通过管道或重定向到其他地方,事情会变得更有趣。

ffmpeg -i input.mov output.webm 2>&1 | tr '\r' '\n' | cat

请注意,输出显示为块而不是逐行。如果这对您的目的不可接受,您可以使用stdbuf 禁用tr 的输出缓冲。

ffmpeg -i input.mov video.webm 2>&1 | stdbuf -o0 tr '\r' '\n' | cat

为了从不同的 shell 读取输出,命名管道可能会起作用。但是,直到ffmpeg 完成,管道才会结束,所以tail 在那之前不会打印任何东西。您可以使用 catgrep 等其他工具读取正在进行的管道,但使用纯文件可能更容易。

# shell 1
ffmpeg -i input.mov output.webm 2>&1 | stdbuf -o0 tr '\r' '\n' > fflog.txt

# shell 2
tail -f fflog.txt

【讨论】:

以上是关于将 ffmpeg 输出通过管道传输到命名管道的主要内容,如果未能解决你的问题,请参考以下文章

使用管道将文件 i/o 传输到另一个进程

我可以将多个 ffmpeg 输出通过管道传输到不同的管道吗?

ffmpeg中的多个命名管道

OpenCV Python,从命名管道中读取视频

将 Windows 命名管道用于 IPC 的一种有效方法

如何通过命名管道传输文件描述符