python-3.x - 管道到ffmpeg时如何在python3中使用stdout.write?

标签 python-3.x opencv ffmpeg stdout v4l2loopback

我正在从事的这个项目的主要目标是使用 python 脚本获取任何网络摄像头素材,使用 opencv 对其进行编辑,然后使用 ffmpeg 将编辑后的视频帧从 v4l2loopback 传输到虚拟网络摄像头。这是我在 python 2.7 上完全按照我想要的方式运行的示例代码:

import cv2
import subprocess as sp
import sys

cap = cv2.VideoCapture(1)

cv2.namedWindow('result', cv2.WINDOW_AUTOSIZE)

while True:
    ret, frame = cap.read()
    cv2.imshow('result', frame)

    sys.stdout.write(frame.tostring())

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

然后运行它

python pySample.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - -vf format=yuv420p -f v4l2 /dev/video17

但是,我希望它可以与 python3 而不是 2.7 一起使用,并且我找到了一种让它工作的方法,我将“sys.stdout ...”行替换为

sys.stdout.buffer.write(frame.tobytes())

这很好用,除了它只能以 14 fps 运行,而 2.7 代码可​​以以 30 fps 运行。我有点不知如何解决这个问题/这个问题到底是什么。如果有帮助,我将在树莓派上运行它。非常感谢!

最佳答案

管道到ffmpeg时如何在python3中使用stdout.write?
因为您的问题的标题是“如何在 python3 中使用 stdout.write 在管道到 ffmpeg 时?”,我将首先回答这个问题:

sys.stdout.buffer.write(data)
这就是你的做法。
你已经知道了(因为我已经从你的问题中得到了答案),所以我想这不是你真正要问的。
所以你真正的问题似乎是:
如何快速写入标准输出?
但是,这意味着您认为写入标准输出很慢。为什么? (很可能是因为您更改的唯一行涉及写入标准输出)。
让我们检查一下(使用分析器),您的 python 脚本在哪里花时间做事:
python3 -m cProfile -o pySample.prof pySample.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - -vf format=yuv420p -f v4l2 /dev/video17
这将创建一个 pySample.prof包含所有调用信息的文件。我们可以检查它:
import pstats
pstats.Stats("pySample.prof").sort_stats(pstats.SortKey.TIME).print_sorted(5)
这将为我们提供运行脚本时最耗时的 5 个函数。
对我来说,这返回:
Mon Nov 16 14:40:40 2020    pySample.prof

         70698 function calls (68335 primitive calls) in 49.782 seconds

   Ordered by: internal time
   List reduced from 881 to 5 due to restriction <5>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      490   40.614    0.083   40.614    0.083 {method 'read' of 'cv2.VideoCapture' objects}
      490    3.813    0.008    3.813    0.008 {method 'write' of '_io.BufferedWriter' objects}
      490    2.334    0.005    2.334    0.005 {waitKey}
      490    1.238    0.003    1.238    0.003 {method 'tobytes' of 'numpy.ndarray' objects}
        1    0.913    0.913   49.783   49.783 pySample.py:1(<module>)
现在这很有趣。
它基本上告诉我们,python 花了很多时间从视频设备读取数据,而只花很少的时间将其写入输出(并将其转换为字节)。
所以你的问题应该是:如何使用 OpenCV 加快视频抓取速度。
不幸的是,我不能回答那个;-)

关于python-3.x - 管道到ffmpeg时如何在python3中使用stdout.write?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64849040/

相关文章:

ffmpeg - 在 fluent-ffmpeg 中,如何包含多个视频过滤器?

regex - python 正则表达式不使用\b 进行计算

ffmpeg - 在具有少量帧的 H.264 原始流中添加当前时间作为时间戳

python - 我的程序使用了大量内存,我该怎么办?

c++ - OpenCV 相机初始化失败

opencv - OpenCV 中的曲线拟合

c++ - 运行 TrainCascade.exe 时出错

ffmpeg - 将 MOV 文件转换为 MP4

python - SPSS 中如何确定数字和字符串变量?

python - 如何修改此代码以用于多个列表?