首页 > 其他分享 >手把手系列之摄像头(或者本地视频)推拉流

手把手系列之摄像头(或者本地视频)推拉流

时间:2024-07-07 13:01:12浏览次数:14  
标签:NGINX process 手把手 self nginx 推拉 usr root 摄像头

整体思路:

1、在本地端选择将摄像头(或者本地视频)流传输到网络的工具,如 ffmpeg
2、在云服务器上配置一个流媒体服务器,如 nginx 的 rtmp 模块
3、使用 ffmpeg 将摄像头(或者本地视频)流推送到云服务器,再用用支持 RTMP 的播放器(如 VLC 或使用 HTML5 视频播放器),输入 RTMP URL拉流实时监控

WINDOWS安装ffmpeg软件

1、下载 ffmpeg 官方网站 上的 Windows 版本。
2、解压下载的压缩包,将 bin 文件夹路径添加到系统环境变量的 Path 中:
3、在“系统变量”中找到并选择 Path,然后点击“编辑”。
点击“新建”并添加 ffmpeg 的 bin 文件夹路径(例如 C:\ffmpeg\bin)。
点击“确定”保存更改。
4、验证安装:
打开命令提示符并输入

ffmpeg -version

如果安装正常,会返回版本信息如下:

ffmpeg version N-116037-g539d2e989d-20240628 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 14.1.0 (crosstool-NG 1.26.0.93_a87bf7f)

###### LINUX安装NGINX软件

安装 Nginx:
sudo apt-get update
sudo apt-get install nginx
编译并安装 Nginx RTMP 模块:
sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
wget http://nginx.org/download/nginx-1.20.1.tar.gz
tar -zxvf nginx-1.20.1.tar.gz
git clone https://github.com/arut/nginx-rtmp-module.git
cd nginx-1.20.1
./configure --add-module=../nginx-rtmp-module
make
sudo make install

以上openssl会报错,可以采取:编译时禁用警告视为错误的措施
在 nginx 源代码目录中,编辑 objs/Makefile 文件,找到 -Werror 标志并删除它。可以通过以下命令来找到并编辑:

sed -i 's/-Werror//' objs/Makefile
验证 NGINX 是否包含 RTMP 模块:

/usr/local/nginx/sbin/nginx -V

/usr/local/nginx/sbin/nginx -V

如果有的话你在输出中看到 --add-module=/path/to/nginx-rtmp-module。

配置 Nginx RTMP 模块:

虽然/etc/nginx/nginx.conf是系统级的全局配置文件,但通常情况下,它由系统管理员或包管理器来管理和配置。在这种情况下,它可能会包含一些全局的NGINX设置,例如NGINX的基本配置和模块加载等。一般来说,对于单个NGINX实例的具体配置,更推荐在/usr/local/nginx/conf/nginx.conf中进行修改和管理。

worker_processes auto;

events {
    worker_connections 1024;
}

error_log /var/log/nginx/error.log;

