【Ubuntu 上搭建 Nginx-RTMP 服务】
本章目录:
- 环境
- 1. 安装依赖
- 2. 创建 Nginx 编译目录
- 3. 下载 Nginx 和 Nginx-RTMP-Module
- 4. 编译 Nginx 并添加 RTMP 模块
- 5. 验证 Nginx 安装成功
- 6. 配置环境变量
- 7. 修改 Nginx 配置文件
- 8. 启动 Nginx 服务
- 查看 Nginx 是否启动成功
- 查看端口监听状态
- 8. 常见问题及解决方法
- 1. 缺少 `zlib` 库
- 2. 找不到 `openssl` 库
- 3. Nginx 端口冲突
- 9. 测试推流与播放
- 必要资源下载:
- 推流命令示例
- 服务端Ubuntu中推流:
- 客户端Windows中使用ffplay命令拉流:
- 播放效果如下:
- 10. 使用C++ 和FFmpeg库实现相同RTMP效果:
- 目录结构如下
- main.cpp源码如下,FFmpeg实现RTMP:
- cmake代码如下:
- 构建和执行步骤:
- 其它
- Nginx相关源码库的官网链接:
环境
- 服务端系统:Ubuntu
- 播放器:Windows 下使用
ffplay
命令
1. 安装依赖
在 Ubuntu 系统中,执行以下命令安装必要的依赖项:
sudo apt-get install build-essential libpcre3 libpcre3-dev libssl-dev
2. 创建 Nginx 编译目录
$ mkdir my_nginx_rtmp
$ cd my_nginx_rtmp/
$ pwd
/home/togevision/wzt/my_nginx_rtmp
3. 下载 Nginx 和 Nginx-RTMP-Module
wget http://nginx.org/download/nginx-1.21.6.tar.gz
wget https://github.com/arut/nginx-rtmp-module/archive/master.zip# 解压压缩包
tar -xf nginx-1.21.6.tar.gz
unzip master.zip
4. 编译 Nginx 并添加 RTMP 模块
进入解压后的 Nginx 源码目录,编译 Nginx,并添加 RTMP 模块:
cd nginx-1.21.6/
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
make -j4 && sudo make install
成功输出示例:
checking for C compiler ... found
...
creating objs/Makefile
Configuration summary+ using system PCRE library+ using system OpenSSL library+ RTMP module added
...
5. 验证 Nginx 安装成功
togevision@TG:~/wzt/my_nginx_rtmp$ /usr/local/nginx/sbin/nginx -v
nginx version: nginx/1.21.6
6. 配置环境变量
将 Nginx 添加到环境变量中:
sudo vi ~/.bashrc
在文件末尾添加:
export PATH=$PATH:/usr/local/nginx/sbin/
执行以下命令生效:
source ~/.bashrc
7. 修改 Nginx 配置文件
编辑 Nginx 配置文件:
sudo vim /usr/local/nginx/conf/nginx.conf
在文件末尾添加以下内容以启用 RTMP 模块:
rtmp {server {listen 1935;chunk_size 4096;application live {live on;record off;}}
}
8. 启动 Nginx 服务
nginx
启动后无提示,但可以通过以下命令确认状态
查看 Nginx 是否启动成功
ps -ef | grep nginx | grep -v grep
输出示例:
rog 1312637 2257 0 15:51 ? 00:00:00 nginx: master process nginx
rog 1314761 1312637 0 16:01 ? 00:00:06 nginx: worker process
查看端口监听状态
netstat -anp | grep nginx
输出示例:
tcp 0 0 0.0.0.0:1935 0.0.0.0:* LISTEN 1312637/nginx: mast
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1312637/nginx: mast
- 端口 80:HTTP 服务默认监听端口
- 端口 1935:RTMP 服务默认监听端口
8. 常见问题及解决方法
1. 缺少 zlib
库
执行以下命令安装:
sudo apt-get install zlib1g-dev
输出示例:
Reading package lists... Done
...
2. 找不到 openssl
库
在 ~/.bashrc
文件中添加 OpenSSL 库位置:
export LD_LIBRARY_PATH=/home/rog/anaconda3/lib:$LD_LIBRARY_PATH
source ~/.bashrc
3. Nginx 端口冲突
如果出现以下错误:
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
修改 /usr/local/nginx/conf/nginx.conf
中的端口号为 1024 以上的端口,例如 8090
。
9. 测试推流与播放
必要资源下载:
测试视频下载
Linux下的x86版本 ffmpeg现成库下载
推流命令示例
服务端Ubuntu中推流:
ffmpeg -re -i ../res/video.mp4 -c copy -f flv rtmp://192.168.194.129:1935/live/1
客户端Windows中使用ffplay命令拉流:
ffplay.exe rtmp://192.168.194.129:1935/live/1
播放效果如下:
10. 使用C++ 和FFmpeg库实现相同RTMP效果:
目录结构如下
togevision@TG:~/wzt/av/rtmp_demo$ tree -L 2
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── Makefile
│ └── rtmp_demo
├── CMakeLists.txt
├── ffmpeg
│ ├── include
│ ├── lib
│ └── Makefile
├── ffmpeg_x86
│ ├── inc
│ └── lib
├── main.cpp
└── res└── video.mp49 directories, 8 files
main.cpp源码如下,FFmpeg实现RTMP:
#include <iostream>
#include <chrono>
#include <thread>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/time.h>
}// ffmpeg -re -i ../res/video.mp4 -c copy -f flv rtmp://192.168.194.129:1935/live/1int main() {const char *input_file = "../res/video.mp4";const char *output_url = "rtmp://192.168.194.129:1935/live/1";// 初始化网络组件avformat_network_init();AVFormatContext *input_ctx = nullptr;if (avformat_open_input(&input_ctx, input_file, nullptr, nullptr) < 0) {std::cerr << "Could not open input file." << std::endl;return -1;}if (avformat_find_stream_info(input_ctx, nullptr) < 0) {std::cerr << "Failed to retrieve input stream information." << std::endl;avformat_close_input(&input_ctx);return -1;}AVFormatContext *output_ctx = nullptr;if (avformat_alloc_output_context2(&output_ctx, nullptr, "flv", output_url) < 0) {std::cerr << "Could not create output context." << std::endl;avformat_close_input(&input_ctx);return -1;}for (unsigned int i = 0; i < input_ctx->nb_streams; i++) {AVStream *in_stream = input_ctx->streams[i];AVStream *out_stream = avformat_new_stream(output_ctx, nullptr);if (!out_stream) {std::cerr << "Failed to allocate output stream." << std::endl;avformat_close_input(&input_ctx);avformat_free_context(output_ctx);return -1;}if (avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar) < 0) {std::cerr << "Failed to copy codec parameters." << std::endl;avformat_close_input(&input_ctx);avformat_free_context(output_ctx);return -1;}out_stream->codecpar->codec_tag = 0;}if (!(output_ctx->oformat->flags & AVFMT_NOFILE)) {if (avio_open(&output_ctx->pb, output_url, AVIO_FLAG_WRITE) < 0) {std::cerr << "Could not open output URL." << std::endl;avformat_close_input(&input_ctx);avformat_free_context(output_ctx);return -1;}}if (avformat_write_header(output_ctx, nullptr) < 0) {std::cerr << "Error occurred when writing header to output." << std::endl;avformat_close_input(&input_ctx);if (!(output_ctx->oformat->flags & AVFMT_NOFILE))avio_closep(&output_ctx->pb);avformat_free_context(output_ctx);return -1;}int64_t start_time = av_gettime_relative();AVPacket pkt;while (true) {if (av_read_frame(input_ctx, &pkt) < 0)break;AVStream *in_stream = input_ctx->streams[pkt.stream_index];AVStream *out_stream = output_ctx->streams[pkt.stream_index];pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);pkt.pos = -1;// 计算每帧的发送时间int64_t pts_time = av_rescale_q(pkt.pts, out_stream->time_base, AVRational{1, AV_TIME_BASE});int64_t now_time = av_gettime_relative() - start_time;if (pts_time > now_time) {av_usleep(pts_time - now_time);}if (av_interleaved_write_frame(output_ctx, &pkt) < 0) {std::cerr << "Error writing frame." << std::endl;av_packet_unref(&pkt);break;}av_packet_unref(&pkt);}// 写入尾部信息if (av_write_trailer(output_ctx) < 0) {std::cerr << "Error occurred when writing trailer to output." << std::endl;}// 释放资源avformat_close_input(&input_ctx);if (!(output_ctx->oformat->flags & AVFMT_NOFILE))avio_closep(&output_ctx->pb);avformat_free_context(output_ctx);avformat_network_deinit();std::cout << "Streaming finished successfully!" << std::endl;return 0;
}
cmake代码如下:
cmake_minimum_required(VERSION 3.10)
project(FFmpegRTMPStreaming)# 设置C++标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)# SET(CMAKE_CXX_COMPILER "/home/togevision/toolchain/arm-AX620E-linux-uclibcgnueabihf/bin/arm-AX620E-linux-uclibcgnueabihf-g++")# 指定头文件和库文件的路径
include_directories(${CMAKE_SOURCE_DIR}/ffmpeg_x86/inc)
link_directories(${CMAKE_SOURCE_DIR}/ffmpeg_x86/lib)
# include_directories(${CMAKE_SOURCE_DIR}/ffmpeg/include)
# link_directories(${CMAKE_SOURCE_DIR}/ffmpeg/lib/arm/uclibc)# 添加可执行文件
add_executable(rtmp_demo main.cpp)# 链接FFmpeg库
target_link_libraries(rtmp_demo avformat avcodec avutil swresample)# 执行之前需要指定动态库路径:
# export LD_LIBRARY_PATH=/home/togevision/wzt/av/rtmp_demo/ffmpeg_x86/lib:$LD_LIBRARY_PATH
构建和执行步骤:
# 进入build目录,准备构建makefile
cd build/# 执行cmake
cmake ..# 执行make
make# 查看生成
ls# 指定动态库路径:
export LD_LIBRARY_PATH=/home/togevision/wzt/av/rtmp_demo/ffmpeg_x86/lib:$LD_LIBRARY_PATH# 执行生成的目标程序
./rtmp_demo # windows下使用ffplay或其它播放器播放rtmp
ffplay.exe rtmp://192.168.194.129:1935/live/1
其它
Nginx相关源码库的官网链接:
软件名称 | 下载链接 | 个人使用版本 | 描述 |
---|---|---|---|
Nginx | http://nginx.org/en/download.html | nginx-1.21.6.tar.gz | 一个高性能的HTTP和反向代理服务器。 |
Pcre | https://sourceforge.net/projects/pcre/files/pcre/8.45/ | pcre-8.45.tar.gz | 一个正则表达式库。(必须) |
Zlib | http://www.zlib.net/ | zlib-1.3.1.tar.gz | 一个开源的数据压缩库,提供了对数据的无损压缩和解压功能。(必须) |
Openssl | https://www.openssl.org/source/ | openssl-1.1.0l.tar.gz | 一个开源的加密库,提供了各种加密算法和安全协议的实现。(必须) |
相关文章:

