python-3.x - How to use stdout.write in python3 when piping to ffmpeg?
问题描述
My main goal for this project I'm working on is to use a python script to get any webcam footage, edit it with opencv, and then pipe the edited video frames with ffmpeg to a dummy webcam from v4l2loopback. Here's the sample code I made that runs exactly as I want to on 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()
and then run it with
python pySample.py | ffmpeg -f rawvideo -pixel_format bgr24 -video_size 640x480 -framerate 30 -i - -vf format=yuv420p -f v4l2 /dev/video17
However, I want it to work with python3 instead of 2.7, and I found a way to make it work where I replace the "sys.stdout..." line with
sys.stdout.buffer.write(frame.tobytes())
This works well, except that it only runs at 14 fps while the 2.7 code could run at 30. I'm kind of at a loss as to how to fix this issue/ what this issue exactly is. I'm running this on a raspberry pi if that helps. Thanks so much!
解决方案
管道到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 加快视频抓取速度。
不幸的是,我不能回答那个;-)
推荐阅读
- c# - 查找表困境
- python - 使用 python 编写 Unicode 章程时出错
- php - 405 方法不允许 - CodeIgniter Rest-server
- jquery - 单击一个单元格会触发该行中每个单元格的“on change”事件
- python - 同等风险贡献投资组合 scipy 优化不起作用
- typescript - 是否可以根据输入在注册表类上键入动态属性?
- c# - 版本 ASP.Net Core
- kotlin - RxJava flatMap 与 toList
- java - Spring Roo 项目。项目构建错误:未能执行目标
- jenkins - 通过 FTP 问题发布 - 詹金斯