日志

day123:MoFang:直播间列表信息的前后端实现&创建房间的前后端实现

 来源    2021-01-14    1  

目录

1.服务端提供所有直播间的列表信息

2.前端显示房间列表

3.创建房间

1.服务端提供所有直播间的列表信息

1.marshmallow.py



from marshmallow_sqlalchemy import SQLAlchemyAutoSchema,auto_field
from .models import LiveStream,db
from application.apps.users.models import User
from marshmallow import post_dump
class 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

marshmallow.py

2.views.py



from .marshmallow import StreamInfoSchema
from flask import current_app
@jsonrpc.method("Live.stream.list")
@jwt_required # 验证jwt
def list_stream():
    # 验证登陆用户信息
    current_user_id = get_jwt_identity() # 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请求,读取当前srs中所有的直播流和客户端列表
    import requests,re,json
    stream_response = requests.get(current_app.config["SRS_HTTP_API"]+"streams/")
    client_response = requests.get(current_app.config["SRS_HTTP_API"]+"clients/")
    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)
    
    # 在循环中匹配所有的客户端对应的总人数和当前推流用户的IP地址
    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
    }

views.py

2.前端显示房间列表

1.房间列表页面初始化:live_list.html

把上面的客户端live_list.html,修改成live.html,并新建live_list.html,代码:



<!DOCTYPE html>
<html>
<head>
    <title>好友列表</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta charset="utf-8">
    <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 setting">
        <div class="bg">
      <img src="../static/images/rooms_bg.png">
    </div>
        <img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
        <div class="add_friend_btn" @click="add_room">
            <img src="../static/images/add_room.png" alt="">
        </div>
    <div class="friends_list room_list">
            <div class="item" v-for="room in rooms">
                <div class="avatar">
                    <img class="user_avatar" :src="room.avatar" alt="">
                </div>
                <div class="info">
                    <p class="username">{{room.name}}</p>
                    <p class="fruit">人数:{{room.num}}</p>
                </div>
                <div class="behavior pick">直播</div>
                <div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
            </div>
        </div>
    </div>
    <script>
    apiready = function(){
        init();
        new Vue({
            el:"#app",
            data(){
                return {
          rooms:[{"avatar":"../static/images/avatar.png",name:"房间名称",num:5}],
                    prev:{name:"",url:"",params:{}},
                    current:{name:"live",url:"live_list.html",params:{}},
                }
            },
      created(){

      },
            methods:{
        add_room(){

        },
        goto_home(){
          // 退出当前页面
          this.game.outFrame("live","live_list.html", this.current);
        },
            }
        });
    }
    </script>
</body>
</html>

房间列表页面初始化:live_list.html

2.房间列表页面CSS样式

.room_list{
  position: absolute;
  top: 18rem;
}

3.前端获取后端传过来的直播流列表:get_room_list

获取服务端的直播流列表, live_list代码:



<!DOCTYPE html>
<html>
<head>
    <title>房间列表</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta charset="utf-8">
    <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 user setting">
        <div class="bg">
      <img src="../static/images/rooms_bg.png">
    </div>
        <img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
        <div class="add_friend_btn" @click="add_room">
            <img src="../static/images/add_room.png" alt="">
        </div>
    <div class="friends_list room_list">
            <div class="item" v-for="room in rooms">
                <div class="avatar">
                    <img class="user_avatar" :src="room.user && settings.static_url+room.user.avatar" alt="">
                </div>
                <div class="info">
                    <p class="username">{{room.room_name}}</p>
                    <p class="fruit">人数:{{room.clients_number}}</p>
                </div>
                <div class="behavior pick" v-if="room.status">直播</div>
                <div class="goto" @click="goto_live(room.id,room.name)"><img src="../static/images/arrow1.png" alt=""></div>
            </div>
        </div>
    </div>
    <script>
    apiready = function(){
        init();
        new Vue({
            el:"#app",
            data(){
                return {
          rooms:[], // 房间列表
                    prev:{name:"",url:"",params:{}},
                    current:{name:"live",url:"live_list.html",params:{}},
                }
            },
      created(){
        this.get_room_list();
      },
            methods:{
        get_room_list(){
          var token = this.game.get("access_token") || this.game.fget("access_token");
          this.axios.post("",{
            "jsonrpc": "2.0",
            "id": this.uuid(),
            "method": "Live.stream.list",
            "params": {}
          },{
            headers:{
              Authorization: "jwt " + token,
            }
          }).then(response=>{
            if(parseInt(response.data.result.errno)==1000){
              this.rooms = response.data.result.stream_list;
            }else{
                this.game.print(response.data.result.errmsg);
            }
          }).catch(error=>{
            // 网络等异常
            this.game.print(error);
          });
        },
        goto_live(room_id,stream_name){
          // 进入房间
          var pageParam = {
            name: this.current.name,
            url: this.current.url,
            room_id: room_id,
            stream_name: stream_name
          }
          this.game.goFrame("room","live.html",pageParam);
        },
        add_room(){
          
        },
        goto_home(){
          // 退出当前页面
          this.game.outWin("live");
        },
            }
        });
    }
    </script>
