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协议,不需要自己额外的实现。

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

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

  • 8
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 32
    评论
<h1>Video_Live_Stream</h1> 一个视频推流小工具 ---------- <h1>简介</h1> Video_Live_Stream是在Linux系统下基于python调用ffmpeg实现的简易推流工具,基本功能如下: * 读取播放列表,按列表顺序循环推流视频至rtmp服务器。 * 添加了`bilibili直播间弹幕模块`,可接收及发送弹幕。 * 可通过指令修改`视频播放模式`,结合弹幕模块可以直播间操作播放模式。 <h1>文件结构</h1> Video_Live_Stream * data * configure.json * <u>配置文件,存放推流参数</u> * filter_complex.txt * <u>存放滤镜参数</u> * loop_tag * <u>存放循环标识</u> * PID_keep_pipe * <u>存放keep_pipe的pid</u> * PID_push * <u>存放push进程ffmpeg进程的pid</u> * PID_send * <u>存放send进程ffmpeg进程的pid</u> * play_method * <u>存放播放模式</u> * play_skip * <u>存放指令</u> * font * msyh.ttc * <u>字体文件(修改后需要在data/filter_complex.txt同步修改)</u> * log * log.log * <u>send进程输出日志,结合py/send_check.py使用</u> * pipe * keep1 * <u>管道文件,用于维持pipe/pipe_push开启</u> * keep2 * <u>管道文件,用于维持pipe/pipe_push开启</u> * pipe_push * <u>管道文件,用于推流</u> * playlist * playlist.txt * <u>当前播放列表</u> * playlist_memory.txt * <u>用于保存播放进度</u> * ... * <u>需自行创建的播放列表</u> * ... * py * bilibili_live * aiorequest.py * <u>网络请求模块</u> * live.py * <u>直播间连接模块</u> * utils * cmd_execute.py * <u>命令执行模块</u> * file_io.py * <u>文件读写模块</u> * LinkList.py * <u>链表模块</u> * play_enum.py * <u>自定义枚举模块</u> * change.py * <u>发送指令</u> * chat.py * <u>直播间连接,弹幕接收与发送</u> * keep_pipe.py * <u>维持管道</u> * stop_pipe.py * <u>取消维持管道</u> * push.py * <u>视频推流至管道</u> * send.py * <u>管道数据推流至rtmp服务器</u> * send_check.py * <u>检查send进程运作</u> * video * xxx文件夹 * 01.mp4 * <u>视频名称</u> * 02.mp4 * ... * ... * ... * ... ---------- <h1>准备工作</h1> 首先把压缩包下载到本地然后解压,做好以下准备。 -------- 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! <项目介绍> 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 --------
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、付费专栏及课程。

余额充值