【Ubuntu 上搭建 Nginx-RTMP 服务】
本章目录: 环境1. 安装依赖2. 创建 Nginx 编译目录3. 下载 Nginx 和 Nginx-RTMP-Module4. 编译 Nginx 并添加 RTMP 模块5. 验证 Nginx 安装成功6. 配置环境变量7. 修改 Nginx 配置文件8. 启动 Nginx 服务查看 Nginx 是否启动成功查看端口监听状态 8. 常见问题及解决方法1. 缺少…...

使用uniapp 微信小程序一些好用的插件分享
总结一下自己在开发中遇见的一问题,通过引入组件可以快速的解决 1.zxz-uni-data-select 下拉框选择器(添加下拉框检索,多选功能,多选搜索功能,自定义 下拉框插件,使用这个的原因是因为 uniui uview 组件库下拉框太…...

linux centos挂载未分配的磁盘空间
使用到的命令 lshw -class disk -short hostnamectl fdisk /dev/sdb partprobe /dev/sdb mount /dev/sdb2 /opt/fastdfs/ mkfs.ext4 /dev/sdb2 mount -t ext4 /dev/sdb2 /opt/fastdfs/...
C语言凯撒密码程序分享
把刚才编写的程序又加工了一下,变成了程序,发给大家 我用夸克网盘分享了「凯撒密码」,点击链接即可保存。打开「夸克APP」,无需下载在线播放视频,畅享原画5倍速,支持电视投屏。 链接:https://p…...

2025新年源码免费送
2025很开门很开门的源码免费传递。不需要馒头就能获取4套大开门源码。 听泉偷宝,又进来偷我源码啦👊👊👊。欢迎偷源码 🔥🔥🔥 获取免费源码以及更多源码,可以私信联系我 我们常常…...

阿里云ethereum
https://geth.ethereum.org/docs/getting-started/installing-geth#linux-and-mac git clone https://github.com/ethereum/go-ethereum.git git checkout v1.10.11 cd go-ethereum # 阿里云添加goproxy export GOPROXYhttps://mirrors.aliyun.com/goproxy/ make geth创建gene…...

子父组件传值
Angular 2 及以上版本中的父子组件通信方式 在 Angular 2 及以上版本中,父子组件通信主要通过以下几种方式实现: 一、使用Input()进行父向子通信 父组件通过属性绑定的方式将数据传递给子组件,子组件使用Input()装饰器来接收这些数据。 二…...

QT自定义工具条渐变背景颜色一例
使用样式定义: QWidget* toolbar new QWidget(this);toolbar->setObjectName("main_tool");toolbar->setStyleSheet("#main_tool{background: qlineargradient(x1:0 , y1:0 , x2:1 , y2:0,""stop:0 rgba(0,255,0, 0.2),"&q…...

2025最新Facebook广告投放常见问题:如何提高广告效果?
Facebook广告投放已成为众多品牌拓展市场、提升品牌知名度和促进销售增长的关键手段。然而经常有人提出遇到广告没人看、定位不准或者内容不吸引人这些问题。那怎么办呢?别急,下面咱们就来聊聊Facebook广告投放常见问题以及如何提高Facebook广告的效果。…...

双向导航和单向导航
目录 双向导航 单向导航 迁移数据库异常 解决办法 1.导航属性改为空 2.使用 ON DELETE NO ACTION 或 ON UPDATE NO ACTION 选择 双向导航 一对多:一个Article有多个Comment class Article {public long Id { get; set; }public string Title { get; set; }pu…...

Unity3d 基于Barracuda推理库和YOLO算法实现对象检测功能
前言 近年来,随着AI技术的发展,在游戏引擎中实现和运行机器学习模型的需求也逐渐显现。Unity3d引擎官方推出深度学习推理框架–Barracuda ,旨在帮助开发者在Unity3d中轻松地实现和运行机器学习模型,它的主要功能是支持在 Unity 中…...
Lambda离线实时分治架构深度解析与实战
一、引言 在大数据技术日新月异的今天,Lambda架构作为一种经典的数据处理模型,在应对大规模数据应用方面展现出了强大的能力。它整合了离线批处理和实时流处理,为需要同时处理批量和实时数据的应用场景提供了成熟的解决方案。本文将对Lambda…...

Spring Boot教程之五十一:Spring Boot – CrudRepository 示例
Spring Boot – CrudRepository 示例 Spring Boot 建立在 Spring 之上,包含 Spring 的所有功能。由于其快速的生产就绪环境,使开发人员能够直接专注于逻辑,而不必费力配置和设置,因此如今它正成为开发人员的最爱。Spring Boot 是…...

jenkins入门6 --拉取代码
Jenkins代码拉取 需要的插件,缺少的安装下 新建一个item,选择freestyle project 源码管理配置如下:需要添加git库地址,和登录git的用户密码 配置好后执行编译,成功后拉取的代码在工作空间里...
CAPL概述与环境搭建
CAPL概述与环境搭建 目录 CAPL概述与环境搭建1. CAPL简介与应用领域1.1 CAPL简介1.2 CAPL的应用领域 2. CANoe/CANalyzer 安装与配置2.1 CANoe/CANalyzer 简介2.2 安装CANoe/CANalyzer2.2.1 系统要求2.2.2 安装步骤 2.3 配置CANoe/CANalyzer2.3.1 配置CAN通道2.3.2 配置CAPL节点…...

Virgo:增强慢思考推理能力的多模态大语言模型
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

偃动访无穿戴动作捕捉系统:赋能多行业开启动作捕捉新篇章
在当今科技飞速发展的时代,动作捕捉技术正以前所未有的态势深入到社会发展的各个领域,成为众多行业不可或缺的重要助力。从早期的惯性动捕与光捕技术,到如今更为先进的无标记动捕技术,动作捕捉领域不断迎来革新与突破。 无标记动…...
mikro-orm 和typeorm 对比
以下是Mikro-ORM和TypeORM的详细对比: 设计理念与架构 Mikro-ORM:基于数据映射器、工作单元和身份映射模式。这种设计使得它在管理内存中实体状态方面表现优异,能够自动处理事务,当调用em.flush()时,所有计算出的更改…...

Docker入门之docker基本命令
Docker入门之docker基本命令 官方网站:https://www.docker.com/ 1. 拉取官方镜像并创建容器(以redis为例) 拉取官方镜像 docker pull redis# 如果不需要添加到自定义网络使用这个命令,如需要,直接看第二步 docker r…...
mysql的一些函数及其用法
mysql 1-来自于leetcode1517的题目 表: Users------------------------ | Column Name | Type | ------------------------ | user_id | int | | name | varchar | | mail | varchar | ------------------------已知一个表,它的…...

超声波清洗设备的清洗效果如何?
超声波清洗设备是一种常用于清洗各种物体的技术,它通过超声波振荡产生的微小气泡在液体中破裂的过程来产生高能量的冲击波,这些冲击波可以有效地去除表面和细微裂缝中的污垢、油脂、污染物和杂质。超声波清洗设备在多个领域得到广泛应用,包括…...
LLaMA-Factory的5种推理方式总结
LLaMA-Factory 作为一款开源的大语言模型微调与推理框架,提供了 5 种核心推理方式,覆盖从本地调试到生产部署的全流程需求。以下是具体方式及示例: 1. 交互式命令行推理 适用场景:快速测试模型效果或进行简单对话。 示例命令&am…...
B+树知识点总结
核心目标:减少磁盘 I/O 数据库系统(如 MySQL)的主要性能瓶颈通常在于磁盘 I/O(读取和写入数据到物理硬盘的速度远慢于内存访问)。B 树的设计核心就是最大限度地减少访问数据时所需的磁盘 I/O 次数。 一、B 树的基本结…...

Blazor-表单提交的艺术:如何优雅地实现 (下)
在上一章节中我们使用HTML的方式介绍了如何在Blazor框架下进行表单的提交,而在Blazor框架中也为我们内置了<EditForm>组件来代替原始的HTML,<form>,下面我们将对<EditForm>的用法进行讲解,并将两种表单方式进行对比&#x…...

Python----目标检测(使用YOLO 模型进行线程安全推理和流媒体源)
一、线程安全推理 在多线程环境中运行YOLO 模型需要仔细考虑,以确保线程安全。Pythons threading 模块允许您同时运行多个线程,但在这些线程中使用YOLO 模型时,需要注意一些重要的安全问题。本页将指导您创建线程安全的YOLO 模型推理。 1.1、…...

[论文阅读] 人工智能+项目管理 | 当 PMBOK 遇见 AI:传统项目管理框架的破局之路
当PMBOK遇见AI:传统项目管理框架的“AI适配指南” 论文信息 arXiv:2506.02214 Is PMBOK Guide the Right Fit for AI? Re-evaluating Project Management in the Face of Artificial Intelligence Projects Alexey Burdakov, Max Jaihyun Ahn Subjects: Software …...

Python----目标检测(《YOLOv3:AnIncrementalImprovement》和YOLO-V3的原理与网络结构)
一、《YOLOv3:AnIncrementalImprovement》 1.1、基本信息 标题:YOLOv3: An Incremental Improvement 作者:Joseph Redmon, Ali Farhadi 机构:华盛顿大学(University of Washington) 发表时间:2018年 代…...

音视频之视频压缩编码的基本原理
系列文章: 1、音视频之视频压缩技术及数字视频综述 2、音视频之视频压缩编码的基本原理 一、预测编码: 1、预测编码的基本概念: 预测法是最简单、实用的视频压缩编码方法,经过压缩编码后传输的并不是像素本身的取样值࿰…...
汇编语言综合程序设计:子程序、分支与循环深度解析
本文将通过一个完整的控制台计算器案例,深入探讨汇编语言中子程序、分支结构和循环结构的综合应用,展示模块化编程、输入输出处理和算法实现的核心技术。 一、模块化编程架构设计 1. 系统架构规划 Calculator System ├── main.asm (主程序)…...

好得睐:以品质守味、以科技筑基,传递便捷与品质
据相关数据显示,超市半成品菜是冻品区增长最快品类,再加上商超渠道作为消费者日常高频接触场景,是促进半成品菜成为冻品生鲜消费领域的关键一环。好得睐作为半成品菜领军品牌,其商超渠道布局是连接消费者与品质生活的重要桥梁。商…...