</body>
</html>

前端获取后端传过来的直播流列表

3.创建房间

1.创建房间页面初始化:add_room.html

当用户点击创建房间时,会让用户输入房间名和房间密码

当用户输入后点击确定,会向后端接口发送请求,将用户输入的房间名和房间密码传递给后端

创建房间, add_room.html, 代码:



<!DOCTYPE html>
<html>
<head>
    <title>创建房间</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta charset="utf-8">
    <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 frame avatar update_password">
    <div class="box">
      <p class="title">创建房间</p>
      <img class="close" @click="close_frame" src="../static/images/close_btn1.png" alt="">
      <div class="content">
                <input class="password" type="text" v-model="name" placeholder="房间名称....">
                <input class="password password2" type="password" v-model="password" placeholder="房间密码....">
      </div>
      <img @click="add_room_submit" class="btn" src="../static/images/yes.png" alt="">
    </div>
    </div>
    <script>
    apiready = function(){
        init();
        new Vue({
            el:"#app",
            data(){
                return {
                    name:"",
                    password:"",
                    prev:{name:"",url:"",params:{}},
                    current:{name:"add_room",url:"add_room.html",params:{}},
                }
            },
            methods:{
        close_frame(){
          this.game.outFrame("add_room");
        },
        add_room_submit(){
                    // 提交数据
          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: this.name,
                            password: this.password
                        }
          },{
            headers:{
              Authorization: "jwt " + token,
            }
          }).then(response=>{
            if(parseInt(response.data.result.errno)==1000){
              this.rooms = response.data.result.stream_list;
            }else{
                this.game.print(response.data.result.errmsg);
            }
          }).catch(error=>{
            // 网络等异常
            this.game.print(error);
          });
        },
            }
        });
    }
    </script>
</body>
</html>

创建房间页面初始化:add_room.html

2.在直播流数据表中增加房间密码字段

服务端接口增加房间密码字段,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="未命名",comment="房间名称")
    room_password = db.Column(db.String(255), default="", comment="房间密码")
    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")

3.后端修改创建房间接口,新增验证密码功能

服务端创建房间接口, 新增密码字段并验证密码才可以进入房间

用户输入房间名和房间密码后,前端向后端发起请求,将输入内容提交给后端

后端接收到房间名和房间密码后,做如下几件事:

1.创建直播流:,mysql中存放:用户id/房间名/房间密码/直播流号

2.创建房间:mysql中存放:用户id/直播流号

live/views.py, 代码:



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,password):
    """创建直播流"""
    current_user_id = get_jwt_identity() # 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,
        }
    # 申请创建直播流
    stream = LiveStream.query.filter(LiveStream.user==user.id).first()
    if stream is None:
        stream_name = "room_%06d%s%06d" % (
        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,
            room_password=password
        )
        db.session.add(stream)
        db.session.commit()
    else:
        stream.room_name = room_name
        stream.room_password = password
        db.session.commit()

    # 进入房间
    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,
        }
    }

from .marshmallow import StreamInfoSchema
from flask import current_app
@jsonrpc.method("Live.stream.list")
@jwt_required # 验证jwt
def list_stream():
    """房间列表"""
    current_user_id = get_jwt_identity() # 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
    }

服务端提供创建房间接口

4.前端判断房间是否存在密码,如存在密码必须正确输入密码才可进入房间

客户端中判定当房间存在密码时, 用户必须输入密码成功以后才可以进入房间, live_list.html代码:



