zoukankan      html  css  js  c++  java
  • day122:MoFang:OSSRS流媒体直播服务器&基于APICloud的acLive直播推流模块实现RTMP直播推流

    目录

    1.docker安装OSSRS流媒体直播服务器

    2.基于APICloud的acLive直播推流模块实现RTMP直播推流

    3.直播流管理

    1.docker安装OSSRS流媒体直播服务器

    1.OSSRS简介

    在外界开发中, 如果要实现直播功能.常用的方式有:

    1. 通过第三方接口来实现.

    可以申请阿里云,腾讯云,网易云,七牛云的直播接口,根据文档,下载集成SDK到项目中,在第三方用户平台上, 创建直播流[就是一个管道].有了直播流以后, 在客户端中集成一个推流[就是基于rtmp协议把视频摄像头采集到的信息push到直播服务器]的播放器或者第三放模块

    在另一个客户端中, 集成支持播放rtmp视频信息的播放器插件,基于这个插件向第三方直播服务器获取直播视频.

    2. 自己部署搭建直播服务器.

    nginx+nginx-rtmp-module+ffmpeg

    ossrs

    OSSRS官网:http://ossrs.net/srs.release/releases/

    官方文档:https://github.com/ossrs/srs/wiki

    SRS定位是运营级的互联网直播服务器集群,追求更好的概念完整性和最简单实现的代码。SRS提供了丰富的接入方案将RTMP流接入SRS,包括推送RTMP到SRS、推送RTSP/UDP/FLV到SRS、拉取流到SRS。 SRS还支持将接入的RTMP流进行各种变换,譬如将RTMP流转码、流截图、转发给其他服务器、转封装成HTTP-FLV流、转封装成HLS、 转封装成HDS、转封装成DASH、录制成FLV/MP4。SRS包含支大规模集群如CDN业务的关键特性,譬如RTMP多级集群、源站集群、VHOST虚拟服务器 、 无中断服务Reload、HTTP-FLV集群。此外,SRS还提供丰富的应用接口,包括HTTP回调、安全策略Security、HTTP API接口、 RTMP测速。SRS在源站和CDN集群中都得到了广泛的应用Applications。

    2.OSSRS安装

    1.创建自定义网络

    sudo docker network create --driver bridge --subnet 172.0.0.0/16 srs_network
    # sudo docker network ls

    2.创建配置文件

    # 使用阿里云镜像安装启动srs
    sudo docker run -p 1935:1935 -p 1985:1985 -p 8080:8080 --name srs registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v4.0.34
    
    # 把容器中的配置文件复制出来
    sudo mkdir -p /home/docker/srs4
    sudo docker cp -a srs:/usr/local/srs/conf /home/docker/srs4/conf
     
    # 把容器中的日志文件复制出来
    sudo docker cp -a srs:/usr/local/srs/objs /home/docker/srs4/objs
    
    # 删除容器
    sudo docker rm -f srs

    3.挂载配置文件并启动

    sudo docker run --restart=always -p 1935:1935 -p 1985:1985 -p 8080:8080 --name srs --network srs_network --ip 172.0.0.35 -v /home/docker/srs4/conf/:/usr/local/srs/conf/ -v /home/docker/srs4/objs/:/usr/local/srs/objs/ -d registry.cn-hangzhou.aliyuncs.com/ossrs/srs:v4.0.34

    通过http://127.0.0.1:8080查看srs终端信息

    通过http://127.0.0.1:1935/live/自定义直播流名称进行直播推流

    2.基于APICloud的acLive直播推流模块实现RTMP直播推流

    生成APPLoader,并安装到手机[注意:推流必须依赖于摄像头,而前面我们使用的安卓模拟器是没有办法完成摄像头调用的。

    客户端创建live_list.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body style="background-color:#fff">
      <br><br><br><br>
      <br><br><br><br>
      <button id="liver">我是主播</button>
      <button id="viewer">我是观众</button>
      <script>
        apiready = function(){
          document.getElementById("viewer").onclick = function(){
    
          }
          document.getElementById("liver").onclick = function(){
            var acLive = api.require('acLive');
            // 打开摄像头采集视频信息
            acLive.open({
                camera:0, // 1为前置摄像头, 0为后置摄像头,默认1
                rect : {  // 采集画面的位置和尺寸
                    x : 0,
                    y : 0,
                    w : 'auto',
                    h : 'auto',
                }
            },(ret, err)=>{
                alert(JSON.stringify(ret));
                // 开启美颜
                acLive.beautyFace();
                // 开始推流
                acLive.start({
                    url:'rtmp://192.168.20.251:1935/live/t1' // t1 就是流名称,可以理解为直播的房间号
                },function(ret, err){
                    alert(JSON.stringify(ret)); // 状态如果为2则表示连接成功,其他都表示不成功
                });
            });
          }
        }
      </script>
    </body>
    </html>

    3.直播流管理

    cd application/apps/
    python ../../manage.py blue -nlive 

    live/models.py,代码:

    from application.utils.models import BaseModel,db
    class LiveStream(BaseModel):
        """直播流管理"""
        __tablename__ = "mf_live_stream"
        name = db.Column(db.String(255), unique=True, comment="流名称")
        room_name = db.Column(db.String(255), default="房间名称")
        user = db.Column(db.Integer, comment="房主")
    
    class LiveRoom(BaseModel):
        """直播间"""
        __tablename__ = "mf_live_room"
        stream_id = db.Column(db.Integer, comment="直播流ID")
        user   = db.Column(db.Integer, comment="用户ID")

    settings.dev.py,代码:

        INSTALLED_APPS = [
            "application.apps.home",
            "application.apps.users",
            "application.apps.orchard",
            "application.apps.live",
        ]

    application/urls.py,代码:

    from application.utils import include
    urlpatterns = [
        include("","home.urls"),
        include("/users","users.urls"),
        include("/orchard","orchard.urls"),
        include("/live","live.urls"),
    ]

    服务端提供创建直播流的API接口,代码:

    from application import jsonrpc,db
    from message import ErrorMessage as message
    from status import APIStatus as status
    from flask_jwt_extended import jwt_required,get_jwt_identity
    from application.apps.users.models import User
    from .models import LiveStream,LiveRoom
    from datetime import datetime
    import random
    @jsonrpc.method("Live.stream")
    @jwt_required # 验证jwt
    def live_stream(room_name):
        """创建直播流"""
        current_user_id = get_jwt_identity() # get_jwt_identity 用于获取载荷中的数据
        user = User.query.get(current_user_id)
    
        # 申请创建直播流
        stream_name = "room_%06d%s%06d" % (user.id, datetime.now().strftime("%Y%m%d%H%M%S"), random.randint(100,999999))
        stream = LiveStream.query.filter(LiveStream.user==user.id).first()
        if stream is None:
            stream = LiveStream(
                name=stream_name,
                user=user.id,
                room_name=room_name
            )
            db.session.add(stream)
            db.session.commit()
        else:
            stream.room_name = room_name
        # 进入房间
        room = LiveRoom.query.filter(LiveRoom.user==user.id,LiveRoom.stream_id==stream.id).first()
        if room is None:
            room = LiveRoom(
                stream_id=stream.id,
                user=user.id
            )
            db.session.add(room)
            db.session.commit()
    
        return {
            "errno": status.CODE_OK,
            "errmsg": message.ok,
            "data":{
                "stream_name": stream_name,
                "room_name": room_name,
                "room_owner": user.id,
                "room_id": "%04d" % stream.id,
            }
        }

    前端live_list.html代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="format-detection" content="telephone=no,email=no,date=no,address=no">
      <link rel="stylesheet" href="../static/css/main.css">
      <script src="../static/js/vue.js"></script>
        <script src="../static/js/axios.js"></script>
        <script src="../static/js/main.js"></script>
        <script src="../static/js/uuid.js"></script>
        <script src="../static/js/settings.js"></script>
    </head>
    <body>
      <div class="app" id="app">
        <br><br><br><br>
        <br><br><br><br>
        <button @click="liver">创建直播间</button>
        <button @click="start_live">我要开播</button>
        <button id="viewer">我是观众</button>
      </div>
      <script>
        apiready = function(){
        init();
            new Vue({
                el:"#app",
                data(){
                    return {
              music_play:true,  //
              stream_name:"",   // 直播流名称
                        prev:{name:"",url:"",params:{}}, //
                        current:{name:"live",url:"live_list.html","params":{}}, //
                    }
                },
                methods:{
            liver(){
              var token = this.game.get("access_token") || this.game.fget("access_token");
                        this.axios.post("",{
                                "jsonrpc": "2.0",
                                "id": this.uuid(),
                                "method": "Live.stream",
                                "params": {
                                    "room_name": "爱的直播间"
                                }
                            },{
                                headers:{
                                    Authorization: "jwt " + token,
                                }
                            }).then(response=>{
                  var message = response.data.result;
                  if(parseInt(message.errno)==1005){
                    this.game.goWin("user","login.html", this.current);
                  }
                                if(parseInt(message.errno)==1000){
                    this.stream_name = message.data.stream_name;
                                }else{
                                    this.game.print(response.data);
                                }
                            }).catch(error=>{
                                // 网络等异常
                                this.game.print(error);
                            });
            },
            start_live(){
              // 开始直播
              var acLive = api.require('acLive');
              // 打开摄像头采集视频信息
              acLive.open({
                  camera:0, // 1为前置摄像头, 0为后置摄像头,默认1
                  rect : {  // 采集画面的位置和尺寸
                      x : 0,
                      y : 0,
                      w : 'auto',
                      h : 'auto',
                  }
              },(ret, err)=>{
                  alert(JSON.stringify(ret));
                  // 开启美颜
                  acLive.beautyFace();
                  // 开始推流
                  alert(this.settings.live_stream_server+this.stream_name)
                  acLive.start({
                      url: this.settings.live_stream_server+this.stream_name // t1 就是流名称,可以理解为直播的房间号
                  },function(ret, err){
                      alert(JSON.stringify(ret)); // 状态如果为2则表示连接成功,其他都表示不成功
                  });
              });
            }
                }
            })
        }
        </script>
    </body>
    </html>
  • 相关阅读:
    jdk与jre安装之后的名字
    手机用笔记本上网
    Django简易安装
    python 结巴分词
    Elasticsearch shield权限管理详解
    nginx配置初步
    linux 使用 rz 和 sz 命令
    eclipse 鲜为人知的调试技巧,你用过多少
    HDOJ 题目3555 Bomb(数位DP)
    Ubuntu1204 vim中文乱码解决方法
  • 原文地址:https://www.cnblogs.com/libolun/p/14264598.html
Copyright © 2011-2022 走看看