使用python读取网络视频流或者本地视频进行RTMP流的生成,并对视频源的每一帧做剪切处理

时间: 2023-07-29 admin 互联网

使用python读取网络视频流或者本地视频进行RTMP流的生成,并对视频源的每一帧做剪切处理

使用python读取网络视频流或者本地视频进行RTMP流的生成,并对视频源的每一帧做剪切处理

python读取网络视频流或者本地视频进行RTMP流的生成

想要获得RTMP推流的功能其实是可以用ffmpeg+ffserver通过命令行方式实现的,但是我为了对原视频流的帧做剪切处理,所以使用python调用ffmpeg来推流,这里只是生成推流,这是不够的,需要有一个代理服务器来接收推流并推向网络,关于代理服务器的配置请看文末的链接

以下是全部代码,需要注意以下几点:

  1. 主体是两个函数,通过两个线程调用,线程之间通过队列进行通信,读流线程将读取到的帧放入队列中,推流线程将队列中的帧取出来进行剪切处理并推流。
  2. 在处理帧的时候一定要注意将处理后的帧的fps设置为ffmpeg command中设置的width,height,不然推流会失败。 就是这一句代码:image = cv2.resize(frame[int(left_x):int(right_x)][int(left_y):int(right_y)], (width, height))
  3. 不知道为什么在队列不为空的时候会出现队列中帧对象为NoneType的问题,所以在处理的时候我加了个判断条件。如果有大佬知道原因请在评论区留言,欢迎交流。
  4. 适应项目要求我剪切帧需要的参数是从文件中读取的,使用时可换成别的方式
import subprocess as sp
import cv2
import sys
import queue
import threading

frame_queue = queue.Queue()
rtmpUrl = "rtmp://IP地址/live/test"
camera_path = 'rtmp://58.200.131.2:1935/livetv/hunantv' #这是湖南台的实时直播流

#获取摄像头参数
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))

#print(fps, width, height)

# ffmpeg command
command = ['ffmpeg',
           '-y',
           'rawvideo',
           '-vcodec', 'rawvideo',
           '-pix_fmt', 'bgr24',
           '-s', "{}x{}".format(width, height),
           '-r', str(fps),
		   '-c:v', 'libx264',
           '-pix_fmt', 'yuv420p',
           '-preset', 'ultrafast',
           '-f', 'flv',
           '-g', '5',
           rtmpUrl]
  
#读流函数           
def Video():
    vid = cv2.VideoCapture(camera_path)
    if not vid.isOpened():
        raise IOError("could't open webcamera or video")
    while(vid.isOpened()):
        ret,frame = vid.read()
        #下面注释的代码是为了防止摄像头打不开而造成断流
        #if not ret:
            #vid = cv2.VideoCapture(camera_path)
            #if not vid.isOpened():
                #raise IOError("couldn't open webcamera or video")
            #continue       
        frame_queue.put(frame)


def push_stream(left_x,left_y,right_x,right_y):
    # 管道配置
    while True:
        if len(command)>0:
            p = sp.Popen(command, stdin=sp.PIPE)
            break

    while True:
        if not frame_queue.empty():
            frame = frame_queue.get()
            if frame is not None:
                #我这里出现了frame为NoneType的情况,所以判断一下
                image = cv2.resize(frame[int(left_x):int(right_x)][int(left_y):int(right_y)], (width, height))
                p.stdin.write(image.tostring())
   
                              

def run(left_x,left_y,right_x,right_y):
    thread_video = threading.Thread(target=Video,)
    thread_push = threading.Thread(target=push_stream,args=(left_x,left_y,right_x,right_y,))
    thread_video.start()
    thread_push.start()


if __name__ == "__main__":
    with open("zoomfile.txt", "r") as f:  # 打开文件
        data = f.read()  # 读取文件
        
    zoom = data.split("_")
    left_x = zoom[0]
    left_y = zoom[1]
    right_x = zoom[2]
    right_y = zoom[3]

    with open("zoomfile.txt","w") as f:
        f.write("0")
    run(left_x,left_y,right_x,right_y)

python代码参考了以下几篇博客:
python利用ffmpeg进行rtmp推流直播
Python 通过ffmpeg实现实时推流(ubuntu16+ffmpeg+nginx)

以下三篇博客是关于nginx服务器和RTMP配置的,都很有参考价值
Ubuntu安装nginx+rtmp
利用nginx搭建RTMP视频点播、直播、HLS服务器
使用 nginx 和 rtmp 插件搭建视频直播和点播服务器