更新记录

1.1(2023-12-06) 下载此版本

解决安卓推流反复重连的bug

1.0(2023-07-27) 下载此版本

推流组件 播流组件


平台兼容性

Android Android CPU类型 iOS
适用版本区间:8.0 - 12.0 armeabi-v7a:未测试,arm64-v8a:未测试,x86:未测试 适用版本区间:9 - 14

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


腾讯直播组件使用DEMO

一、推流功能

模板部分

<template>
    <view class="content">
        <Tx-Push 
        @onNetStatus="onNetStatus"
        @onError="onError" 
        @onStatisticsUpdate="onStatisticsUpdate" :style="{width: lebWidth+'rpx', height:lebHeight+'rpx'}"
         ref="TxPush" class="liveview"></Tx-Push>
        <view class="input">
            <input class="iptVal" type="text" placeholder="输入参数" v-model="iptVal" />
        </view>
        <view class="controlrow">
            <button class="livebutton" @click="setConfig">初使化</button>
            <button class="livebutton" @click="startCameraPreview">预览</button>
            <button class="livebutton" @click="stopCameraPreview">停止预览</button>
        </view>
        <view class="controlrow">
            <button class="livebutton" @click="startPusher">开始推流</button>
            <button class="livebutton" @click="stopPusher">结束推流</button>
            <button class="livebutton" @click="setBeautyFilter">美颜</button>
        </view>
        <view class="controlrow">
            <button class="livebutton" @click="setVideoQuality2">码率设置</button>
            <button class="livebutton" @click="switchCamera">切换摄像头</button>
            <button class="livebutton" @click="turnOnFlashLight">打开闪光灯</button>
        </view>
        <view class="controlrow">
            <button class="livebutton" @click="setZoom">调整焦距</button>
            <button class="livebutton" @click="getMaxZoom">获取最大焦距</button>
            <button class="livebutton" @click="setExposureCompensation">曝光比例</button>
        </view>
        <view class="controlrow">
            <button class="livebutton" @click="setMirror">观众端的镜像</button>
            <button class="livebutton" @click="setRenderRotation">设置翻转</button>
            <button class="livebutton" @click="requestAndroidPermission">申请权限</button>
        </view>
        <view class="controlrow">
            <button class="livebutton" @click="changeTouchFocus">切换对焦</button>
            <button class="livebutton" @click="pausePusher">暂停推流</button>
            <button class="livebutton" @click="resumePusher">恢复推流</button>
            <view class="emptyitem"></view>
        </view>
        <view class="output">
            <textarea class="textarea" v-model="msg"></textarea>
        </view>
    </view>
</template>

脚本部分

