Python 通过ffmpeg实现实时推流(ubuntu16+ffmpeg+nginx)

最近在做一个校园安防的项目,其中涉及到前端要实时展示监控摄像机的画面,其中画面要求是经过神经网络处理过的画面。

如果前端只要求展示原始画面,只需要在接入摄像机的时候,把视频流推送到一个服务器地址上,前端可根据地址获取视频流,

本次开发,前端借助的是一个视频流插件video.js,可拉取rtmp格式的视频流。

如果接入多路的摄像头,可以借助服务器Nginx + ffmpeg,具体的安装配置可参考:这篇博客

在这边主要讲解代码上的推流实现,也是借鉴别人的方法,结合自己的实际项目修改,其中有些地方需要注意:

import cv2
import queue
import os
import numpy as np
from threading import Thread
import datetime,_thread
import subprocess as sp
import time
# 使用线程锁,防止线程死锁
mutex = _thread.allocate_lock()
# 存图片的队列
frame_queue = queue.Queue()
# 推流的地址,前端通过这个地址拉流,主机的IP,2019是ffmpeg在nginx中设置的端口号
rtmpUrl="rtmp://192.168.40.145:2019/live/1"
# 用于推流的配置,参数比较多,可网上查询理解
command=['ffmpeg',
                '-y',
                '-f', 'rawvideo',
                '-vcodec','rawvideo',
                '-pix_fmt', 'bgr24',
                '-s', "{}x{}".format(640, 480),# 图片分辨率
                '-r', str(25.0),# 视频帧率
                '-i', '-',
                '-c:v', 'libx264',
                '-pix_fmt', 'yuv420p',
                '-preset', 'ultrafast',
                '-f', 'flv',
                rtmpUrl]

def Video():
# 调用相机拍图的函数
    vid = cv2.VideoCapture(0)
    if not vid.isOpened():
        raise IOError("Couldn't open webcam or video")
    while (vid.isOpened()):
        return_value, frame = vid.read()

        # 原始图片推入队列中
        frame_queue.put(frame)


def push_frame():
    # 推流函数
    accum_time = 0
    curr_fps = 0
    fps = "FPS: ??"
    prev_time = time()

    # 防止多线程时 command 未被设置
    while True:
        if len(command) > 0:
            # 管道配置,其中用到管道
            p = sp.Popen(command, stdin=sp.PIPE)
            break

    while True:
        if frame_queue.empty() != True:
            #从队列中取出图片
            frame = frame_queue.get()
            #curr_time = timer()
            #exec_time = curr_time - prev_time
            #prev_time = curr_time
            #accum_time = accum_time + exec_time
            #curr_fps = curr_fps + 1

            # process frame
            # 你处理图片的代码
            # 将图片从队列中取出来做处理,然后再通过管道推送到服务器上
            # 增加画面帧率
            #if accum_time > 1:
                #accum_time = accum_time - 1
                #fps = "FPS: " + str(curr_fps)
                #curr_fps = 0
          
            # write to pipe
            # 将处理后的图片通过管道推送到服务器上,image是处理后的图片
            p.stdin.write(image.tostring())

def run():
     #使用两个线程处理

    thread1 = Thread(target=Video,)
    thread1.start()
    thread2 = Thread(target=push_frame,)
    thread2.start()
if __name__ == '__main__':

    run()

确保自己已经安装了ffmpeg ,而且ffmpeg已经和nginx配置好。

在处理图像的时候,最好是将原图存到队列中,再从队列中取出来做处理,之前试过将处理后的图片存到队列中,然后直接推送,发现推送的进程占用了所有的资源,导致处理图像的进程无法执行。所以顺序不对,很容易产生资源占用的情况。

怎样查看推流是否成功,可借助vlc软件,具体可上网查一下,很多教程。

业余时候和几个朋友讨论过推流的问题,如果一帧一帧往前端推送,方法比较傻,前端小伙伴估计也不愿意,这里就考虑到代理服务器,服务器类似于一个容器,将图片以流的形式放到容器中,容器可以做到均衡负载,高访问量。当然与服务器的通信协议

要以UDP的形式,不容易丢包,ffmpeg内部就封装好了UDP协议,不需要自己额外的实现。

以上的代码实现参考:这篇博客

以上的内容如有错误,欢迎指正,不吝赐教。也欢迎各位共同讨论交流深度学习。

FFmpeg是一个开源的多媒体处理工具,可以用于录制、转码和处理音视频文件。Nginx是一个快速、可靠、高性能的Web服务器,同时也可用作反向代理服务器等。 结合FFmpegNginx,可以实现视频推流功能。具体步骤如下: 1. 配置Nginx服务器:首先需要在Nginx服务器上进行一些配置。通过编辑Nginx的配置文件,在http模块下添加rtmp模块,并设置rtmp监听的端口和应用的名称。 2. 安装FFmpeg:在推流前需要确保系统中已安装FFmpeg。如果没有安装,可以通过官方网站下载并安装对应的版本。 3. 配置FFmpeg推流:打开命令行终端,输入ffmpeg命令,并根据所需参数配置推流的源文件、输出地址、编码相关参数等。通过命令行输入ffmpeg -i 输入文件地址 -vcodec xxx -acodec xxx -f flv 输出地址 进行推流操作。 4. 启动Nginx服务器:操作系统中启动Nginx服务器,这样可以通过提供的rtmp地址进行推流。 5. 建立推流连接:在推流端使用支持RTMP协议的软件工具,如OBS Studio等,配置正确的推流地址,并开始推流。 此时,FFmpeg会将推流的音视频数据传输给Nginx服务器上的RTMP模块进行处理和转发。 总结来说,通过FFmpegNginx的配合,我们可以实现视频推流功能。FFmpeg负责编码推流的数据,而Nginx负责接收和转发数据。这种方式结合了FFmpeg灵活的音视频处理能力和Nginx优越的网络传输性能,使得推流过程更加稳定和高效。
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值