【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 | ------------------------已知一个表,它的…...
杰理之变声接口异常死机问题【篇】
void audio_voice_changer_mode_switch(u16 uuid, char *name, VOICE_CHANGER_MODE mode)...
揭秘银行核心系统C++内存池配置:如何将GC停顿从200ms压至8μs?
第一章:银行核心系统内存管理的金融级挑战银行核心系统是金融基础设施的中枢,其内存管理不仅关乎性能,更直系交易一致性、资金安全与监管合规。毫秒级延迟抖动可能引发跨行清算超时,未释放的内存泄漏可在高并发批量代发场景下数小…...
Open UI5 源代码解析之884:OverflowToolbarAssociativePopover.js
源代码仓库: https://github.com/SAP/openui5 源代码位置:src\sap.m\src\sap\m\OverflowToolbarAssociativePopover.js OverflowToolbarAssociativePopover.js 深度解析 文件定位与整体价值 OverflowToolbarAssociativePopover.js 是 sap.m 库里一个非常典型的内部增强组…...
如何快速安装和配置Pop Shell:面向初学者的完整教程
如何快速安装和配置Pop Shell:面向初学者的完整教程 【免费下载链接】shell Pop!_OS Shell 项目地址: https://gitcode.com/gh_mirrors/sh/shell Pop Shell是一款功能强大的窗口管理扩展,专为提升Linux桌面操作效率设计。本教程将带您逐步完成Pop…...
5步掌握B站高清视频下载:开源工具bilibili-downloader完整指南
5步掌握B站高清视频下载:开源工具bilibili-downloader完整指南 【免费下载链接】bilibili-downloader B站视频下载,支持下载大会员清晰度4K,持续更新中 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-downloader 还在为无法…...
如何解决WordPress国内访问难题?WP-China-Yes让网站加载速度提升300%
如何解决WordPress国内访问难题?WP-China-Yes让网站加载速度提升300% 【免费下载链接】wp-china-yes 此插件将你的WordPress接入本土生态体系之中,使之更适合国内应用环境 项目地址: https://gitcode.com/gh_mirrors/wpc/wp-china-yes 当中国用户…...
Outfit字体全面解析与实战指南:现代设计的无衬线字体解决方案
Outfit字体全面解析与实战指南:现代设计的无衬线字体解决方案 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts Outfit字体作为一款现代开源无衬线字体,以其完整的9种字重体…...
别再只写Prompt了!用Cursor Skills给你的AI助手装上‘前端设计说明书’
别再只写Prompt了!用Cursor Skills给你的AI助手装上‘前端设计说明书’ 作为一名长期与AI代码生成工具打交道的前端开发者,我深刻理解那种面对千篇一律的"AI感"设计时的无奈。每次都要花费大量时间编写冗长的Prompt,结果生成的代码…...
STM32F407实战指南(十九) 红外避障传感器模块深度调试与CubeMX源码解析
1. 红外避障传感器模块的核心原理与硬件解析 红外避障传感器本质上是一个"主动探测反射接收"的系统。发射管会持续发射38kHz的红外信号(这个频率能有效避免自然光干扰),当遇到障碍物时,红外线会被反射回来。接收管内部其…...
告别网络依赖:MedGemma 1.5医疗助手,离线环境下的智能健康顾问
告别网络依赖:MedGemma 1.5医疗助手,离线环境下的智能健康顾问 1. 医疗AI的新范式:离线智能问诊 在医疗健康领域,数据隐私和即时响应往往难以兼得。传统在线医疗咨询需要联网上传敏感健康数据,而完全离线的解决方案又…...