<script>
    var TXLiveConstants = {};
    TXLiveConstants.VIDEO_ANGLE_HOME_DOWN = 1; //竖屏推流
    TXLiveConstants.VIDEO_ANGLE_HOME_RIGHT = 0; //横屏推流
    TXLiveConstants.VIDEO_ANGLE_HOME_LEFT = 2; //横屏推流

    import permision from "@/js_sdk/wa-permission/permission.js"
    export default {
        data() {
            return {
                touchFocus:false,
                iptVal: '',
                title: 'Hello',
                lebWidth: 750,
                lebHeight: 350,
                msg: '=='
            }
        },
        onLoad() {},
        methods: {
            //推流状态回调
            onNetStatus(res) {
                this.msg = res.detail.SPD
            },
            changeTouchFocus(){
                if(this.touchFocus){
                    this.touchFocus = false
                }else{
                    this.touchFocus = true
                }
            },
            toMsg(obj) {
                if (obj instanceof Object) {
                    this.msg += JSON.stringify(obj);
                }
                if (obj instanceof String) {
                    this.msg += obj;
                }
            },
            //初使化
            setConfig() {
                //enablePureAudioPush纯音频
                //homeOrientatio 横屏模式
                var licenceURL =
                    'http://license.vod2.myqcloud.com/license/v1/cf7126e6484fe916ef7e23c4acc9eb1c/TXLiveSDK.licence';
                var licenceKey = 'e8353becb62cc5cedfabe4fa4ef2f9f0';

                var bitrate = 1000
                var minBitrate = 1000
                var maxBitrate = 1800
                var fps = 20
                var touchFocus = this.touchFocus
                var sampleRate = 48000

                var setConfig = {
                    enablePureAudioPush: false,
                    autoAdjustBitrate: true,
                    bitrate: bitrate,
                    minBitrate: minBitrate,
                    maxBitrate: maxBitrate,
                    touchFocus: touchFocus,
                    sampleRate: sampleRate,
                    fps: fps,
                    homeOrientatio: this.VIDEO_ANGLE_HOME,
                    licenceURL: licenceURL,
                    licenceKey: licenceKey
                }
                this.$refs.TxPush.setConfig(setConfig, ret=>{
                    uni.showToast({
                        title: `初使化状态:${ret}`
                    })
                    console.log(`初使化状态:${ret}`)
                    this.msg = `初使化状态:${ret}`
                })
            },
            //开始预览
            startCameraPreview() {
                var value = this.iptVal
                console.log('startCameraPreview')
                this.$refs.TxPush.startCameraPreview({
                    'value': value
                })
            },
            //停止预览
            stopCameraPreview() {
                console.log('stopCameraPreview')
                this.$refs.TxPush.stopCameraPreview();
            },
            //开始推流
            startPusher() {
                var value = 'rtmp://live-tencent.51bidlive.com/live/PM3984955411651497985?txSecret=08ce36c94552cb316da60a5a34c673d4&txTime=61bff362';

                console.log('startPusher')
                this.$refs.TxPush.startPusher(value,ret=>{
                    uni.showToast({
                        title: `推流状态:${ret}`
                    })
                    console.log(`推流状态:${ret}`)
                    this.msg = `推流状态:${ret}`
                })
            },
            //停止推流
            stopPusher() {
                console.log('stopPusher')
                this.$refs.TxPush.stopPusher();
            },

            //暂停推流
            pausePusher() {
                console.log('pausePusher')
                this.$refs.TxPush.pausePusher();
            },
            //恢复推流
            resumePusher() {
                console.log('resumePusher')
                this.$refs.TxPush.resumePusher();
            },
            //切换摄像头
            switchCamera() {
                console.log('switchCamera')
                var value = this.iptVal;
                this.$refs.TxPush.switchCamera({
                    'value': value
                });
            },
            //打开闪光灯
            enableCameraTorch() {
                console.log('enableCameraTorch')
                var value = this.iptVal;
                this.$refs.TxPush.enableCameraTorch({
                    'value': value
                });
            },
            setVideoQuality2(){
                var bitrate = 300
                var minBitrate = 300
                var maxBitrate = 300
                var fps = 20
                var value = this.iptVal;

                var config = {
                    autoAdjustBitrate: true,
                    bitrate: bitrate,
                    minBitrate: minBitrate,
                    maxBitrate: maxBitrate,
                    fps: fps
                }
                this.$refs.TxPush.setVideoQuality2(config);
            },
            //设置推流质量
            setVideoQuality() {
                //VIDEO_QUALITY_STANDARD_DEFINITION YES 360 × 640   500kbps - 900kbps
                //VIDEO_QUALITY_STANDARD_DEFINITION NO  360 × 640   800kbps
                //VIDEO_QUALITY_HIGH_DEFINITION YES 540 × 960   800kbps - 1500kbps
                //VIDEO_QUALITY_HIGH_DEFINITION NO  540 × 960   1200kbps
                //VIDEO_QUALITY_SUPER_DEFINITION    YES 720 × 1280  1000kbps - 1800kbps
                //VIDEO_QUALITY_SUPER_DEFINITION    NO  720 × 1280  1800kbps
                //VIDEO_QUALITY_ULTRA_DEFINITION    YES 1080 × 1920 2500kbps - 3000kbps
                //VIDEO_QUALITY_ULTRA_DEFINITION    NO  1080 × 1920 3000kbps
                //VIDEO_QUALITY_LINKMIC_MAIN_PUBLISHER  不支持设置   540 × 960   800kbps - 1500kbps
                //VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER   不支持设置   320 × 480   350kbps
                TXLiveConstants.VIDEO_QUALITY_STANDARD_DEFINITION = 1;
                TXLiveConstants.VIDEO_QUALITY_HIGH_DEFINITION = 2;
                TXLiveConstants.VIDEO_QUALITY_SUPER_DEFINITION = 3;
                TXLiveConstants.VIDEO_QUALITY_LINKMIC_MAIN_PUBLISHER = 4;
                TXLiveConstants.VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER = 5;
                TXLiveConstants.VIDEO_QUALITY_REALTIEM_VIDEOCHAT = 6;
                TXLiveConstants.VIDEO_QUALITY_ULTRA_DEFINITION = 7;
                var qualityPara = {
                    adjustBitrate: true,
                    quality: TXLiveConstants.VIDEO_QUALITY_LINKMIC_SUB_PUBLISHER
                }
                this.$refs.TxPush.setVideoQuality(qualityPara);
            },
            //设置屏幕翻转
            setRenderRotation() {
                console.log('setRenderRotation')
                //0,90,180,270,360
                var value = this.iptVal;
                this.$refs.TxPush.setRenderRotation({
                    'value': value
                });
            },
            //调整摄像头的焦距
            setZoom() {
                console.log('setZoom')
                var value = this.iptVal;
                this.$refs.TxPush.setZoom({
                    'value': value
                });
            },
            //测试
            test() {
                console.log('test')
                var value = this.iptVal;
                this.$refs.TxPush.test({
                    'value': value
                });
            },
            //获取当前摄像头
            getCurrentCamera() {
                console.log('getCurrentCamera')
                var value = this.iptVal;
                this.$refs.TxPush.getCurrentCamera({
                    'value': value
                });
            },
            //获取摄像头的最大焦距
            getMaxZoom() {
                console.log('getMaxZoom')
                var zoom = this.$refs.TxPush.getMaxZoom();
                uni.showToast({
                    title: zoom + 'zoom'
                })
                if (zoom == 0) {
                    this.$refs.TxPush.getMaxZoom(function(ret) {
                        uni.showToast({
                            title: JSON.stringify(ret)
                        })
                    });
                }
            },
            //获取摄像头曝光
            setExposureCompensation() {
                //曝光比例,表示该手机支持最大曝光调整值的比例,取值范围从-1到1。 
                //负数表示调低曝光,-1是最小值,对应 getMinExposureCompensation。 
                //正数表示调高曝光,1是最大值,对应 getMaxExposureCompensation。 
                //0表示不调整曝光,默认值为0。
                console.log('setExposureCompensation')
                var value = this.iptVal;
                this.$refs.TxPush.setExposureCompensation({
                    'value': value
                });
            },
            //设置镜像
            setMirror() {
                console.log('setMirror')
                var value = this.iptVal;
                this.$refs.TxPush.setMirror({
                    'value': value
                });
            },
            //设置美颜
            setBeautyFilter() {
                //style             美颜算法:  0:光滑  1:自然  2:朦胧    
                //beautyLevel       磨皮等级: 取值为 0-9.取值为 0 时代表关闭美颜效果.默认值: 0,即关闭美颜效果.  
                //whiteningLevel    美白等级: 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.  
                //ruddyLevel        红润等级: 取值为 0-9.取值为 0 时代表关闭美白效果.默认值: 0,即关闭美白效果.  
                var style = 0;
                var beautyLevel = 8;
                var whiteningLevel = 8;
                var ruddyLevel = 8;
                var para = {
                    style: style,
                    beautyLevel: beautyLevel,
                    whiteningLevel: whiteningLevel,
                    ruddyLevel: ruddyLevel
                }
                this.$refs.TxPush.setBeautyFilter(para);
            },
            //暂时不用
            setFilter() {
                console.log('setFilter')
                var value = this.iptVal;
                this.$refs.TxPush.setFilter({
                    'value': value
                });
            },
            //请求相机权限
            requestAndroidPermission() {
                console.log('requestAndroidPermission')
                var _this = this;
                var permisionID = 'android.permission.CAMERA';
                permision.requestAndroidPermission(permisionID).then((result) => {
                    if (result == 1) {
                        uni.showToast({
                            title: '获得CAMERA授权'
                        })
                        permisionID = 'android.permission.RECORD_AUDIO';
                        permision.requestAndroidPermission(permisionID).then((result) => {
                            if (result == 1) {
                                uni.showToast({
                                    title: '获得RECORD授权'
                                })
                                //READ_EXTERNAL_STORAGE
                                //WRITE_EXTERNAL_STORAGE
                                permisionID = 'android.permission.READ_EXTERNAL_STORAGE';
                                permision.requestAndroidPermission(permisionID).then((result) => {
                                    if (result == 1) {
                                        uni.showToast({
                                            title: '获得READ_EXTERNAL_STORAGE授权'
                                        })
                                        permisionID = 'android.permission.WRITE_EXTERNAL_STORAGE';
                                        permision.requestAndroidPermission(permisionID).then((result) => {
                                            if (result == 1) {
                                                uni.showToast({
                                                    title: '获得WRITE_EXTERNAL_STORAGE授权'
                                                })
                                            }
                                        });
                                    }
                                });

                            }
                        });
                    } else if (result == 0) {
                        uni.showToast({
                            title: result + '未获得授权'
                        })
                    } else {
                        uni.showToast({
                            title: result + '被永久拒绝权限'
                        })
                        permision.gotoAppPermissionSetting()
                    }
                })
            },

            onStatisticsUpdate(data) {
                console.log(data.detail)
                if(this.iptVal==1){
                    this.msg = JSON.stringify(data.detail);
                }
            },
            onError(data) {
                if(this.iptVal==2){
                    console.log(data.detail)
                    this.msg = JSON.stringify(data.detail);
                }
            },
            onPushStatusUpdate(data) {
                console.log(data.detail)
                if(this.iptVal==3){
                    console.log(data.detail)
                    this.msg = JSON.stringify(data.detail);
                }
            },

        }
    }
