ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

nginx + nginx-rtmp-module搭建直播流服务器实现推流实时直播功能

2022-04-28 00:35:30  阅读:208  来源: 互联网

标签:Exception module nginx 直播 rtmp import org recorder


业务需求

最近公司在做养老相关的业务,现在需要子女从小程序端对家里的老人通过家庭终端交互屏进行实时看护。

解决方案

第三方的一些现成的服务:腾讯音视频通话、直播功能; 阿里的音视频通信;两者都挺好的,但是需要收费因此放弃决定自己搭建一套直播流服务;

先看效果(自己服务器配置低有延迟、放到公司服务器上很流畅、清楚)

image

使用工具

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
image

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、测试
image

标签:Exception,module,nginx,直播,rtmp,import,org,recorder
来源: https://www.cnblogs.com/Tom-shushu/p/16201229.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有