直播

客户端中直播的界面调整和当前窗口一致
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为后置摄像头,默认1rect : {  // 采集画面的位置和尺寸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为后置摄像头,默认1rect : {  // 采集画面的位置和尺寸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_field
from .models import LiveStream, db
from application.apps.users.models import User
from marshmallow import post_dumpclass StreamInfoSchema(SQLAlchemyAutoSchema):id = auto_field()name = auto_field()room_name = auto_field()user = auto_field()class Meta:model = LiveStreaminclude_fk = Trueinclude_relationships = Truefields = ['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 datadata['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 InitConfig
class Config(InitConfig):"""项目开发环境下的配置"""DEBUG = True# 数据库SQLALCHEMY_DATABASE_URI = "mysql://mofang_user:mofang@127.0.0.1:3306/mofang?charset=utf8mb4"SQLALCHEMY_ECHO = False# redisREDIS_URL = "redis://@127.0.0.1:6379/0"# session存储配置SESSION_REDIS_HOST = "127.0.0.1"SESSION_REDIS_PORT = 6379SESSION_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"  # 应用IDSMS_TEMPLATE_ID = 1  # 短信模板IDSMS_EXPIRE_TIME = 60 * 5  # 短信有效时间,单位:秒/sSMS_INTERVAL_TIME = 60   # 短信发送冷却时间,单位:秒/s# jwt 相关配置# 加密算法,默认: HS256JWT_ALGORITHM = "HS256"# 秘钥,默认是flask配置中的SECRET_KEYJWT_SECRET_KEY = "y58Rsqzmts6VCBRHes1Sf2DHdGJaGqPMi6GYpBS4CKyCdi42KLSs9TQVTauZMLMw"# token令牌有效期,单位: 秒/s,默认: datetime.timedelta(minutes=15) 或者 15 * 60JWT_ACCESS_TOKEN_EXPIRES = 60 * 60 * 2# refresh刷新令牌有效期,单位: 秒/s,默认:datetime.timedelta(days=30) 或者 30*24*60*60JWT_REFRESH_TOKEN_EXPIRES = 30*24*60*60# 设置通过哪种方式传递jwt,默认是http请求头,也可以是query_string,json,cookiesJWT_TOKEN_LOCATION = ["headers", "query_string"]# 当通过http请求头传递jwt时,请求头参数名称设置,默认值: AuthorizationJWT_HEADER_NAME = "Authorization"# 当通过查询字符串传递jwt时,查询字符串的参数名称设置,默认:jwtJWT_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"# socketioCORS_ALLOWED_ORIGINS = '*'ASYNC_MODE = NoneHOST = '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, 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):"""创建直播流"""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_%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)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}}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 requestsstream_response = requests.get(current_app.config['SRS_HTTP_API']+'streams/')client_response = requests.get(current_app.config['SRS_HTTP_API']+'clients/')import re, jsonstream_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'] = Falsefor stream in stream_dict['streams']:if data['name'] == stream['name']:data['status'] = stream['publish']['active']breakdata['clients_number'] = 0for client in client_dict['clients']:if data['name'] == client['url'].split('/')[-1]:data['clients_number'] += 1if 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}

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

  1. 魔坊APP项目-25-种植园,植物的状态改动、当果树种植以后在celery的异步任务中调整浇水的状态、客户端通过倒计时判断时间,显示浇水道具

    种植园 植物的状态改动 一.当果树种植以后在celery的异步任务中调整浇水的状态 在进行果树种植的时候, 在服务端设置当前果树到等待浇水的redis变量中.通过celery不断进行周期任务的处理, ...

  2. 魔坊APP项目-21-种植园,宠物栏的功能实现、服务端提供显示宠物的api接口、客户端中展示宠物栏和宠物列表以及饱食度、宠物道具的使用

    种植园 一.宠物栏的功能实现 1. 宠物的显示 2. 宠物的使用 3. 宠物的饱食度 4. 宠物的开锁 1.服务端提供显示宠物的api接口 socket.py,代码 ... import math f ...

  3. 魔坊APP项目-26-直播、docker安装OSSRS流媒体直播服务器、基于APICloud的acLive直播推流模块实现RTMP直播推流、直播流管理

    一.docker安装OSSRS流媒体直播服务器 在外界开发中, 如果要实现直播功能.常用的方式有: 1. 通过第三方接口来实现.可以申请阿里云,腾讯云,网易云,七牛云的直播接口,根据文档,下载集成SD ...

  4. 魔坊APP项目-22-种植园,种植栏的功能实现,客户端根据激活状态和未激活状态分别显示树桩、服务端提供种植植物的相关数据、解锁树桩、植物相关道具使用

    种植园 一.种植栏的功能实现 1. 客户端需要的植物相关参数: 总树桩数量, 当前用户激活树桩数量, 当前种植的树桩数量, 树桩列表状态 2. 客户端根据激活状态和未激活状态分别显示树桩 3. 服务端 ...

  5. 魔坊APP项目-20-种植园,背包显示道具、用户购买道具的时候,判断背包存储是否达到上限、背包解锁

    种植园 一.背包显示道具 在背包中显示道具,会涉及到用户的背包格子的显示以及解锁问题,所以我们需要在服务端准备一个参数信息, 用于保存种植园中用户的业务参数,例如: 格子的初始化数量, 每次解锁背包格 ...

  6. 魔坊APP项目-18-种植园,基于支付宝提供的沙箱测试环境开发支付接口、服务端, 处理支付结果的同步通知和异步通知、修复页面底部菜单无法被点击的BUG

    种植园 一.基于支付宝提供的沙箱测试环境开发支付接口 沙箱环境: https://openhome.alipay.com/platform/appDaily.htm?tab=info 开发文档: ht ...

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

    直播 显示房间列表 把上面的客户端live_list.html,修改成live.html,并新建live_list.html,代码: <!DOCTYPE html> <html> ...

  8. 魔坊APP项目-24-种植园,修复宠物喂食时出现的饱食度没有增加的bug、宠物挂了的bug问题

    种植园 修复宠物喂食时出现的饱食度没有增加的bug 在feed方法中监听是否喂食成功的pet_feed_success通知中, 保存更新后的hp_time. my_orchard.html代码: &l ...

  9. 魔坊APP项目-23-种植园,宠物和种植物的状态改变、宠物的状态改动

    种植园 宠物和种植物的状态改变 1. 宠物的状态改动 2. 种植物的状态改动 3. 道具的使用 宠物的状态改动 因为宠物有多个,每个宠物会有不同的初始生命的饥饿时间,所以我们提前在mysql中进行配置 ...

最新文章

  1. “不会Linux,怎么当程序员?”骨灰级程序员:干啥都不行。
  2. 减少代码中该死的 if else 嵌套
  3. python if后面要不要加括号_Python装饰器兼容加括号与不加括号的写法
  4. 定义简单类-接收对象的变量同样是对对象的引用
  5. FZU2105 Digits Count(按位建线段树)题解
  6. 微星P55-主板是怎样造出来的
  7. matlab图像分割(肺实质)
  8. html中怎样做成相册的效果,CSS相册简单实现方法(功能分析及代码)
  9. 联合国基金会 广告投放 策略
  10. 小程序内部如何跳转公众号
  11. 微软project服务器搭建,安装和配置 Project Server 2013
  12. aiml的中文适配aiml_cn
  13. CSS——设置元素边框的bug,当boder-radius比border本身大的时候
  14. EditText自动弹出输入法问题
  15. WannaCry勒索病毒处理指南
  16. 解析身份证号码(Python版)
  17. 第一章之OpenCV安装
  18. Qt 使用 Matlab函数
  19. Richard Matthew Stallman和GNU
  20. HTML中的meta的属性作用

热门文章

  1. 零点工作室暑假集训(AtCoder--ABC233)
  2. 如果你还不懂会员管理系统,那还做什么实体零售
  3. OriginPro 8 简单论文作图并且将多个worksheet表画在同一张图以及图的保存
  4. 论情绪之恐惧感(上)
  5. 在Linux中修改打开文件数量和进程数量限制的3种方法
  6. HBuilderX及其插件的安装
  7. 模型剪枝三:Learning Structured Sparsity in Deep Neural Networks
  8. 薪水被应届生倒挂,裸辞了
  9. 高中就开始学的正态分布,原来如此重要!
  10. 代码随想录打卡day1(补卡)