一、问题描述
最近在用ffmpeg+Python opencv 的方法实现采集摄像头实时视频并完成推流。实现思路是:cv2先获取摄像头视频数据,然后建立一个subprocess.popen管道去推流,然后将视频帧处理完后写入管道中完成图像处理并推流的工作。在windows下调试可以正常实现,代码如下(这个网上很多,我把我调试成功的代码也贴出来)。但是我想要在树莓派上实现,将该部分代码移植到树莓派上后就出现报错:pipe.stdin.write(img.tostring()) BrokenPipeError: [Errno 32] Broken pipe。现象是:代码刚跑起来,刚显示一两帧画面就中断了。
import cv2
import subprocess
# 视频读取对象
cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
# 推流地址
rtsp = "rtsp://192.168.1.100:554/live/test1"# 推流的服务器地址
# 设置推流的参数
command = ['ffmpeg',
'-y',
'-f', 'rawvideo',
'-vcodec', 'rawvideo',
'-pix_fmt', 'bgr24',
'-s', '640*480', # 根据输入视频尺寸填写
'-r', '30',
'-i', '-',
'-c:v', 'h264',
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-f', 'rtsp',
rtsp]
# 创建、管理子进程
pipe = subprocess.Popen(command,shell=True, stdin=subprocess.PIPE)
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# 循环读取
num = 0
while cap.isOpened():
num = num + 1
print(num)
# 读取一帧
ret, frame = cap.read()
if frame is None:
print('read frame err!')
continue
# 显示一帧
fps = int(cap.get(cv2.CAP_PROP_FPS))
cv2.imshow("frame", frame)
print("fps:",fps)
# 按键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 读取尺寸、推流
img = cv2.resize(frame, size)
pipe.stdin.write(img.tobytes())
# 关闭窗口
cv2.destroyAllWindows()
# 停止读取
cap.release()
二、问题解决
1.找到问题
从别人的帖子里发现可以用pipe.poll()来检查当前popen的工作状态,如果然后0,表示进程正常结束,返回1表示进程sleep挂起,返回2,表示子进程不存在,返回-15表示进程被kill,返回None,表示进程正在在运行。我print之后发现,返回了1,所以预估应该是,在树莓派上和windows上的popen创建方法有差别,在树莓派这里popen刚开始工作就被挂起了,终于找到解决办法。
2.解决办法
尝试了一下,将创建popen的shell = True 改为 shell = False就可以了。
将如下代码,
pipe = subprocess.Popen(command,shell=True, stdin=subprocess.PIPE)
改为文章来源:https://www.toymoban.com/news/detail-608111.html
pipe = subprocess.Popen(command,shell=False, stdin=subprocess.PIPE)
即可文章来源地址https://www.toymoban.com/news/detail-608111.html
到了这里,关于树莓派Python+ffmpeg+opencv实现推流 并 解决报错:BrokenPipeError: [Errno 32] Broken pipe的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!