使用 ffmpeg-python + OpenCV + 匿名管道 推流

使用OpenCV的cv2.VideoCapture(videoname)获取关于视频的对象,使用该对象的.read()返回帧,本例使用cv2.cvtColor()对每帧进行颜色变换,注释的部分是原样输出。

把读出的每一帧,写到匿名管道中,同时ffmpeg-python通过该管道输入视频,视频为rawvideo格式,所以必须指定pix_fmt和长宽信息。

为了调试方便,rtmp地址写的是本地,可以使用ffplay或者VLC等工具接收串流。

最后,别忘了用.release()释放视频对象

# coding=utf-8
import cv2
import ffmpeg

# 本地调试地址
# ffplay -f flv http://127.0.0.1:8081


def file2rtmp():
    # RTMP推流地址dst, 用opencv把各种处理后的流推到dst
    rtmp_url = 'http://127.0.0.1:8081'
    cap = cv2.VideoCapture(r"../video/mp4.mp4")
    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))

    process_stdin = (
        ffmpeg
        #.input('pipe:', format='rawvideo', pix_fmt='bgr24', s="{}x{}".format(width, height))
        .input('pipe:', format='rawvideo', pix_fmt='gray', s="{}x{}".format(width, height))
        .output(
                rtmp_url,
                vcodec='libx264',
                acodec='aac',
                #crf=20, preset='slower', movflags='faststart', pix_fmt='yuv420p',
                listen=1, # enables HTTP server
                f='flv')
        .overwrite_output()
        .run_async(cmd=["ffmpeg", "-re"],pipe_stdin=True)
    )
    
    while cap.isOpened():
        ret, frame = cap.read()
        # 如果正确读取帧,ret为True
        if not ret:
            print("Can't receive frame. Exiting ...")
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        #cv2.imshow('frame', gray)
        process_stdin.stdin.write(gray.tobytes())
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    #cv2.destroyAllWindows()
    process_stdin.stdin.close()
    process_stdin.wait()