</script>

样式部分

<style scoped>
    .input {
        padding: 10rpx;
    }

    .output {
        padding: 10rpx;
    }

    .iptVal {
        border: 1px solid #cccccc;
        background-color: #F1F1F1;
        height: 60rpx;
        padding-left: 20rpx;
    }

    .liveview {
        /*      width: 750rpx;
        height: 421rpx; */
        background-color: #C0C0C0;
        overflow: hidden;
    }

    .controlrow {
        width: 750rpx;
        flex-direction: row;
        flex-wrap: wrap;
        margin-bottom: 10rpx;
        display: flex;
    }

    .livebutton {
        flex: 1;
        width: 200rpx;
        margin: 0rpx 10rpx 0rpx 10rpx;
        font-size: 24rpx;
        padding: 0rpx 0rpx 0rpx 0rpx;
    }

    .emptyitem {
        flex: 1;
        width: 200rpx;
        margin: 0rpx 10rpx 0rpx 10rpx;
        font-size: 24rpx;
    }

    .textarea {
        width: 750rpx;
        height: 250rpx;
    }
</style>

二、播流功能

模板部分

<template>
    <view class="content">
        <Leb-Live @onEventConnected="onEventConnected" 
        @onEventConnectFailed="onEventConnectFailed" 
        @onEventFirstFrameRendered="onEventFirstFrameRendered" 
        @onEventStatsReport="onEventStatsReport" 
        :style="{width: lebWidth+'px', height:lebHeight+'px'}" ref="LebLive" class="liveview"></Leb-Live>
        <view class="buttons">
            <view class="input">
                <input class="iptVal" type="text" placeholder="输入参数" v-model="iptVal" />
            </view>
            <view class="controlrow">
                <button class="livebutton" @click="startPlay">播放</button>
                <button class="livebutton" @click="pausePlay">暂停</button>
                <button class="livebutton" @click="stopPlay">结束</button>
            </view>
            <view class="controlrow">
                <button class="livebutton" @click="release">释放资源</button>
                <button class="livebutton" @click="mutePlay">静音播放</button>
                <button class="livebutton" @click="setVolume">音量设置</button>
            </view>
            <view class="controlrow">
                <button class="livebutton" @click="setRenderRotation">旋转</button>
                <button class="livebutton" @click="initLeb">初使化</button>
                <button class="livebutton" @click="rotateVideo(false)">横屏</button>
            </view>
            <view class="controlrow">
                <button class="livebutton" @click="resumePlay">恢复</button>
            </view>
            <view class="output">
                <textarea class="textarea" v-model="msg"></textarea>
            </view>
        </view>
    </view>