<!DOCTYPE html>
<html>
<head>
    <title>房间列表</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta charset="utf-8">
    <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 user setting">
        <div class="bg">
      <img src="../static/images/rooms_bg.png">
    </div>
        <img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
        <div class="add_friend_btn" @click="add_room">
            <img src="../static/images/add_room.png" alt="">
        </div>
    <div class="friends_list room_list">
            <div class="item" v-for="room in rooms" @click="goto_live(room.id,room.name,room.room_password)">
                <div class="avatar">
                    <img class="user_avatar" :src="room.user && settings.static_url+room.user.avatar" alt="">
                </div>
                <div class="info">
                    <p class="username">{{room.room_name}}</p>
                    <p class="fruit">人数:{{room.clients_number}}</p>
                </div>
                <div class="behavior pick" v-if="room.status">直播</div>
                <div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
            </div>
        </div>
    </div>
    <script>
    apiready = function(){
        init();
        new Vue({
            el:"#app",
            data(){
                return {
          rooms:[], // 房间列表
                    prev:{name:"",url:"",params:{}},
                    current:{name:"live",url:"live_list.html",params:{}},
                }
            },
      created(){
        this.get_room_list();
      },
            methods:{
        get_room_list(){
          var token = this.game.get("access_token") || this.game.fget("access_token");
          this.axios.post("",{
            "jsonrpc": "2.0",
            "id": this.uuid(),
            "method": "Live.stream.list",
            "params": {}
          },{
            headers:{
              Authorization: "jwt " + token,
            }
          }).then(response=>{
            if(parseInt(response.data.result.errno)==1000){
              this.rooms = response.data.result.stream_list;
            }else{
                this.game.print(response.data.result.errmsg);
            }
          }).catch(error=>{
            // 网络等异常
            this.game.print(error);
          });
        },
        goto_live(room_id,stream_name,room_password){
          // 验证密码
          if(room_password != null){
            api.prompt({
                title:"请输入房间密码!",
                buttons: ['确定', '取消'],
            }, (ret, err)=>{
                if( ret.text == room_password ){
                    this.goto_room(room_id,stream_name);
                }else {
                  alert("密码错误!");
                }
            });
          }else{
            this.goto_room(room_id,stream_name);
          }
        },
        goto_room(room_id,stream_name){
          // 进入房间
          var pageParam = {
            name: this.current.name,
            url: this.current.url,
            room_id: room_id,
            stream_name: stream_name
          }
          this.game.goFrame("room","live.html",pageParam);
        },
        add_room(){
          this.game.goFrame("add_room","add_room.html",this.current,null,{
              type:"push",
              subType:"from_top",
              duration:300
          });

          api.addEventListener({
              name: 'add_room_success'
          }, (ret, err)=>{
              if( ret ){
                   this.game.print("创建房间成功");
              }
          });


        },
        goto_home(){
          // 退出当前页面
          this.game.outWin("live");
        },
            }
        });
    }
    </script>
</body>
</html>

前端判断房间是否存在密码,如果存在密码,必须正确输入密码才可以进入房间

5.当用户点击返回键时,关闭推流

1.live_list.html

监听当前窗口下的任意一个帧页面点击返回键(keyback)的操作

当用户点击返回键的时候,告知(sendEvent)直播间关闭直播推流



