简介
需求:需要本地搭建一个RTMP推流服务器,然后在Python中把本地一个视频文件以RTMP视频流推出去。
关于搭建RTMP视频流服务器,可参考之前文章:
Windows搭建RTMP视频流服务器_rtmp服务器 install windows-CSDN博客
详细步骤
启动本地RTMP流服务器
进入到nginx_1.7.11.3目录下,打开cmd窗口,输入:
nginx.exe -c conf\nginx-win.conf
Python代码中推流
附上测试代码
import cv2
# subprocess 模块允许我们启动一个新进程,并连接到它们的输入/输出/错误管道,从而获取返回值。
import subprocess
# 测试 ffmpeg 推流 rtmp格式 报错 BrokenPipeError: [Errno 32] Broken pipe,原因是rtmp地址写错了,要严格与conf文件对应
# 搭配本地rtmp流媒体服务器
# 视频读取对象
camera_path = 'test.mp4'
cap = cv2.VideoCapture(camera_path)
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 推流地址
rtmp = "rtmp://127.0.0.1:1935/live/test" # 推流的服务器地址
# 设置推流的参数
command = ['ffmpeg',
'-y',
'-f', 'rawvideo',
'-vcodec', 'rawvideo',
'-pix_fmt', 'bgr24',
'-s', "{}x{}".format(width, height),
'-r', str(fps),
'-i', '-',
#'-stream_loop','-1',
'-c:v', 'libx264',
'-pix_fmt', 'yuv420p',
'-preset', 'ultrafast',
'-f', 'flv',
rtmp]
# 创建、管理子进程
pipe = subprocess.Popen(command, shell=False, stdin=subprocess.PIPE)
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# 循环读取
while cap.isOpened():
# 读取一帧
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)
# 按键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 读取尺寸、推流
img = cv2.resize(frame, size)
#print('piped.poll:', pipe.poll()) # 0--正常结束 1--sleep 2--子进程不存在 -15--kill None--在运行
pipe.stdin.write(img.tobytes())
# 关闭窗口
cv2.destroyAllWindows()
# 停止读取
cap.release()
pipe.terminate()
遇到的问题
最开始一直报BrokenPipeError: [Errno 32] Broken pipe的错误,百度了很久,查了监听的1935端口正常,没找到原因,后来在文心一言中,输入全部报错信息,它给出一串提示,帮助我找到了原因,再次感谢AI,感谢文心一言。下面是文心一言给的回答:
上面回答有一条引起了我的注意,他说“确保RTMP URL和流密钥正确无误”,我之前推流的rtmp地址只保证了ip和端口号是Nginx配置的,后面拼了个stream,长这样:
检查了一下Nginx配置文件中,配的名称为live:
后面地址改成下面这个地址就可以了!还可以在live后面再拼接自己指定的名称,也是可以的。
rtmp = "rtmp://127.0.0.1:1935/live"
rtmp = "rtmp://127.0.0.1:1935/live/test"