跨平台应用开发进阶(三十):uni-app 实现视频直播

x33g5p2x  于2022-08-17 转载在 其他  
字(6.0k)|赞(0)|评价(0)|浏览(402)

一、前言

项目开发进程中,业务提出新需求,需要接入视频直播。为此,开始接触火山引擎视频直播。火山引擎方值负责提供观播SDK,综合考虑现有技术栈,采用集成Web SDK方式,接入观播功能。直播通过企业版腾讯会议方式进行推流操作。

二、技术实现

前端采用uni-app Webview嵌套H5页面方式,重点处理逻辑集中在H5观播页面中,因为涉及观播activityId值的获取,故需要实现Webview与H5页面双向通信机制。

uni-app在 App 平台同时支持网络网页和本地网页,但本地网页及相关资源(js、css等文件)必须放在 uni-app 项目根目录->hybrid->html 文件夹下或者 static 目录下,因为这个目录下的文件不会被编译。

注意⚠️:每个vue页面,其实都是一个webview,而vue页面里的web-view组件,其实是webview里的一个子webview。这个子webviewappend到父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%">
  <head>
    <title>企业直播WEB SDK DEMO</title>
    <link rel="shortcut icon"
      href=//p1-live.byteimg.com/tos-cn-i-gjr78lqtd0/3f061494968a653d3409e0607259939e.png~tplv-gjr78lqtd0-image.image
      sizes="16x16">
    <meta name="viewport" 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.0.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-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.0.js"></script>
  </body>
  <script>
    var webSDK = new window.ByteLiveWebSDK({
      activityId: 1740896046764078,
      token: 'psNBho',
      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-appvue页面本身是一个webviewvue页面里的web-view组件,其实是一个子webview。但一个vue页面不能放多个web-view组件,这个组件默认是全屏的(不会覆盖原生头和原生导航)。

使用plus代码获得当前webview的对象后(参考此文https://ask.dcloud.net.cn/article/35036),再获取子webview,其实也可以得到web-view组件所对应的pluswebview对象,进而再使用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">
        <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'
                    }
                });
            });
            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>

五、拓展阅读

相关文章