使用python将opencv图像通过管道传输到ffmpeg
Posted
技术标签:
【中文标题】使用python将opencv图像通过管道传输到ffmpeg【英文标题】:Pipe opencv images to ffmpeg using python 【发布时间】:2016-03-14 01:40:32 【问题描述】:如何将 openCV 图像通过管道传输到 ffmpeg(将 ffmpeg 作为子进程运行)? (我正在使用 spyder/anaconda)
我正在从视频文件中读取帧并对每一帧进行一些处理。
import cv2
cap = cv2.VideoCapture(self.avi_path)
img = cap.read()
gray = cv2.cvtColor(img[1], cv2.COLOR_BGR2GRAY)
bgDiv=gray/vidMed #background division
然后,为了将处理后的帧传输到 ffmpeg,我在一个相关问题中找到了这个命令:
sys.stdout.write( bgDiv.tostring() )
接下来,我尝试将 ffmpeg 作为子进程运行:
cmd='ffmpeg.exe -f rawvideo -pix_fmt gray -s 2048x2048 -r 30 -i - -an -f avi -r 30 foo.avi'
sp.call(cmd,shell=True)
(这也来自提到的帖子) 但是,这会使我的 IPython 控制台充满神秘的象形文字,然后使其崩溃。有什么建议吗?
最后,我想输出 4 个流并让 ffmpeg 并行编码这 4 个流。
【问题讨论】:
您是否有理由不想使用 OpenCV VideoWriter 界面来写出您的视频?我不认为你可以一次输出 4 个流。 我希望这样可以更快地保存视频。我注意到我上面使用 VideoWriter 的 openCV 读写示例所花费的时间大约是相同输入视频的纯 ffmpeg 编码的两倍(当然,ffmpeg 编码不包括背景分割 - 这就是我尝试使用 openCV 的原因第一名)。我希望使用命名管道... 【参考方案1】:我曾经遇到过类似的问题。 I opened an issue on Github,原来它可能是平台问题。
与您的问题相关,您也可以将 OpenCV 图像通过管道传输到 FFMPEG。这是一个示例代码:
# This script copies the video frame by frame
import cv2
import subprocess as sp
input_file = 'input_file_name.mp4'
output_file = 'output_file_name.mp4'
cap = cv2.VideoCapture(input_file)
ret, frame = cap.read()
height, width, ch = frame.shape
ffmpeg = 'FFMPEG'
dimension = 'x'.format(width, height)
f_format = 'bgr24' # remember OpenCV uses bgr format
fps = str(cap.get(cv2.CAP_PROP_FPS))
command = [ffmpeg,
'-y',
'-f', 'rawvideo',
'-vcodec','rawvideo',
'-s', dimension,
'-pix_fmt', 'bgr24',
'-r', fps,
'-i', '-',
'-an',
'-vcodec', 'mpeg4',
'-b:v', '5000k',
output_file ]
proc = sp.Popen(command, stdin=sp.PIPE, stderr=sp.PIPE)
while True:
ret, frame = cap.read()
if not ret:
break
proc.stdin.write(frame.tostring())
cap.release()
proc.stdin.close()
proc.stderr.close()
proc.wait()
【讨论】:
我收到一个错误:pipe.proc.stdin.write(frame.tostring()) AttributeError: 'Popen' object has no attribute 'proc 当我将您的代码更改为pipe.stdin.write(frame.tostring())
时,我收到另一个错误:pipe.stdin.write(frame.tostring()) IOError: [Errno 22] Invalid argumen
这是 python 2.7 代码。你的python是什么版本的?
我已经尝试过这些更改。使用此代码,我得到:IOError: [Errno 22] Invalid argument
.
@jlarsch 是的,你是对的。 ffmpeg 命令出错,现在修复。我刚刚在我的机器上测试了这段代码,它工作得很好!【参考方案2】:
我有点晚了,但是我强大的VidGear Python 库使用其WriteGear API's Compression Mode 可以在任何平台上自动将 OpenCV 帧流水线化到 FFmpeg 的过程。 OP,您可以按如下方式实现您的答案:
# import libraries
from vidgear.gears import WriteGear
import cv2
output_params = "-s":"2048x2048", "-r":30 #define FFmpeg tweak parameters for writer
stream = cv2.VideoCapture(0) #Open live webcam video stream on first index(i.e. 0) device
writer = WriteGear(output_filename = 'Output.mp4', compression_mode = True, logging = True, **output_params) #Define writer with output filename 'Output.mp4'
# infinite loop
while True:
(grabbed, frame) = stream.read()
# read frames
# check if frame empty
if not is grabbed:
#if True break the infinite loop
break
# do something with frame here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# write a modified frame to writer
writer.write(gray)
# Show output window
cv2.imshow("Output Frame", frame)
key = cv2.waitKey(1) & 0xFF
# check for 'q' key-press
if key == ord("q"):
#if 'q' key-pressed break out
break
cv2.destroyAllWindows()
# close output window
stream.release()
# safely close video stream
writer.close()
# safely close writer
来源:https://abhitronix.github.io/vidgear/latest/gears/writegear/compression/usage/#using-compression-mode-with-opencv
您可以查看VidGear Docs 了解更多高级应用程序和功能。
希望有帮助!
【讨论】:
再晚一点... op 正朝着相反的方向发展。您的 api 可以将 cv 输入发送到 Youtube 直播吗? WriteGear 用法示例? @dbmitch 谢谢,答案已更新。您可以直接使用 FFmpeg 将 cv 输入发送到 Youtube 直播吗?如果是,那么 WriteGear 可以做到,如果不是,那么答案是否定的。 好的 - 我会试一试 - 但如果我能做到,我会从 WriteGear 获得什么 轻松灵活。 一个很好的例子会更好——WriteGear 需要一个输出文件名——你将如何将它发送到流?您的 github 上没有示例。您可以将 ffmpeg 命令与 cv2 流一起使用吗?以上是关于使用python将opencv图像通过管道传输到ffmpeg的主要内容,如果未能解决你的问题,请参考以下文章
Python OpenCV 图像到字节字符串以进行 json 传输
从 python 中的 opencv 写入 Gstreamer 管道