魔坊APP项目-27-直播、客户端中调整窗口大小、能播放rtmp格式直播流的播放器模块

直播

客户端中直播的界面调整和当前窗口一致
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 : 450,                  h : 1080,              }          },(ret, err)=>{  this.game.print(ret);              // 开启美颜              acLive.beautyFace();              // 开始推流              acLive.start({  url: this.settings.live_stream_server this.stream_name  // t1 就是流名称,可以理解为直播的房间号              },(ret, err)=>{  this.game.print(ret); // 状态如果为2则表示连接成功,其他都表示不成功              });          });        }        }      })    }  </script></body></html>

基于能播放rtmp格式直播流的播放器模块.

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 @click="in_live">进入直播间</button>    <button @click="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: {  in_live(){// 进入直播间          },          viewer(){// 观看直播            var obj = api.require('playModule');            obj.play({rect:                {   x: 0,                    y: 0,                    w: 450,                    h: 1080,                },                fixedOn: api.frameName,                title: 'test',                scalingMode: 2,                url: this.settings.live_stream_server 'room_',                defaultBtn: false,                enableFull : false,                isTopView : false,                isLive: true,                placeholderText: true,            }, (ret, err)=>{  this.game.print(ret);            });          },          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;                this.game.print(this.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 : 450,                  h : 1080,              }          },(ret, err)=>{  this.game.print(ret);              // 开启美颜              acLive.beautyFace();              // 开始推流              acLive.start({  url: this.settings.live_stream_server this.stream_name  // t1 就是流名称,可以理解为直播的房间号              },(ret, err)=>{  this.game.print(ret); // 状态如果为2则表示连接成功,其他都表示不成功              });          });          api.addEventListener({  name: 'keyback'          }, (ret, err)=>{acLive.close();            acLive.end();          });        }        }      })    }  </script></body></html>

服务端提供当前所有直播间的列表信息
live/marshmallow.py:,代码

from marshmallow_sqlalchemy import SQLAlchemyAutoSchema, auto_fieldfrom .models import LiveStream, dbfrom application.apps.users.models import Userfrom marshmallow import post_dumpclass StreamInfoSchema(SQLAlchemyAutoSchema):    id = auto_field()    name = auto_field()    room_name = auto_field()    user = auto_field()        class Meta:        model = LiveStream        include_fk = True        include_relationships = True        fields = ['id', 'name', 'room_name', 'user']        sql_session = db.session            @post_dump()    def user_format(self, data, **kwargs):        user = User.query.get(data['user'])        if user is None:            return data                data['user'] = {'id': user.id,            'nickname': user.nickname if user.nickname else "",            'ip': user.ip_address if user.ip_address else "",            'avatar': user.avatar if user.avatar else "",        }        return data

dev.py,

from . import InitConfigclass Config(InitConfig):    """项目开发环境下的配置"""    DEBUG = True    # 数据库    SQLALCHEMY_DATABASE_URI = "mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4"    SQLALCHEMY_ECHO = False    # redis    REDIS_URL = "redis://@127.0.0.1:6379/0"    # session存储配置    SESSION_REDIS_HOST = "127.0.0.1"    SESSION_REDIS_PORT = 6379    SESSION_REDIS_DB = 1    # 日志配置    LOG_LEVEL = "INFO"  # 日志输出到文件中的最低等级    LOG_DIR = "/logs/mofang.log"  # 日志存储目录    LOG_MAX_BYTES = 300 * 1024 * 1024   # 单个日志文件的存储上限[单位: b]    LOG_BACKPU_COUNT = 20   # 日志文件的最大备份数量    LOG_NAME = "mofang"  # 日志器名称    # 注册蓝图    INSTALLED_APPS = [        "application.apps.home",        "application.apps.users",        "application.apps.marsh",        "application.apps.orchard",        "application.apps.live",    ]    # 短信相关配置    SMS_ACCOUNT_ID = "8aaf0708754a3ef2017563ddb22d0773"  # 接口主账号    SMS_ACCOUNT_TOKEN = "0b41612bc8a8429d84b5d37f29178743"  # 认证token令牌    SMS_APP_ID = "8aaf0708754a3ef2017563ddb3110779"  # 应用ID    SMS_TEMPLATE_ID = 1  # 短信模板ID    SMS_EXPIRE_TIME = 60 * 5  # 短信有效时间,单位:秒/s    SMS_INTERVAL_TIME = 60   # 短信发送冷却时间,单位:秒/s    # jwt 相关配置    # 加密算法,默认: HS256    JWT_ALGORITHM = "HS256"    # 秘钥,默认是flask配置中的SECRET_KEY    JWT_SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw"    # token令牌有效期,单位: 秒/s,默认: datetime.timedelta(minutes=15) 或者 15 * 60    JWT_ACCESS_TOKEN_EXPIRES = 60 * 60 * 2    # refresh刷新令牌有效期,单位: 秒/s,默认:datetime.timedelta(days=30) 或者 30*24*60*60    JWT_REFRESH_TOKEN_EXPIRES = 30*24*60*60    # 设置通过哪种方式传递jwt,默认是http请求头,也可以是query_string,json,cookies    JWT_TOKEN_LOCATION = ["headers", "query_string"]    # 当通过http请求头传递jwt时,请求头参数名称设置,默认值: Authorization    JWT_HEADER_NAME = "Authorization"    # 当通过查询字符串传递jwt时,查询字符串的参数名称设置,默认:jwt    JWT_QUERY_STRING_NAME = 'token'    # 当通过http请求头传递jwt时,令牌的前缀。    # 默认值为 "Bearer",例如:Authorization: Bearer <JWT>    JWT_HEADER_TYPE = "jwt"    # 防水墙验证码    CAPTCHA_GATEWAY = "https://ssl.captcha.qq.com/ticket/verify"    CAPTCHA_APP_ID = "2041284967"    CAPTCHA_APP_SECRET_KEY = "0FrDthTnnU8vG-jSwz7DOAA**"    # mongoDB配置信息    MONGO_URI = 'mongodb://127.0.0.1:27017/mofang'    # 用户默认头像    DEFAULT_AVATAR = '54270a03-3587-4638-9156-b1f479efc958.jpeg'    # 服务端带外提供的url地址    # SERVER_URL = "http://127.0.0.1:5000"    # socketio    CORS_ALLOWED_ORIGINS = '*'    ASYNC_MODE = None    HOST = '0.0.0.0'    PORT = 5000    # 支付宝配置信息    ALIPAY_APP_ID = '2016110100783756'    ALIPAY_SIGN_TYPE = 'RSA2'    # ALIPAY_NOTIFY_URL = 'https://example.com/notify'    ALIPAY_NOTIFY_URL = "http://127.0.0.1:5000/alipay/notify"    ALIPAY_SANDBOX = True    # ossrs 服务端    SRS_HTTP_API = "http://127.0.0.1:1985/api/v1/"

live/views.py,代码:

from application import jsonrpc, dbfrom message import ErrorMessage as messagefrom status import APIStatus as statusfrom flask_jwt_extended import jwt_required, get_jwt_identityfrom application.apps.users.models import Userfrom .models import LiveStream, LiveRoomfrom datetime import datetimeimport random@jsonrpc.method('Live.stream')@jwt_requireddef live_stream(room_name):    """创建直播流"""    current_user_id = get_jwt_identity()    user = User.query.get(current_user_id)    if user is None:        return {'errno': status.CODE_NO_USER,            'errmsg': message.user_not_exists,            'data': {}        }    # 申请创建直播流    stream = LiveStream.query.filter(LiveStream.user == user.id).first()    if stream is None:        stream_name = 'room_d%sd' % (        user.id, datetime.now().strftime('%Y%m%d%H%M%S'), random.randint(100, 999999))        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': 'd' % stream.id        }    }from .marshmallow import StreamInfoSchemafrom flask import current_app@jsonrpc.method('Live.stream.list')@jwt_requireddef list_stream():    current_user_id = get_jwt_identity()    user = User.query.get(current_user_id)    if user is None:        return {'errno': status.CODE_NO_USER,            'errmsg': message.user_not_exists,            'data': {}        }    stream_list = LiveStream.query.filter(LiveStream.status == True, LiveStream.is_deleted == False).all()    sis = StreamInfoSchema()    data_list = sis.dump(stream_list, many=True)    # 使用requests发送get请求    import requests    stream_response = requests.get(current_app.config['SRS_HTTP_API'] 'streams/')    client_response = requests.get(current_app.config['SRS_HTTP_API'] 'clients/')    import re, json    stream_text = re.sub(r'[^\{\}\/\,0-9a-zA-Z\"\'\:\[\]\._]', "", stream_response.text)    client_text = re.sub(r'[^\{\}\/\,0-9a-zA-Z\"\:\[\]\._]', "", client_response.text)    stream_dict = json.loads(stream_text)    client_dict = json.loads(client_text)    for data in data_list:        data['status'] = False        for stream in stream_dict['streams']:            if data['name'] == stream['name']:                data['status'] = stream['publish']['active']                break        data['clients_number'] = 0        for client in client_dict['clients']:            if data['name'] == client['url'].split('/')[-1]:                data['clients_number']  = 1            if client['publish'] and '/live/'   data['name'] == client['url']:                data['user']['ip'] = client['ip']    return {'errno': status.CODE_OK,        'errmsg': message.ok,        'stream_list': data_list    }

来源:https://www.icode9.com/content-4-821051.html

(0)

相关推荐