rtmp {
    server {
        listen 1936;  # 监听RTMP流的默认端口

        application live {
            live on;  # 开启实时推流功能
            allow publish all;  # 允许所有人推流
            allow play all;     # 允许所有人播放

            # 可选的HLS(HTTP Live Streaming)配置
            hls on;
            hls_path /usr/local/nginx/html/hls;  # HLS文件存放路径
            hls_fragment 3;
            hls_playlist_length 60s;
        }
    }
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8081;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

localhost为云服务器地址, rtmp端口设置为1936,hhtp端口设置为8081.

测试 Nginx 配置
sudo /usr/local/nginx/sbin/nginx -t

如果没有语法错误,就会显示:

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
启动Nginx

手动安装编译一般的默认路径为:/usr/local/nginx/sbin/nginx

sudo /usr/local/nginx/sbin/nginx
停止 NGINX 服务

手动安装编译一般的默认路径为:/usr/local/nginx/sbin/nginx

sudo /usr/local/nginx/sbin/nginx -s stop
检查 NGINX 是否启动成功

再次使用 ps aux | grep nginx 查看 NGINX 进程是否正在运行:

ps aux | grep nginx

如果 NGINX 启动成功,您应该会看到类似以下的输出,显示多个 NGINX 进程,如下:

root        7661  0.0  0.0  17492  1040 ?        Ss   11:30   0:00 nginx: master process /usr/local/nginx/sbin/nginx
nobody      7662  0.0  0.2  18184  3632 ?        S    11:30   0:00 nginx: worker process
nobody      7663  0.0  0.2  18184  3632 ?        S    11:30   0:00 nginx: worker process
nobody      7664  0.0  0.2  17964  3700 ?        S    11:30   0:00 nginx: cache manager process
root        7825  0.0  0.1   6480  2344 pts/1    S+   11:30   0:00 grep --color=auto nginx
重新启动 NGINX

重新启动 NGINX 服务,以确保配置更改已生效:

sudo /usr/local/nginx/sbin/nginx -s reload
NGINX 服务的状态查询
sudo systemctl status nginx

如果 NGINX 正在启动中,你会看到类似以下的输出:

● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: activating (start) since Tue 2024-07-02 15:00:00 CST; 1min 30s ago
     Docs: man:nginx(8)
  Process: 1234 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 5678 (nginx)
    Tasks: 2 (limit: 4567)
   CGroup: /system.slice/nginx.service
           ├─5678 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           └─5679 nginx: worker process

Jul 02 15:00:00 localhost systemd[1]: Starting A high performance web server and a reverse proxy server...

如果 NGINX 已经启动完成,状态会显示为 Active: active (running)。如果 NGINX 正在启动过程中,则状态可能显示为 activating (start) 或类似的状态。

如果 NGINX 未能成功启动,状态可能会显示为 failed,并且会有相应的错误信息解释 NGINX 启动失败的原因。

本地视频推到云服务器

可以使用以下指令推送:

ffmpeg -re -i "C:\Users\xsy\Desktop\发包文件2\TEST VIDEO.mp4" -c:v copy -c:a aac -strict -2 -f flv rtmp://121.43.119.130:1936/live/stream_name

然后打开VLC软件–>媒体–>打开网络串流–>输入网络URL:

rtmp://121.43.119.130:1936/live/stream_name

使用简约的Python脚本:

import subprocess
import tkinter as tk
from tkinter import messagebox, filedialog

class StreamApp:
    def __init__(self, root):
        self.root = root
        self.root.title("RTMP Streamer")
        self.root.geometry("450x150")  # 设置窗口大小为450x150
        self.process = None
        
        # 设置UI
        self.create_widgets()

    def create_widgets(self):
        # 创建一个框架来容纳文件路径输入框和浏览按钮
        path_frame = tk.Frame(self.root)
        path_frame.pack(pady=10)

        # 文件路径输入框
        self.file_entry = tk.Entry(path_frame, width=50)
        self.file_entry.pack(side=tk.LEFT, padx=(0, 10))

        # 浏览按钮
        self.browse_button = tk.Button(path_frame, text="Browse", command=self.browse_file)
        self.browse_button.pack(side=tk.LEFT)

        # 开始推流按钮
        self.start_button = tk.Button(self.root, text="开始推流", command=self.start_stream)
        self.start_button.pack(pady=10)

        # 停止推流按钮
        self.stop_button = tk.Button(self.root, text="停止推流", command=self.stop_stream)
        self.stop_button.pack(pady=10)

    def browse_file(self):
        file_path = filedialog.askopenfilename(filetypes=[("MP4 files", "*.mp4"), ("All files", "*.*")])
        if file_path:
            self.file_entry.delete(0, tk.END)
            self.file_entry.insert(0, file_path)

    def start_stream(self):
        if self.process is None:
            # 获取输入的文件路径
            video_file = self.file_entry.get()
            if not video_file:
                messagebox.showerror("Error", "请先选择一个视频文件")
                return
            
            # RTMP 服务器地址
            rtmp_server_url = "rtmp://121.43.119.130:1936/live/stream"

            # ffmpeg 命令
            ffmpeg_command = [
                "ffmpeg",
                "-re",
                "-i", video_file,
                "-c:v", "copy",
                "-c:a", "aac",
                "-strict", "-2",
                "-f", "flv",
                rtmp_server_url
            ]

            try:
                # 调用 ffmpeg 命令
                self.process = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                self.root.after(100, self.read_output)
            except Exception as e:
                messagebox.showerror("Error", f"Failed to start stream: {e}")
                self.process = None

    def read_output(self):
        if self.process is not None:
            try:
                output = self.process.stderr.read(1).decode('utf-8', errors='replace')
                if output:
                    print(output, end='')
            except Exception as e:
                print(f"Error reading output: {e}")

            if self.process.poll() is None:
                self.root.after(100, self.read_output)
            else:
                self.process = None

    def stop_stream(self):
        if self.process is not None:
            self.process.terminate()
            self.process = None
            messagebox.showinfo("信息", "推流已停止")

if __name__ == "__main__":
    root = tk.Tk()
    app = StreamApp(root)
    root.mainloop()

UI界面如下:
在这里插入图片描述
VLC拉流界面如下:在这里插入图片描述

本地外接摄像头视频实时推送到云服务器

直接做一个简约的Python脚本:

import subprocess
import tkinter as tk
from tkinter import messagebox

class StreamApp:
    def __init__(self, root):
        self.root = root
        self.root.title("RTMP Streamer")
        self.root.geometry("280x150")  # 设置窗口大小为280x150
        self.process = None
        
        # 设置UI
        self.create_widgets()

    def create_widgets(self):
        # 开始推流按钮
        self.start_button = tk.Button(self.root, text="开始推流", command=self.start_stream)
        self.start_button.pack(pady=20)
        
        # 停止推流按钮
        self.stop_button = tk.Button(self.root, text="停止推流", command=self.stop_stream)
        self.stop_button.pack(pady=20)

    def start_stream(self):
        if self.process is None:
            # 摄像头设备名称
            video_device = "Logi C270 HD WebCam"
            
            # RTMP 服务器地址
            rtmp_server_url = "rtmp://121.43.119.130:1936/live/stream"

            # ffmpeg 命令
            ffmpeg_command = [
                "ffmpeg",
                "-f", "dshow", "-i", f"video={video_device}",
                "-vcodec", "libx264", "-b:v", "2000k",
                "-f", "flv", rtmp_server_url
            ]

            try:
                # 调用 ffmpeg 命令
                self.process = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                self.root.after(100, self.read_output)
            except Exception as e:
                messagebox.showerror("Error", f"Failed to start stream: {e}")
                self.process = None

    def read_output(self):
        if self.process is not None:
            try:
                output = self.process.stderr.read(1).decode('utf-8', errors='replace')
                if output:
                    print(output, end='')
            except Exception as e:
                print(f"Error reading output: {e}")
            
            if self.process.poll() is None:
                self.root.after(100, self.read_output)
            else:
                self.process = None

    def stop_stream(self):
        if self.process is not None:
            self.process.terminate()
            self.process = None
            messagebox.showinfo("信息", "推流已停止")

if __name__ == "__main__":
    root = tk.Tk()
    app = StreamApp(root)
    root.mainloop()

UI界面如下:
UI界面图
VLC拉流界面如下:
拉流截图
PS:上面只拉流了视频。加入音频一起推会出现疯狂掉帧的现象,等研究明白了,到时再开一帖

注意项

1、一定不要同时开两个ngnix,会冲突打架
2、如果是阿里云服务器,务必在安全组中允许推流占用的端口
3、允许防火墙通过

sudo ufw allow 8081/tcp
sudo ufw allow 1936/tcp

4、错误日志文件路径问题:
NGINX 在测试配置文件时,尝试打开日志文件 /var/log/nginx/error.log,但是该文件不存在,导致测试失败。解决方法是创建日志文件及其父目录,并设置正确的权限:

sudo mkdir -p /var/log/nginx
sudo touch /var/log/nginx/error.log
sudo chmod 640 /var/log/nginx/error.log
sudo chown www-data:www-data /var/log/nginx/error.log

5、检查Nginx监听端口

netstat -lntp

会返回类似如下

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:8081            0.0.0.0:*                 LISTEN      7661/nginx: master  
tcp        0      0 0.0.0.0:1936            0.0.0.0:*                 LISTEN      7661/nginx: master  
tcp        0      0 127.0.0.53:53           0.0.0.0:*                 LISTEN      775/systemd-resolve 
tcp        0      0 0.0.0.0:8888            0.0.0.0:*                 LISTEN      1198/python3        
tcp        0      0 0.0.0.0:22              0.0.0.0:*                 LISTEN      934/sshd: /usr/sbin 

6、使用 pkill 命令停止所有 NGINX 进程

sudo pkill -f nginx

7、把自己编译安装的nginx使用systemd控制
首先进入/etc/systemd/system编辑nginx.service ,添加实际安装运行路径和配置文件路径:

[Unit]
Description=NGINX
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PIDFile=/usr/local/nginx/logs/nginx.pid
PrivateTmp=true

[Install]
WantedBy=multi-user.target

8、确认 NGINX 进程状态:

ps aux | grep nginx

如果没被占用显示如下:

root       25237  0.0  0.1   6480  2452 pts/0    S+   00:23   0:00 grep --color=auto nginx

如果被占用显示如下:

root       25406  0.0  0.0  17492  1036 ?        Ss   00:25   0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
nobody     25407  0.0  0.2  18184  3656 ?        S    00:25   0:00 nginx: worker process
nobody     25408  0.0  0.2  18184  3656 ?        S    00:25   0:00 nginx: worker process
nobody     25409  0.0  0.2  17964  3688 ?        S    00:25   0:00 nginx: cache manager process
root       25571  0.0  0.1   6480  2244 pts/0    S+   00:25   0:00 grep --color=auto nginx

8、查询有没有进程占用端口:

sudo netstat -tuln | grep ':1936\|:8081'

9、确认 NGINX 服务状态:

sudo systemctl status nginx

没启动显示如下:

○ nginx.service - NGINX
     Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Thu 2024-07-04 00:53:18 CST; 6s ago
    Process: 26889 ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf (code=exited, status=0/SUCCESS)
    Process: 27374 ExecStop=/usr/local/nginx/sbin/nginx -s stop (code=exited, status=0/SUCCESS)
   Main PID: 26890 (code=exited, status=0/SUCCESS)
        CPU: 18ms

Jul 04 00:52:33 kara systemd[1]: Starting NGINX...
Jul 04 00:52:33 kara systemd[1]: Started NGINX.
Jul 04 00:53:18 kara systemd[1]: Stopping NGINX...
Jul 04 00:53:18 kara systemd[1]: nginx.service: Deactivated successfully.
Jul 04 00:53:18 kara systemd[1]: Stopped NGINX.

如果 NGINX 正在启动中,你会看到类似以下的输出:

● nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: activating (start) since Tue 2024-07-02 15:00:00 CST; 1min 30s ago
     Docs: man:nginx(8)
  Process: 1234 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
 Main PID: 5678 (nginx)
    Tasks: 2 (limit: 4567)
   CGroup: /system.slice/nginx.service
           ├─5678 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
           └─5679 nginx: worker process

启动好显示如下

● nginx.service - NGINX
     Loaded: loaded (/etc/systemd/system/nginx.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2024-07-04 00:52:33 CST; 10s ago
    Process: 26889 ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf (code=exited, status=0/SUCCESS)
   Main PID: 26890 (nginx)
      Tasks: 4 (limit: 1930)
     Memory: 3.1M
        CPU: 10ms
     CGroup: /system.slice/nginx.service
             ├─26890 "nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf"
             ├─26891 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
             ├─26892 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
             └─26893 "nginx: cache manager process" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" 

Jul 04 00:52:33 kara systemd[1]: Starting NGINX...
Jul 04 00:52:33 kara systemd[1]: Started NGINX.

10、通过 systemd 启动和关闭 NGINX 服务(如果你手去安装路径启动就无法从syetemctl关闭,需要先杀死相关进程,才能正常使用systemctl管理启动和关闭):

sudo systemctl start nginx
sudo systemctl stop nginx

标签:NGINX,process,手把手,self,nginx,推拉,usr,root,摄像头
From: https://blog.csdn.net/ywl1204246322/article/details/140139175

相关文章

  • 计算机毕业设计项目推荐:66945 同城信息网(开题答辩+程序定制+全套文案 )上万套实战教程
    摘要随着社会的发展,社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。本文以实际运用为开发背景,运用软件工程原理和开发方法,它主要是采SSM技术和mysql数据库来完成对系统的设计。整个开发过程首先对同城信息网进行需求分析,得出......
  • Qt/C++音视频开发78-获取本地摄像头支持的分辨率/帧率/格式等信息/mjpeg/yuyv/h264
    一、前言上一篇文章讲到用ffmpeg命令方式执行打印到日志输出,可以拿到本地摄像头设备信息,顺藤摸瓜,发现可以通过执行ffmpeg-fdshow-list_optionstrue-ivideo="Webcam"命令获取指定摄像头设备的分辨率帧率格式等信息,会有很多条。那为什么需要这个功能呢?现场大量应用下来,尽管......
  • 手把手教你一步一步通过AI助手生成利润表分析报告
    AI助手之利润表分析报告-操作篇以下为文字整理部分:如果要手工制作一份这样的利润分析报告大概要多久时间?从准备数据做成表格,到完成报告,至少需要1天的时间吧,特别是敲文字报告的时候,生怕把数字搞错要反复检查,耗时耗力。那么如果我们已经有一张利润表分析报表,是不是可......
  • 手把手教你解决spring boot导入swagger2版本冲突问题,刘老师教编程
    手把手教你解决springboot导入swagger2版本冲突问题本文仅为个人理解,欢迎大家批评指错首先SpringBoot3和Swagger2不兼容。在SpringBoot3中,应该使用Springdoc或其他与SpringBoot3兼容的API文档工具来替代Swagger2。Swagger2的依赖底层使用的是javax......
  • Kafka集群部署(手把手部署图文详细版)
    1.1.1部署zookpeer在node02下载并解压zookeeper软件包cd/usr/localwgethttps://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz或者:[email protected]:/home/cat/zookeeper-3.4.6.tar.gz/tmp(注意目录)mvzookeeper-3.4.6.tar.gz......
  • 手把手教你,利用机器学习模型,构建量化择时策略(附全流程代码)
    歌神演唱会人脸识别抓逃犯,阿尔法狗战胜人类围棋手,AI绘图《太空歌剧院》惊艳艺术博览会,ChatGPT一问解千愁~~~这些震撼成果的背后,都是人工智能在蓬勃发力。既然人工智能/机器学习这么厉害,在其他领域都取得了丰硕的成果和巨大的成功,那么是不是可以让计算机帮咱预测市场大盘、......
  • 复现网红阻力支撑指标RSRS,手把手教你构建大盘择时策略
    之前写过一篇利用RSRS指标做ETF轮动的文章,可能是因为回测绩效看起来还不错,其后就有不少小伙伴陆陆续续来询问,想不到还有那么多人关注,于是本期文章就想掰开了揉碎了唠唠RSRS,从数据获取、计算细节一直聊到策略构建,不藏着掖着,每一步都有对应代码。我当初关注到RSRS,是因为当时无......
  • (必看图文)Hadoop集群安装及MapReduce应用(手把手详解版)
    前言    随着大数据时代的到来,处理和分析海量数据已成为企业和科研机构不可或缺的能力。Hadoop,作为开源的分布式计算平台,因其强大的数据处理能力和良好的可扩展性,成为大数据处理领域的佼佼者。本图文教程旨在帮助读者理解Hadoop集群的安装过程,并通过MapReduce应用实例,......
  • 手把手教你如何用python写一个经典小游戏(仅需100行以内的代码)
    创作灵感小时候也就是大概十几年前的时候,智能触屏手机还未大量普及,移动网络还是2G,大部分人用的都是小灵通,里面只有几款经典的游戏,比如俄罗斯方块,贪吃蛇等。还记得以前自己玩的不亦乐乎。如今网络发展迅速,通讯设备越来越智能化,集成化,这些上世纪的经典游戏似乎早已淡忘人们的视......
  • 基于python语言的网页设计(手把手教你设计一个个人博客网站)
     总体的设计思路设计网页的思路涉及多个方面,从前端的页面结构和样式,到后端的数据处理和逻辑实现。1.确定网站的需求和功能首先要明确网站的功能需求,比如用户注册登录、博客文章发布和展示、评论系统等。2.选择技术栈选择适合的框架和工具。对于Python,常用的Web框架包括Fl......