当前位置:   article > 正文

树莓派Python+ffmpeg+opencv实现推流解决报错:BrokenPipeError: [Errno 32] Broken pipe_broken pipe error when using ffmpeg stream camera

broken pipe error when using ffmpeg stream camera video

树莓派Python报错解决pipe.stdin.write img.tostring BrokenPipeError: [Errno 32] Broken pipe


一、问题描述

  最近在用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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

二、问题解决

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)
  • 1

  改为

pipe = subprocess.Popen(command,shell=False, stdin=subprocess.PIPE)
  • 1

  即可

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/850857
推荐阅读
相关标签
  

闽ICP备14008679号