uni-app 实现集成火山视频直播服务
一、前言
项目开发进程中,业务提出新需求,需要接入视频直播。为此,开始接触火山引擎视频直播。火山引擎方值负责提供观播SDK,综合考虑现有技术栈,采用集成Web SDK
方式,接入观播功能。直播通过企业版腾讯会议方式进行推流操作。
二、技术实现
前端采用uni-app Webview
嵌套H5
页面方式,重点处理逻辑集中在H5
观播页面中,因为涉及观播activityId
值的获取,故需要实现Webview
与H5
页面双向通信机制。
uni-app在 App 平台同时支持网络网页和本地网页,但本地网页及相关资源(js
、css
等文件)必须放在 uni-app 项目根目录->hybrid->html
文件夹下或者 static
目录下,因为这个目录下的文件不会被编译。
注意⚠️:Web SDK
以本地网页嵌套集成火山视频方式,目前不支持预告片播放及直播回放功能,故需要将视频直播H5
作为一个独立H5
应用进行部署。
补充知识点⚠️:每个vue
页面,其实都是一个webview
,而vue
页面里的web-view
组件,其实是webview
里的一个子webview
。这个子webview
被append
到父webview
上。
var currentWebview = this.$scope.$getAppWebview(); //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
currentWebview.append(wv);//一定要append到当前的页面里!!!才能跟随当前页面一起做动画,一起关闭
vue
页面内容如下:
<template>
<!-- 注:使用动态url -->
<view>
<web-view :src="url"></web-view>
<view>
</template>
<script>
export default {
data() {
return {
url: ''
}
},
onLoad() {
// 默认一个你的html(h5地址)
this.url = '/hybrid/html/vedioLive.html'
},
mounted(){
// 需要监听 message 之后触发方法
window.addEventListener("message", this.handlePostMessage);
},
methods: {
// 触发方法
handlePostMessage(data) {
console.log(data)
console.log(data.data.data.arg.data)
if (data.data.data.arg.data == 'h5页面传的值') {
// 给url重新赋值
this.url = ""
} else if (data.data.data.arg.data == '判断返回uniapp页面') {
// 其他的跳转查看uniapp官网
uni.switchTab({
url: '/pages/xxx/index'
});
}
},
}
}
</script>
html页面内容如下:
<!DOCTYPE html>
<html style="height: 100%" lang="zh-CN">
<head>
<title>直播Demo</title>
<meta charset="utf-8" content="text/html">
<link rel="shortcut icon"
href=//p1-live.byteimg.com/tos-cn-i-gjr78lqtd0/3f061494968a653d3409e0607259939e.png~tplv-gjr78lqtd0-image.image
sizes="16x16">
<meta name="viewport" http-equiv="Content-Type" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,
maximum-scale=1.0, user-scalable=no, shrink-to-fit=no, viewport-fit=cover">
<link rel="stylesheet"
href="https://lf-cdn-tos.bytescm.com/obj/static/livesaas-client/mobile/css/index.1.1.4.css">
<style>
.app {
display: flex;
height: 100%;
flex-direction: column;
/* background-image: url('//p6-live.byteimg.com/tos-cn-i-gjr78lqtd0/923a9e572712a19d5b8c84fa66e90bd6.png~tplv-gjr78lqtd0-image.image'); */
background-color: white!important;
background-size: 100% 100%;
background-attachment: fixed;
}
.player {
width: 100vw;
height: calc(100vw / 16 * 9);
}
.menu {
flex: 1 1;
min-height: 300px;
overflow: hidden;
}
</style>
</head>
<body style='
font-size: 10px; margin: 0; background-color: #080B12;
height: 100%; overflow: hidden;'>
<div class="app">
<div id="player" class="player"></div>
<div id="content" class="menu"></div>
</div>
<script src="https://lf-cdn-tos.bytescm.com/obj/static/livesaas-client/mobile/js/index.1.1.4.js"></script>
<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
</body>
<script>
// 等待sdk加载,待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
document.addEventListener('UniAppJSBridgeReady', function() {
console.log('-----------UniAppJSBridgeReady------------')
// 向应用发送消息
uni.postMessage({
data: {
order: 'playRecord'
}
});
uni.getEnv(function(res) {
console.log('当前环境:' + JSON.stringify(res));
});
});
window.msgFromUniapp= function(arg) {
console.log('<<<<<<<<<<<<<arg>>>>>>>>>>>:', arg);
console.log('<<<<<<<<<<<<<JSON.stringify(arg)>>>>>>>>>>>:', JSON.stringify(arg));
}
var webSDK = new window.ByteLiveWebSDK({
activityId: 1740896046764078,
token: 'xSfupZ',
service: 'liveDemo',
mode: 1,
modules: [
{
id: "player", // 页面元素 ID, 播放器模块会嵌入到此元素内
mode: "player",
},
{
id: "content", // 页面元素 ID, 菜单模块会嵌入到此元素内
mode: "menu"
}
],
options: {
mobileBackgroundTransparent: true,
saveUserInfo: true,
}
})
webSDK.on('error', console.log);
</script>
</html>
有关参数、回调函数等详细用法,详参接口文档。
2.1 web-view组件在app中的窗体关系和plus.webview操作方式
uni-app
的vue
页面本身是一个webview
,vue
页面里的web-view
组件,其实是一个子webview
。但一个vue
页面不能放多个web-view
组件,这个组件默认是全屏的(不会覆盖原生头和原生导航)。
使用plus
代码获得当前webview
的对象后(参考此文https://ask.dcloud.net.cn/article/35036),再获取子webview
,其实也可以得到web-view
组件所对应的plus
的webview
对象,进而再使用plus.webview
的丰富api
。
获取子webview
时注意时机,获取方法执行太早可能获取不到。
三、双向通信
3.1 uni-app与内嵌网页通信
uni-app向内嵌网页发消息:
const
_funName='msgFromUniapp',
_data = {
msg:'msg from uniapp'
};
const currentWebview = this.$scope.$getAppWebview().children()[0];
currentWebview.evalJS(`${_funName}(${JSON.stringify(_data)})`);
内嵌网页接收消息:
<script type="text/javascript" src="https://gitee.com/dcloud/uni-app/raw/dev/dist/uni.webview.1.5.3.js">
window.msgFromUniapp= function(arg) {
console.log(arg);
console.log(JSON.stringify(arg));
}
3.2 内嵌网页向uni-app发消息
在web-view
访问的网页内引入uni.webview.1.5.3.js
,待sdk
加载完毕后就可以调用方法postMessage
。如下:
// index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" src="https://gitee.com/dcloud/uni-app/raw/dev/dist/uni.webview.1.5.3.js">
</script>
</head>
<body>
<script>
// 等待sdk加载
document.addEventListener('UniAppJSBridgeReady', function() {
// 向应用发送消息
uni.postMessage({
data: {
order: 'playRecord'
}
});
});
</script>
</body>
</html>
uni-app接收消息
在web-view
存在的组件内写监听message
的方法。如下:
<template>
<web-view @message="message" src="/hybrid/html/index.html"></web-view>
</template>
<script>
export default {
data() {
return {};
},
methods: {
message(arg) {
console.loh(arg)
},
}
};
</script>
四、实现案例
内嵌H5网页代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- uni 的 SDK -->
<!-- 需要把 uni.webview.1.5.4.js 下载到自己的服务器 -->
<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
</script>
</head>
<body>
<script>
// 等待sdk加载
document.addEventListener('UniAppJSBridgeReady', function() {
// 向应用发送消息
uni.postMessage({
data: {
order: 'playRecord'
}
});
});
window.msgFromUniapp = function(arg) {
console.log(JSON.stringify(arg));
}
</script>
</body>
</html>
uniapp组件代码:
<template>
<web-view @message='message' src="/hybrid/html/index.html"></web-view>
</template>
<script>
export default {
methods: {
message(arg) {
console.log(JSON.stringify(arg))
this.sendMsgToWebview()
},
sendMsgToWebview() {
const
_funName = 'msgFromUniapp',
_data = {
msg: 'msg from uniapp'
};
const currentWebview = this.$scope.$getAppWebview().children()[0];
currentWebview.evalJS(`${_funName}(${JSON.stringify(_data)})`);
}
}
};
</script>
五、直播
应用火山平台进行直播,取决于直播平台的支持方式,例如企微仅支持拉流直播、腾讯会议仅支持推流直播。
5.1 拉流直播
企业直播支持拉流直播方式。拉流直播是指将获取到的拉流地址的直播画面同步到企业直播间。该功能一般适用于多会场直播的场景。
前提条件:已获取待拉取对象的拉流地址。
操作步骤
-
登录企业直播控制台。
-
在直播列表中,单击进入直播间。
-
在播放器下方,单击开播方式,并单击拉流直播页签。
输入拉流 URL 地址。
说明⚠️:支持的拉流地址协议类型为 rtmp
(推流协议)、rtsp
、hls
、flv
等。
- 单击开始拉流。
5.2 推流直播
首先需要确保开播平台支持推流直播,支持的话就将观播间url配置至开播平台地址。
观播端生成的房间activityid
与token
是与直播间一一绑定的。
六、拓展阅读
- 点赞
- 收藏
- 关注作者
评论(0)