</template>

脚本部分

<script>
    export default {
        data() {
            return {
                iptVal: '',
                title: 'Hello',
                primarytype: '',
                lebWidth: 0,
                lebHeight: 0,
                msg: '==',
                pageReady: false,
                pageHide: false
            }
        },
        onLoad() {
            uni.getSystemInfo({
                success: res => {
                    this.lebWidth = res.screenWidth
                    this.lebHeight = res.screenWidth * 0.5625
                }
            })
        },
        onReady() {
            if(this.primarytype=='portrait-primary'){
                this.initLeb(true)
            } else {
                this.rotateVideo(true, 'landscape-primary')
            }
        },
        onShow() {
            if(this.pageHide){
                this.initLeb(true)
            }
            this.pageHide = false
        },
        onHide() {
            this.pageHide = true
            this.stopPlay()
        },
        methods: {
            requestPermissions(){
                this.$refs.LebLive.requestPermissions();
            },
            toMsg(obj){
                if(obj instanceof Object){
                    this.msg += JSON.stringify(obj);
                }
                if(obj instanceof String){
                    this.msg += obj;
                }
            },
            onEventConnected(obj){
                this.msg = '连接成功'
                console.log(this.msg)
            },
            onEventConnectFailed(obj){
                this.msg = '连接失败';
                //this.stopPlay()
                //this.release()
                this.initLeb(true)
                console.log(this.msg,obj)
            },
            onEventFirstFrameRendered(obj){
                this.msg = '首帧准备';
                console.log(this.msg,obj)
            },
            onEventStatsReport(obj){
                //console.log(obj);
                this.msg = JSON.stringify(obj);
            },
            startPlay(){
                console.log('startPlay')
                this.$refs.LebLive.startPlay();
            },
            stopPlay(){
                console.log('stopPlay')
                this.$refs.LebLive.stopPlay();
            },
            pausePlay(){
                console.log('pausePlay')
                this.$refs.LebLive.pausePlay();
            },
            resumePlay(){
                console.log('resumePlay')
                this.$refs.LebLive.resumePlay();
            },
            release(){
                console.log('release')
                this.$refs.LebLive.release();
            },
            mutePlay(){
                console.log('mutePlay')
                var mute = this.iptVal == 'yes' ? true : false;
                this.$refs.LebLive.mutePlay({'value':mute});
            },
            setVolume(){
                console.log('setVolume')
                var volume = parseFloat(this.iptVal);
                this.$refs.LebLive.setVolume({'value':volume});
            },
            setRenderRotation(){
                console.log('setRenderRotation')
                var rotation = parseInt(this.iptVal);
                //plus.screen.lockOrientation('landscape-primary');
                this.$refs.LebLive.setRenderRotation({'value':rotation});
            },
            setHide(){
                if(this.lebWidth==0||this.lebHeight==0){
                    uni.getSystemInfo({
                        success: res => {
                            this.lebWidth = res.screenWidth
                            this.lebHeight = res.screenWidth * 0.5625
                        }
                    })
                }else{
                    this.lebWidth = 0
                    this.lebHeight = 0
                }
            },
            initLeb(isAutoPlay){
                var part = [];
                part[0] = '750';
                part[1] = '461';
                part[2] = 'webrtc://5664.liveplay.myqcloud.com/live/5664_harchar1';
                //part[2] = 'webrtc://play-tencent.51bidlive.com/live/37260?txSecret=110e9e93f8ca191c648273be62e264f9';
                part[3] = 'no';
                part[4] = 'https://webrtc.liveplay.myqcloud.com/webrtc/v1/pullstream';
                part[5] = 'https://webrtc.liveplay.myqcloud.com/webrtc/v1/stopstream';
                part[6] = 16;
                part[7] = 9;

                //this.lebWidth = part[0];
                //this.lebHeight = part[1];
                this.msg = `${this.lebHeight}`
                var width = this.lebWidth;
                var height = this.lebHeight;
                var autoPlay = part[3];
                var videoWidthRate = part[6];
                var videoHeightRate = part[7];
                var liveUrl = part[2];
                var requestPullUrl = part[4];
                var requestStopUrl = part[5];
                this.$refs.LebLive.initLeb({
                    'width':width, 
                    'height':height, 
                    'liveUrl':liveUrl, 
                    'videoWidthRate':videoWidthRate,
                    'videoHeightRate':videoHeightRate,
                    'requestPullUrl':requestPullUrl,
                    'requestStopUrl':requestStopUrl,
                }, ret => {
                    // console.log('isAutoPlay')
                    // console.log(isAutoPlay)
                    if(isAutoPlay){
                        this.startPlay()
                    }
                    // uni.showToast({
                    //  title: `初使化${ret}`
                    // })
                    this.$refs.LebLive.resetVideoSize(this.lebWidth, this.lebHeight)
                    // console.log(`初使化${ret}`)
                    // this.msg = `初使化${ret}`
                })
            },
            rotateVideo(needPlay, primarytype){
                if(primarytype){
                    //指定屏幕方向
                    this.primarytype = primarytype
                } else {
                    //切换方向
                    if(this.primarytype == `portrait-primary`){
                        this.primarytype = `landscape-primary`
                    } else {
                        this.primarytype = `portrait-primary`
                    }
                }
                plus.screen.lockOrientation(this.primarytype)
                uni.onWindowResize(res => {
                    //屏幕翻译完成后逻辑
                    uni.offWindowResize(() => {})
                    uni.getSystemInfo({
                        success: res => {
                            if(this.primarytype == `landscape-primary`){
                                //横屏全屏
                                this.lebWidth = res.screenWidth
                                this.lebHeight = res.screenHeight
                            } else if(this.primarytype == `portrait-primary`) {
                                //竖屏全屏
                                this.lebWidth = res.screenWidth
                                this.lebHeight = res.screenWidth * 0.5625
                            }
                            if(needPlay){
                                //翻转后播放
                                this.initLeb(true)
                            }else{
                                //仅翻转
                                this.$refs.LebLive.resetVideoSize(this.lebWidth, this.lebHeight)
                            }
                        }
                    })
                })
            },
        }
    }
