nginx + nginx-rtmp-module搭建直播流服务器实现推流实时直播功能
业务需求
最近公司在做养老相关的业务,现在需要子女从小程序端对家里的老人通过家庭终端交互屏进行实时看护。
解决方案
第三方的一些现成的服务:腾讯音视频通话、直播功能; 阿里的音视频通信;两者都挺好的,但是需要收费因此放弃决定自己搭建一套直播流服务;
先看效果(自己服务器配置低有延迟、放到公司服务器上很流畅、清楚)
使用工具
Nginx、Nginx-Rtmp-Module
下载地址
Nginx:https://nginx.org/en/download.html
Nginx-Rtmp-Module:https://github.com/arut/nginx-rtmp-module
软件安装
1、下载Nginx
wget https://nginx.org/download/nginx-1.21.6.tar.gz
2、将压缩包移到需要的安装目录下
mv nginx-1.21.6.tar.gz /usr/local
3、下载Nginx-Rtmp-Module
git clone https://github.com/arut/nginx-rtmp-module.git
4、将文件移到需要安装目录下
mv nginx-rtmp-module /usr/local
5、进入目录
cd /usr/local
6、解压Nginx压缩包
tar -zxvf nginx-1.21.6.tar.gz
7、进入Nginx目录
cd nginx-1.21.6
8、配置
./configure --prefix=/usr/local/nginx --add-module=../nginx-rtmp-module --with-http_ssl_module
9、安装
make && make install
10、配置 nginx.conf 文件(/usr/local/nginx/conf下)
#user nobody;
# multiple workers works !
worker_processes 2;
#pid logs/nginx.pid;
events {
worker_connections 8192;
}
rtmp {
server {
listen 1935;
chunk_size 4000;
application live {
live on;
record all;
record_path /tmp/av;
record_max_size 1K;
record_unique on;
allow publish all;
deny publish all;
allow play all;
}
}
}
http {
include mime.types;
default_type application/octet-stream;
sendfile off;
server_names_hash_bucket_size 128;
client_body_timeout 10;
client_header_timeout 10;
keepalive_timeout 30;
send_timeout 10;
keepalive_requests 10;
#gzip on;
server {
listen 8080;
server_name localhost;
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
}
location /stat.xsl {
root nginx-rtmp-module/;
}
location /control {
rtmp_control all;
}
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
11、启动Nginx
cd /usr/local/nginx/sbin
./nginx -t
./nginx -s reload
启动时可能会包错:nginx: [error] invalid PID number "" in "/usr/local/nginx/logs/nginx.pid"
解决:
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
12、测试(注意打开服务器8080和1935端口安全组)
访问服务器外网 IP:8080
Java编码实现直播推流、拉流
1、新建SpringBoot项目 pom.xml 引入所需的jar包
<!--直播相关依赖-->
<!--javacv-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/opencv-platform -->
<!--opencv-->
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv-platform</artifactId>
<version>4.0.1-1.4.4</version>
</dependency>
2、新建直播推流实现类
package com.honyar.iot.vedio.pushandpullimpl;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.IplImage;
import javax.swing.*;
public class PushStream {
/**
* 直播推流实现
*/
public void getRecordPush(String outputPath, int v_rs) throws Exception, org.bytedeco.javacv.FrameRecorder.Exception, InterruptedException {
//创建采集器
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0); //本地摄像头默认为0
//开启采集器
try {
grabber.start();
} catch (Exception e) {
try {
grabber.restart(); //一次重启尝试
} catch (Exception e2) {
throw e;
}
}
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); //转换器
Frame grabframe = grabber.grab(); //获取一帧
IplImage grabbedImage = null;
if (grabframe != null) {
grabbedImage = converter.convert(grabframe); //将这一帧转换为IplImage
}
//创建录制器
FrameRecorder recorder;
recorder = FrameRecorder.createDefault(outputPath, 1280, 720); //输出路径,画面高,画面宽
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //设置编码格式
recorder.setFormat("flv");
recorder.setFrameRate(v_rs);
recorder.setGopSize(v_rs);
//开启录制器
try {
recorder.start();
} catch (java.lang.Exception e) {
try {
if (recorder != null) { //尝试重启录制器
recorder.stop();
recorder.start();
}
} catch (java.lang.Exception e1) {
e.printStackTrace();
}
}
//直播效果展示窗口
CanvasFrame frame = new CanvasFrame("主播-菜鸡-德华", CanvasFrame.getDefaultGamma() / grabber.getGamma());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
//推流
while (frame.isVisible() && (grabframe = grabber.grab()) != null) {
frame.showImage(grabframe); //展示直播效果
grabbedImage = converter.convert(grabframe);
Frame rotatedFrame = converter.convert(grabbedImage);
if (rotatedFrame != null) {
recorder.record(rotatedFrame);
}
Thread.sleep(50); //50毫秒/帧
}
}
}
3、新建直播推流启动类
package com.honyar.iot.vedio.start;
import com.honyar.iot.vedio.pushandpullimpl.PushStream;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
/**
* 直播推流--启动
*/
@SpringBootApplication
@Configuration
public class PushApplication {
public static void main(String[] args) throws Exception {
//设置rtmp服务器推流地址(写你自己服务器外网地址)
String outputPath = "rtmp://xxx.xx.xxx.xx:1935/live/address";
PushStream recordPush = new PushStream();
recordPush.getRecordPush(outputPath, 25);
}
}
4、新建直播拉流实现类
package com.honyar.iot.vedio.pushandpullimpl;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.IplImage;
import javax.swing.*;
public class PushStream {
/**
* 直播推流实现
*/
public void getRecordPush(String outputPath, int v_rs) throws Exception, org.bytedeco.javacv.FrameRecorder.Exception, InterruptedException {
//创建采集器
OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0); //本地摄像头默认为0
//开启采集器
try {
grabber.start();
} catch (Exception e) {
try {
grabber.restart(); //一次重启尝试
} catch (Exception e2) {
throw e;
}
}
OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage(); //转换器
Frame grabframe = grabber.grab(); //获取一帧
IplImage grabbedImage = null;
if (grabframe != null) {
grabbedImage = converter.convert(grabframe); //将这一帧转换为IplImage
}
//创建录制器
FrameRecorder recorder;
recorder = FrameRecorder.createDefault(outputPath, 1280, 720); //输出路径,画面高,画面宽
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //设置编码格式
recorder.setFormat("flv");
recorder.setFrameRate(v_rs);
recorder.setGopSize(v_rs);
//开启录制器
try {
recorder.start();
} catch (java.lang.Exception e) {
try {
if (recorder != null) { //尝试重启录制器
recorder.stop();
recorder.start();
}
} catch (java.lang.Exception e1) {
e.printStackTrace();
}
}
//直播效果展示窗口
CanvasFrame frame = new CanvasFrame("主播-菜鸡-德华", CanvasFrame.getDefaultGamma() / grabber.getGamma());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
//推流
while (frame.isVisible() && (grabframe = grabber.grab()) != null) {
frame.showImage(grabframe); //展示直播效果
grabbedImage = converter.convert(grabframe);
Frame rotatedFrame = converter.convert(grabbedImage);
if (rotatedFrame != null) {
recorder.record(rotatedFrame);
}
Thread.sleep(50); //50毫秒/帧
}
}
}
5、新建直播拉流启动类(可以多建几个模拟多个客户端)
package com.honyar.iot.vedio.start;
import com.honyar.iot.vedio.pushandpullimpl.PullStream;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
/**
* 直播拉流--启动
*/
@SpringBootApplication
@Configuration
public class PullApplication1 {
public static void main(String[] args) throws Exception {
//rtmp服务器拉流地址(自己服务器外网地址)
String inputPath = "rtmp://xxx.xx.xxx.xx/live/address";
PullStream pullStream = new PullStream();
pullStream.getPullStream(inputPath);
}
}
6、测试
nginx + nginx-rtmp-module搭建直播流服务器实现推流实时直播功能的更多相关文章
- 搭建rtmp直播流服务之1:使用nginx搭建rtmp直播流服务器(nginx-rtmp模块的安装以及rtmp直播流配置)
欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) 一.方案简要 首先通过对开发方案的仔细研究(实时监控.流媒体.直播流方案的数据源-->协议转换-->服务器--&g ...
- 极速搭建RTMP直播流服务器+webapp (vue) 简单实现直播效果
在尝试使用webRTC实现webapp直播失败后,转移思路开始另外寻找可行的解决方案.在网页上尝试使用webRTC实现视频的直播与看直播,在谷歌浏览器以及safari浏览器上测试是可行的.但是基于基座 ...
- 使用 nginx 和 rtmp 插件搭建视频直播和点播服务器
使用 nginx 和 rtmp 模块 ,可以很容易地搭建一个视频直播和点播服务器出来. 首先,看一下最经典的参考文献: How to set up your own private RTMP serv ...
- 搭建RTMP直播流服务器
最近项目比较紧张,所以没什么时间写博客,正好这几天没什么事,赶紧记录下自己最近所学. 环境配置 服务器选用 服务器我选择的是小鸟云 ,原因很简单,他的个人用户有3个月免费使用时间. 服务器环境 Win ...
- 利用docker搭建RTMP直播流服务器实现直播
一.rtmp服务器搭建 环境: centos 7.* 1.先安装docker(省略) 2.下载docker容器 docker pull alfg/nginx-rtmp 3.运行容器(记得打开防火墙端口 ...
- 利用Docker挂载Nginx-rtmp(服务器直播流分发)+FFmpeg(推流)+Vue.js结合Video.js(播放器流播放)来实现实时网络直播
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_75 众所周知,在视频直播领域,有不同的商家提供各种的商业解决方案,其中比较靠谱的服务商有阿里云直播,腾讯云直播,以及又拍云和网易云 ...
- nginx搭建mp4流服务器
流媒体服务器 流媒体指以流方式在网络中传送音频.视频和多媒体文件的媒体形式.相对于下载后观看的网络播放形式而言,流媒体的典型特征是把连续的音频和视频信息压缩后放到网络服务器上,用户边下载边观看,而不必 ...
- Nginx和Squid配合搭建的Web服务器前端系统
这个架构是目前我个人觉得比较稳妥并且最方便的架构,易于多数人接受: 前端的lvs和squid,按照安装方法,把epoll打开,配置文件照搬,基本上问题不多. 这个架构和app_squid架构的区别,也 ...
- Linux----CentOS-7搭建免流服务器
本次实验采用腾讯云服务器:https://cloud.tencent.com/ 大学生身份的可以看看有没有什么活动购买 其他身份的78一个月 关于腾讯云服务器的使用可以看看腾讯云的使用手册 本博客涉及 ...
随机推荐
- idea在新窗口中打开
IntelliJ IDEA 2018.1.4 x64版本同时打开多个窗口可以进行如下设置,找到file--Settings...,然后会弹出下面的窗口:然后注意红框里的勾选项,最后确定Apply,OK ...
- fiber核心(react 16)?
旧: 浏览器渲染引擎单线程, 计算DOM树时锁住整个线程, 所有行为同步发生, 有效率问题, 期间react会一直占用浏览器主线程,如果组件层级比较深,相应的堆栈也会很深,长时间占用浏览器主线程, 任 ...
- Dubbo 的整体架构设计有哪些分层?
接口服务层(Service):该层与业务逻辑相关,根据 provider 和 consumer 的 业务设计对应的接口和实现 配置层(Config):对外配置接口,以 ServiceConfig 和 ...
- Kafka新建的分区会在哪个目录下创建?
在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录,这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘上用于提高读写性 ...
- AQS分析笔记
1 介绍 AQS: AbstractQueuedSynchronizer,即队列同步器.是构建锁或者其他同步组件的基础框架.它维护了一个volatile int state(代表共享资源)和一个FIF ...
- Spring配置文件?
Spring配置文件是个XML 文件,这个文件包含了类信息,描述了如何配置它们,以及如何相互调用.
- spring-boot-learning 缓存之redis
什么是BSD协议: BSD是"Berkeley Software Distribution"的缩写,意思是"伯克利软件发行版". BSD开源协议是一个给于使用者 ...
- C++“拷贝构造函数”和“等号重载”有什么区别?
CTypeA(const CTypeB& b)CTypeA& operator=(const CTypeB& b)一直没弄懂这两个有什么区别.只知道,重载了=号,下面复制的时候 ...
- kali Linux 渗透测试 | ARP 欺骗
目录 ARP 欺骗及其原理 ARP 欺骗实施步骤 必备工具安装 nmap 工具 dsniff 工具 driftnet 工具 ettercap 工具 ARP 欺骗测试 ARP 断网攻击 ARP 欺骗(不 ...
- Nuxt.js的踩坑指南(常见问题汇总)
本文会不定期更新在nuxt.js中遇到的问题进行汇总.转发请注明出处,尊重作者,谢谢! 强烈推荐作者文档版踩坑指南,点击跳转踩坑指南 在Nuxt的官方文档中,中文文档和英文文档都存在着不小的差异. 1 ...