<!DOCTYPE html>
<html>
<head>
    <title>房间列表</title>
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta charset="utf-8">
    <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 user setting">
        <div class="bg">
      <img src="../static/images/rooms_bg.png">
    </div>
        <img class="back" @click="goto_home" src="../static/images/user_back.png" alt="">
        <div class="add_friend_btn" @click="add_room">
            <img src="../static/images/add_room.png" alt="">
        </div>
    <div class="friends_list room_list">
            <div class="item" v-for="room in rooms" @click="goto_live(room.id,room.name,room.room_password)">
                <div class="avatar">
                    <img class="user_avatar" :src="room.user && settings.static_url+room.user.avatar" alt="">
                </div>
                <div class="info">
                    <p class="username">{{room.room_name}}</p>
                    <p class="fruit">人数:{{room.clients_number}}</p>
                </div>
                <div class="behavior pick" v-if="room.status">直播</div>
                <div class="goto"><img src="../static/images/arrow1.png" alt=""></div>
            </div>
        </div>
    </div>
    <script>
    apiready = function(){
        init();
        new Vue({
            el:"#app",
            data(){
                return {
          rooms:[], // 房间列表
                    prev:{name:"",url:"",params:{}},
                    current:{name:"live",url:"live_list.html",params:{}},
                }
            },
      created(){
        this.get_room_list();
      },
            methods:{
        get_room_list(){
          var token = this.game.get("access_token") || this.game.fget("access_token");
          this.axios.post("",{
            "jsonrpc": "2.0",
            "id": this.uuid(),
            "method": "Live.stream.list",
            "params": {}
          },{
            headers:{
              Authorization: "jwt " + token,
            }
          }).then(response=>{
            if(parseInt(response.data.result.errno)==1000){
              this.rooms = response.data.result.stream_list;
            }else{
                this.game.print(response.data.result.errmsg);
            }
          }).catch(error=>{
            // 网络等异常
            this.game.print(error);
          });
        },
        goto_live(room_id,stream_name,room_password){
          // 验证密码
          if(room_password != null){
            api.prompt({
                title:"请输入房间密码!",
                buttons: ['确定', '取消'],
            }, (ret, err)=>{
                if( ret.text == room_password ){
                    this.goto_room(room_id,stream_name);
                }else {
                  alert("密码错误!");
                }
            });
          }else{
            this.goto_room(room_id,stream_name);
          }
        },
        goto_room(room_id,stream_name){
          // 进入房间
          var pageParam = {
            name: this.current.name,
            url: this.current.url,
            room_id: room_id,
            stream_name: stream_name
          }
                    // 当用户在当前窗口下的任何一个帧页面中点击返回键,发起全局通知
                    api.addEventListener({
                        name: 'keyback'
                    }, (ret, err)=>{
                          // 告知直播间,关闭直播推流
                            api.sendEvent({
                                name: 'live_page_out',
                                extra: {

                                }
                            });
                    });

          this.game.goFrame("room","live.html",pageParam);
        },
        add_room(){
          this.game.goFrame("add_room","add_room.html",this.current,null,{
              type:"push",
              subType:"from_top",
              duration:300
          });

          api.addEventListener({
              name: 'add_room_success'
          }, (ret, err)=>{
              if( ret ){
                  this.game.print("创建房间成功");
                  // 进入房间
                  this.goto_room(ret.value.room_id,ret.value.stream_name);
              }
          });


        },
        goto_home(){
          // 退出当前页面
          this.game.outWin("live");
        },
            }
        });
    }
    </script>
</body>
</html>

live_list.html监听退出动作,并告知直播间关闭直播推流

2.live.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">
    <br><br><br><br>
    <br><br><br><br>
    <button @click="start_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":{}}, //
                }
            },
      created(){
        this.stream_name = api.pageParam.stream_name;
      },
            methods:{
        viewer(){
          // 观看直播
          var obj = api.require('playModule');
          obj.play({
              rect:
              {   x:  0,
                  y : 0,
                  w : 360,
                  h: 1080,
              },
              fixedOn: api.frameName,
              title: 'test',
              scalingMode:2,
              url: this.settings.live_stream_server+this.stream_name,
              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 : 360,
                  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:'live_page_out'
          },()=>{
              acLive.close();
              acLive.end();
          });

        }
            }
        })
    }
    </script>
</body>
</html>