</script>

样式部分

<style scoped>
    .content{
        width: 100%;
    }
    .input{
        padding: 10rpx;
    }
    .output{
        padding: 10rpx;
    }
    .iptVal{
        border: 1px solid #cccccc;
        background-color: #F1F1F1;
        height: 50px;
        padding-left: 20rpx;
    }
    .buttons{
        position:fixed;
        left: 0;
        bottom: 0;
        background-color: rgba(0,0,0,0);
    }
    .liveview{
/*      position: fixed;
        left: 0;
        top: 0;
        background-color: #C0C0C0; */

    }
    .controlrow{
        width: 750rpx;
        flex-direction: row;
        flex-wrap: wrap;
        margin-bottom: 10rpx;
        display: flex;
    }
    .livebutton{
        flex: 1;
        width: 200rpx;
        margin: 0rpx 10rpx 0rpx 10rpx;
        font-size: 24rpx;
        padding: 0rpx 0rpx 0rpx 0rpx;
    }
    .emptyitem{ 
        flex: 1;
        width: 200rpx;
        margin: 0rpx 10rpx 0rpx 10rpx;
        font-size: 24rpx;
    }
    .textarea{
        width: 750rpx;
        height: 250rpx;
    }
    .btnSetLandscape{
        padding: 10px 10px 10px 10px;
        background-color: #333333;
    }
    .btnSetLandscapetext {
        color: #FFFFFF;
    }

</style>

隐私、权限声明

1. 本插件需要申请的系统权限列表:

摄像头 麦克风

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

插件使用腾讯云移动直播SDK,详情可参考: https://cloud.tencent.com/product/mlvb

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

作者未提供license.md

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问