如何将一个程序 (ffmpeg) 的输出传递给 python 脚本?

How to pass the output of one program (ffmpeg) to python script?

我想做的是:

ffmpeg -i udp://224.10.10.10:15004 -qscale:v 2 sttest%04d.jpg

然后将其输出图像路径传递给 python 脚本,该脚本单独接收图像并对其进行操作,因为 ffmpeg 是 运行(最终我将使用ffmpy 调用 ffmpeg 而不是使用命令行工具,但为了现在的测试目的,我从这里开始。

我想这样做的一种方法是每次我处理图像时查看 ffmpeg 输出的目录,看看是否有新的,然后将其加载到 python (使用 OpenCV)——如果没有要处理的新图像,则等待一定的时间间隔。

但是有没有更好的方法,比如将图像的路径直接发送到某种队列,然后 python 脚本可以一个一个地处理?

由于 FFmpeg 没有流式传输的输出 "file names I've generated",您唯一的选择是使用您拥有的文件系统。

根据您的 OS,可能有一种方法可以在目录中有新文件被触及时得到通知。我不知道这是否适用于 linux、windows、os x,但值得研究一下。

事实上,这看起来很简单,您不必通过外部调用 ffmpeg 来完成它。 ffmpeg 基本上是 libavcodec 的用户前端,一个用于对视频、音频等进行解码和编码的库

因此,您可能只想在应用程序中使用 libavcodec。我实际上认为,如果使用实际的媒体流架构,您尝试做的事情会容易得多。 GStreamer 可能是您的首选工具,您可以从 python 直接使用它,但我没有体验过它有多简单。

您的目标可能应该是直接在 python 程序中获取帧,而无需绕道将它们写入磁盘。

如果您不想使用 libav* 或 [=14],简单的 MJPEG(Motion JPEG)转换器可能是最简单的方法,只需通过管道传输到程序的 stdin =].

对于任何好奇的人,这是我的解决方案。它正在使用 OpenCV。我问这个问题的时候并没有意识到这一点,但是 OpenCV 有一些在幕后使用 ffmpeg 的功能。由于我的程序已经在使用 OpenCV,我只是在传递问题时提到了这一点(因为我认为它不重要),因此使用 OpenCV 中内置的功能并不是很难做我想做的事。这是代码:

cap = cv2.VideoCapture("video.mpg")
count = 0
frame_q = queue.Queue()

while cap.grab():
    success, frame = cap.read()

    if count % 5 == 0 and success:
            frame_alpha = np.insert(frame, 3, 255, axis=2)
            frame_q.put(frame_alpha)

    count += 1

如您所见,我只是将每五帧放入 Queue 帧中。核心就是这三行:

cap = cv2.VideoCapture("video.mpg")
while cap.grab():
    success, frame = cap.read()

第一行打开捕获,while 子句使用 cap.grab() 检查是否还有更多帧(如果有下一帧则返回 True)然后我将该帧读入numpy 数组使用 cap.read()success 是一个布尔值,表示操作是否成功。后来我在 frame 中添加了一个 alpha 通道并将其放入 frame_q.

然后,程序的另一个线程 gets 帧超出 Queue。这样,我根本不必处理文件系统——正如 Marcus 所说,我将它们直接放入程序中。

注意:要使cv2.VideoCapture()工作,opencv_ffmpeg.dll需要在系统路径或[=29安装的根目录中=] 你正在使用。您可能需要将其重命名为 opencv_ffmpegXYZ.dll,其中 XYZ 是 OpenCV 版本号减去小数点。所以对我来说,它是 opencv_ffmpeg330.dll 因为我的版本是 3.3.0。它也可能在 x64 系统上被称为 opencv_ffmpeg330_64.dll

opencv_ffmpeg.dll 的位置取决于您安装 OpenCV 的方式,我只是在 OpenCV 目录中搜索 opencv_ffmpeg 并查看它出现的位置。在将它复制到 Python 目录之前,请确保检查它是否已经存在。可能是这样,具体取决于您的安装方式 OpenCV.