live.html监听用户是否有返回的动作,如果监听到,则关闭摄像头采集功能和直播推流
相关文章
java – 在Spring Data JPA中有没有最简单的方法来获取Table元数据(列名列表)信息?我可以在通用数据库上使用它
问答我处于这样一种情况,我想使用spring数据jpa获取所有表的列列表,我的数据库是灵活的,所以查询应该适用于所有类型的数据库.::JPA规范包含Metamodel API,允许您查询有关托管类型及其托 ...
1
如何检索CUDA 4.0内核的参数列表信息?
问答根据cuLaunchKernel function的NVidia文档,使用CUDA 3.2编译的内核包含有关其参数列表的信息.有没有办法以编程方式从CUfunction句柄中检索此信息?我需要从CU函 ...
1
GB28181流媒体web直播方案设备信息查询信令分析
日志关于LiveGBS GB28181流媒体服务器的部署详见https://www.liveqing.com/docs/download/LiveGBS.html.通过LiveGBS流媒体服务可以实现GB ...
1
[js高手之路]Node.js实现简易的爬虫-抓取博客所有文章列表信息
日志抓取目标:就是我自己的博客:http://www.cnblogs.com/ghostwu/ 需要实现的功能: 抓取博客所有的文章标题,超链接,文章摘要,发布时间 需要用到的库: node.js自带的h ...
2
自己制作一个链表用来存储列表信息,并查找当前id信息,找上一条信息,下一条信息(信息浏览的时候方便使用)
日志偶然看到某些网站在新闻详情中 ,往往是需要根据当前信息id获取到上一条信息和下一条信息的,而通常我们的做法是先获取当前信息,再获取上一条信息,再获取下一条信息,就需要发送三次查询才能够得到这些信息,一 ...
1
26.Extjs 部门列表信息展示页面
日志/** * @author sux * @time 2011-1-14 * @desc 部门信息显示 */ deptInfoGridPanel = Ext.extend(Ext.grid.Editor ...
1
海瑞菌的web前端学习直播间
日志这是本人的web前端学习直播间 一般每天晚上10点--12点为直播时间...以web前端开发为主. 若设备无法打开,请点击链接进入:https://www.huya.com/14958154 setT ...
1
javascript动态添加本地文件列表信息
日志 工作需要做了一个动态添加列表页面的小demo.用到了杂七杂八的javascript小知识. 而且并没有涉及到工作中的具体情境.有些通用,所以暂且罗列到这里.以后需要的时候可以直接拿来用. 看源码总是 ...
1
Android Launcher分析和修改12——Widget列表信息收集
日志很久没写Launcher分析的文章,最近实在太忙.今天七夕本来是想陪女朋友逛街 ,碰巧打台风呆在家里,就继续写一篇文章.今天主要是讲一下Launcher里面的Widget列表,这方面信息比较多,今天重 ...
1
C/C++ 获取目录下的文件列表信息
日志在C/C++编程时,需要获取目录下面的文件列表信息. 1.数据结构 struct dirent {     long d_ino;                 /* inode number 索引 ...
1
全栈开发——动手打造属于自己的直播间(Vue+SpringBoot+Nginx)
日志前言 大学的学习时光临近尾声,感叹时光匆匆,三年一晃而过.同学们都忙着找工作,我也在这里抛一份简历吧,欢迎各位老板和猎手诚邀.我们进入正题.直播行业是当前火热的行业,谁都想从中分得一杯羹,直播养活了一 ...
1
iOS直播Liveroom组件,游客,用户多次切换登录同一直播间,消息出现多次重复问题解决
日志byzqk 新版,加入连麦功能,直播的流程修改很多,每次登录都需要登录liveroom组件 期间遇到一个奇葩的问题,就是游客登录组件之后,切换为用户登录,出现im消息重复的问题,一开始以为是游客退出不 ...
1
MySQL 按照数据库表字段动态排序 查询列表信息
日志MySQL 按照数据库表字段动态排序 查询列表信息 背景描述 项目中数据列表分页展示的时候,前端使用的Table组件,每列自带对当前页的数据进行升序或者降序的排序. 但是客户期望:随机点击某一列的时候 ...
1
mysql查询每个直播间每个用户最早进入时间和最晚退出时间
日志myself_sql = 'select room_id,source_id user_id,min(cast(at as datetime)) joinroom,max(cast(at as dat ...
2
Windows下C编程获取软件安装列表信息
日志代码如下: #include <windows.h> #include <stdio.h> #include <iostream> #include <vec ...
2
edgedb 内部pg 数据存储的探索 (五) 运行进程列表信息
日志做为一个简单的记录,方便后期分析学习 当前包含了一个timescale 的extension 可以不用关注 信息 ps -ef |grep edgedb edgedb 10559 24858 0 4月 ...
1
python 多进程间交换信息与共享信息
日志多线程调用函数,获取其返回值,个人总结了三种方法: 一.Queue(进程队列) 构造方法:multiprocessing.Queue([maxsize]) Queue.Queue类即是一个队列的同步实 ...
50_创建动态类及查看其方法列表信息
日志package com.itcast.day3; import java.lang.reflect.Constructor; import java.lang.reflect.Method; impo ...
2
模仿qq列表信息滑动删除效果
日志这个效果的完成主要分为两个部分 自定义view作为listview的列表项 一个view里面包括 显示头像,名字,消息内容等的contentView和滑动才能显示出来的删除,置顶的右边菜单menuVi ...
1
Extjs4.2如何实现鼠标点击统计图时弹出窗口来展示统计的具体列表信息
日志var pageSize = 20;//初始化每页数据条数 var winTitle = '';//初始化窗口标题 /** *点击统计图时,弹出一个窗口,显示统计的详情列表信息, *该方法为项目中所有 ...
1