魔坊APP项目-28-直播、显示房间列表

直播

显示房间列表

把上面的客户端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" id="app">
		<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>

main.css,代码:

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

获取服务端的直播流列表, 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" id="app">
		<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>

创建房间, 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" id="app">
    <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=>{
            var message = response.data.result;
            if(parseInt(message.errno)==1000){
              this.game.outFrame('add_room');
              api.sendEvent({
                  name: 'add_room_success',
                  extra: {
                    stream_name:message.data.stream_name,
                    room_id:message.data.room_id,
                  }
              });

            }else{
                this.game.print(response.data.result.errmsg);
            }
          }).catch(error=>{
            // 网络等异常
            this.game.print(error);
          });
        },
			}
		});
	}
	</script>
</body>
</html>

服务端接口创建房间密码, 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')

终端执行,命令:

python manage.py db migrate -m "add live password"
python manage.py db upgrade

服务端创建房间接口, 新增密码字段并验证密码才可以进入房间,
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
def live_stream(room_name, password):
    """创建直播流"""
    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,
        }

    # 申请创建直播流
    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
def 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
    }

live/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()
    room_password = auto_field()

    class Meta:
        model = LiveStream
        include_fk = True
        include_relationships = True
        fields = ['id', 'name', 'room_name', 'user', 'room_password']
        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

客户端中判定当房间存在密码时, 用户必须输入密码成功以后才可以进入房间, 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" id="app">
		<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>

当用户点击返回键退出当前窗口时, 关闭推流
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" id="app">
		<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(){
        setInterval(()=>{
          this.get_room_list();
        },3000);
      },
			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.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="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: 450,
                    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 : 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: 'live_page_out'
          }, ()=>{
            acLive.close();
            acLive.end();
          });

        }

        }
      })


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

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
def live_stream(room_name, password):
    """创建直播流"""
    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,
        }

    # 申请创建直播流
    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
def 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)
    outline_list = []
    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']
                
        if data['status'] == False:
            outline_list.append(data)
            
    for item in outline_list:
        data_list.remove(item)
    return {
        'errno': status.CODE_OK,
        'errmsg': message.ok,
        'stream_list': data_list
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值