管道传输到 ffmpeg 时如何在 python3 中使用 stdout.write?
How to use stdout.write in python3 when piping to ffmpeg?
我正在从事的这个项目的主要目标是使用 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 时只有 运行s 而 2.7 代码可以在 30 fps 运行。我有点不知道如何解决这个问题/ 这个问题究竟是什么。如果有帮助,我会 运行 在 raspberry pi 上解决这个问题。非常感谢!
当管道传输到 ffmpeg 时,如何在 python3 中使用 stdout.write?
由于您的问题标题为“当管道传输到 ffmpeg 时如何在 python3 中使用 stdout.write?”,我将首先回答:
sys.stdout.buffer.write(data)
这就是你的做法。
你已经知道了(因为我已经从你的问题中得到了答案),所以我想这不是你真正想问的。
所以你真正的问题似乎是:
如何写入标准输出快速?
然而,这意味着您认为写入 stdout 很慢。为什么? (很可能是因为您更改的唯一一行处理写入标准输出)。
让我们检查一下(使用分析器),您的 python-script 花时间做事的地方:
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 个函数。
对我来说这个 returns:
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 脚本获取任何网络摄像头素材,使用 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 时只有 运行s 而 2.7 代码可以在 30 fps 运行。我有点不知道如何解决这个问题/ 这个问题究竟是什么。如果有帮助,我会 运行 在 raspberry pi 上解决这个问题。非常感谢!
当管道传输到 ffmpeg 时,如何在 python3 中使用 stdout.write?
由于您的问题标题为“当管道传输到 ffmpeg 时如何在 python3 中使用 stdout.write?”,我将首先回答:
sys.stdout.buffer.write(data)
这就是你的做法。
你已经知道了(因为我已经从你的问题中得到了答案),所以我想这不是你真正想问的。
所以你真正的问题似乎是:
如何写入标准输出快速?
然而,这意味着您认为写入 stdout 很慢。为什么? (很可能是因为您更改的唯一一行处理写入标准输出)。
让我们检查一下(使用分析器),您的 python-script 花时间做事的地方:
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 个函数。 对我来说这个 returns:
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 加速视频抓取。
很遗憾,我无法回答 那个 ;-)