123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- <template>
- <view class="container" data-type="template" data-is="1v1" data-attr="pusher, streamList, debug">
- <view v-for="item in streams.slice(0,1)" :key="item.streamID" class="player-container" :style="'display:'+playerStyle">
- <template v-if="item.src && (item.hasVideo || item.hasAudio)">
- <live-player
- class="player"
- :data-userid="item.userID"
- :data-streamid="item.streamID"
- :data-streamtype="item.streamType"
- :src="item.src"
- mode="RTC"
- :autoplay="item.autoplay"
- :mute-audio="item.muteAudio"
- :mute-video="item.muteVideo"
- :orientation="item.orientation"
- :object-fit="item.objectFit"
- :background-mute="item.enableBackgroundMute"
- :min-cache="item.minCache"
- :max-cache="item.maxCache"
- :sound-mode="item.soundMode"
- :enable-recv-message="item.enableRecvMessage"
- :auto-pause-if-navigate="item.autoPauseIfNavigate"
- :auto-pause-if-open-native="item.autoPauseIfOpenNative"
- :debug="debug"
- @statechange="playerStateChangeFun"
- @fullscreenchange="playerFullscreenChangeFun"
- @netstatus="playerNetStatusFun"
- @audiovolumenotify="playerAudioVolumeNotifyFun"
- :idAttr="item.streamID" />
- </template>
- </view>
- <view class="pusher-container" :style="'display:'+pusherStyle">
- <live-pusher
- class="pusher"
- :url="pusher.url"
- :mode="pusher.mode"
- :autopush="pusher.autopush"
- :enable-camera="pusher.enableCamera"
- :enable-mic="pusher.enableMic"
- :enable-agc="pusher.enableAgc"
- :enable-ans="pusher.enableAns"
- :enable-ear-monitor="pusher.enableEarMonitor"
- :auto-focus="pusher.enableAutoFocus"
- :zoom="pusher.enableZoom"
- :min-bitrate="pusher.minBitrate"
- :max-bitrate="pusher.maxBitrate"
- :video-width="pusher.videoWidth"
- :video-height="pusher.videoHeight"
- :beauty="pusher.beautyLevel"
- :whiteness="pusher.whitenessLevel"
- :orientation="pusher.videoOrientation"
- :aspect="pusher.videoAspect"
- :device-position="pusher.frontCamera"
- :remote-mirror="pusher.enableRemoteMirror"
- :local-mirror="pusher.localMirror"
- :background-mute="pusher.enableBackgroundMute"
- :audio-quality="pusher.audioQuality"
- :audio-volume-type="pusher.audioVolumeType"
- :audio-reverb-type="pusher.audioReverbType"
- :waiting-image="pusher.waitingImage"
- :debug="debug"
- @statechange="pusherStateChangeHandlerFun"
- @netstatus="pusherNetStatusHandlerFun"
- @error="pusherErrorHandlerFun"
- @bgmstart="pusherBGMStartHandlerFun"
- @bgmprogress="pusherBGMProgressHandlerFun"
- @bgmcomplete="pusherBGMCompleteHandlerFun" />
- </view>
- </view>
- </template>
- <script>
- export default {
- name: 'jhlive-wechat',
- data() {
- return {
- pusher: null,
- users: [],
- };
- },
- props: {
- sdkAppID: Number,
- userSig: String,
- userid: String,
- roomid: String,
- isAuthor: Boolean,
- linkMic: Boolean
- },
- computed: {
- streams() {
- console.log('--users', this.users);
- let streams = [];
- this.users.forEach(v=>{
- let userStreams = Object.entries(v.streams);
- streams = streams.concat(userStreams.map(([kk,vv])=>vv).filter(vv=>vv.hasVideo));
- });
- console.log('--streams', streams);
- return streams;
- },
- playerStyle() {
- return (!this.isAuthor)?'block':'none';
- },
- pusherStyle() {
- return this.isAuthor?'block':'none';
- }
- },
- methods: {
- enterRoom() {
- this.pusher = {
- url: 'room://cloud.tencent.com/rtc?sdkappid=' +
- this.sdkAppID +
- '&roomid=' +
- this.roomid +
- '&userid=' +
- this.userid +
- '&usersig=' +
- this.userSig +
- '&appscene=' +
- 'live' +
- '&encsmall=' +
- '1' +
- '&cloudenv=' +
- 'PRO',
- mode: 'RTC', // RTC:实时通话(trtc sdk) live:直播模式(liteav sdk)
- autopush: this.isAuthor||this.linkMic, // 自动推送
- enableCamera: this.isAuthor, // 是否开启摄像头
- enableMic: this.isAuthor||this.linkMic, // 是否开启麦克风
- enableAgc: false, // 是否开启音频自动增益
- enableAns: false, // 是否开启音频噪声抑制
- enableEarMonitor: false, // 是否开启耳返(目前只在iOS平台有效)
- enableAutoFocus: true, // 是否自动对焦
- enableZoom: false, // 是否支持调整焦距
- minBitrate: 200, // 最小码率
- maxBitrate: 1000, // 最大码率
- videoWidth: 360, // 视频宽(若设置了视频宽高就会忽略aspect)
- videoHeight: 640, // 视频高(若设置了视频宽高就会忽略aspect)
- beautyLevel: 0, // 美颜,取值范围 0-9 ,0 表示关闭
- whitenessLevel: 0, // 美白,取值范围 0-9 ,0 表示关闭
- videoOrientation: 'vertical', // vertical horizontal
- videoAspect: '9:16', // 宽高比,可选值有 3:4,9:16
- frontCamera: 'front', // 前置或后置摄像头,可选值:front,back
- enableRemoteMirror: false, // 设置推流画面是否镜像,产生的效果会表现在 live-player
- localMirror: 'auto', // auto:前置摄像头镜像,后置摄像头不镜像(系统相机的表现)enable:前置摄像头和后置摄像头都镜像 disable: 前置摄像头和后置摄像头都不镜像
- enableBackgroundMute: false, // 进入后台时是否静音
- audioQuality: 'high', // 高音质(48KHz)或低音质(16KHz),可选值:high,low
- audioVolumeType: 'voicecall', // 声音类型 可选值: media: 媒体音量,voicecall: 通话音量
- audioReverbType: 0, // 音频混响类型 0: 关闭 1: KTV 2: 小房间 3:大会堂 4:低沉 5:洪亮 6:金属声 7:磁性
- waitingImage: '', // 当微信切到后台时的垫片图片 trtc暂不支持
- waitingImageHash: ''
- };
- console.log('JHLIVE-PUSHER CONFIG', this.pusher);
- setTimeout(()=>{
- this.pusherContext = wx.createLivePusherContext();
- this.pusherContext.start();
- console.log('JHLIVE-PUSHER pusherContext', this.pusherContext);
- },1000);
- },
- exitRoom: function() {
- if (this.pusherContext) {
- this.pusherContext.stop();
- this.pusherContext = null;
- }
- },
- /** --- pusher event handler --- **/
- pusherStateChangeHandlerFun: function(event) {
- const code = event.detail.code;
- const message = event.detail.message;
-
- switch (code) {
- case 0:
- console.log(message, code);
- break;
- case 1001:
- console.log('已经连接推流服务器', code);
- break;
- case 1002:
- console.log('已经与服务器握手完毕,开始推流', code);
- break;
- case 1003:
- console.log('打开摄像头成功', code);
- break;
- case 1004:
- console.log('录屏启动成功', code);
- break;
- case 1005:
- console.log('推流动态调整分辨率', code);
- break;
- case 1006:
- console.log('推流动态调整码率', code);
- break;
- case 1007:
- console.log('首帧画面采集完成', code);
- break;
- case 1008:
- console.log('编码器启动', code);
- break;
- case 1018:
- console.log('进房成功', code);
- break;
- case 1019:
- console.log('退出房间', code);
- break;
- case 2003:
- console.log('渲染首帧视频', code);
- break;
- case 1020: // 远端用户全量列表更新
- break;
- case 1031: {// 远端用户进房通知
- const data = JSON.parse(event.detail.message)||{};
- console.log('远端用户进房通知', data);
- (data.userlist||[]).forEach( v=> {
- if(!this.users.find(vv => vv.userid == v.userid)) {
- this.users.push({
- userid: v.userid,
- streams: {},
- });
- }
- })
- }break;
- case 1032: {// 远端用户退房通知
- console.log('远端用户退房通知', data);
- const data = JSON.parse(event.detail.message)||{};
- (data.userlist||[]).forEach( v=> {
- let user = this.users.find(v => v.userid == data.userid);
- if(!user) return;
- user.streams.forEach(vv=>{
- if(vv.playerContext) {
- vv.playerContext.stop;
- vv.playerContext = null;
- }
- });
- user.streams = [];
- })
- this.users = this.users.filter(v => (data.userlist||[]).find(vv=>vv.userid!=v.userid));
- }break;
- case 1033: {// 用户视频状态变化,新增stream或者更新stream 状态
- console.log('用户视频状态变化,新增stream或者更新stream', data);
- const data = JSON.parse(event.detail.message)||{};
- (data.userlist||[]).forEach( v=> {
- let user = this.users.find(vv => v.userid == v.userid);
- if(!user) return;
- let stream = user.streams[v.streamtype] = user.streams[v.streamtype] || {
- streamType: v.streamtype,
- src: '',
- mode: 'RTC',
- autoplay: true, // 7.0.9 必须设置为true,否则 Android 有概率调用play()失败
- muteAudio: false, // 默认不拉取音频,需要手动订阅
- muteVideo: false, // 默认不拉取视频,需要手动订阅
- orientation: 'vertical', // 画面方向 vertical horizontal
- objectFit: 'fillCrop', // 填充模式,可选值有 contain,fillCrop
- enableBackgroundMute: false, // 进入后台时是否静音(已废弃,默认退台静音)
- minCache: 1, // 最小缓冲区,单位s(RTC 模式推荐 0.2s)
- maxCache: 2, // 最大缓冲区,单位s(RTC 模式推荐 0.8s)
- soundMode: 'speaker', // 声音输出方式 ear speaker
- enableRecvMessage: 'false', // 是否接收SEI消息
- autoPauseIfNavigate: true, // 当跳转到其它小程序页面时,是否自动暂停本页面的实时音视频播放
- autoPauseIfOpenNative: true // 当跳转到其它微信原生页面时,是否自动暂停本页面的实时音视频播放
- }
- stream.userID = v.userid;
- stream.streamID = v.userid + '_' + stream.streamType;
- stream.hasVideo = v.hasvideo;
- stream[`has${stream.streamType}Video`] = stream.hasVideo;
- stream.src = v.playurl;
- // stream.objectFit = stream.hasVideo && stream.streamType === 'aux' && 'contain';
- if(stream.hasVideo) stream.playerContext = wx.createLivePlayerContext(stream.streamID, this);
- })
- this.users = [...this.users];
- }break;
- case 1034: {// 远端用户音频状态位变化通知
- console.log('远端用户音频状态位变化通知', data);
- const data = JSON.parse(event.detail.message)||{};
- (data.userlist||[]).forEach( v=> {
- let user = this.users.find(vv => v.userid == vv.userid);
- if(!user) return;
-
- v.streamtype = 'main';
- let stream = user.streams[v.streamtype] = user.streams[v.streamtype] || {
- streamType: v.streamtype,
- src: '',
- mode: 'RTC',
- autoplay: true, // 7.0.9 必须设置为true,否则 Android 有概率调用play()失败
- muteAudio: false, // 默认不拉取音频,需要手动订阅
- muteVideo: false, // 默认不拉取视频,需要手动订阅
- orientation: 'vertical', // 画面方向 vertical horizontal
- objectFit: 'fillCrop', // 填充模式,可选值有 contain,fillCrop
- enableBackgroundMute: false, // 进入后台时是否静音(已废弃,默认退台静音)
- minCache: 1, // 最小缓冲区,单位s(RTC 模式推荐 0.2s)
- maxCache: 2, // 最大缓冲区,单位s(RTC 模式推荐 0.8s)
- soundMode: 'speaker', // 声音输出方式 ear speaker
- enableRecvMessage: 'false', // 是否接收SEI消息
- autoPauseIfNavigate: true, // 当跳转到其它小程序页面时,是否自动暂停本页面的实时音视频播放
- autoPauseIfOpenNative: true // 当跳转到其它微信原生页面时,是否自动暂停本页面的实时音视频播放
- }
- stream.userID = v.userid;
- stream.streamID = v.userid + '_' + stream.streamType;
- stream.hasAudio = v.hasaudio;
- stream[`has${stream.streamType}Audio`] = stream.hasAudio;
- stream.src = v.playurl;
- if(stream.hasAudio) stream.playerContext = wx.createLivePlayerContext(stream.streamID, this);
- })
- this.users = [...this.users];
- }break;
- case -1301:
- console.error('打开摄像头失败: ', code);
- break;
- case -1302:
- console.error('打开麦克风失败: ', code);
- break;
- case -1303:
- console.error('视频编码失败: ', code);
- break;
- case -1304:
- console.error('音频编码失败: ', code);
- break;
- case -1307:
- console.error('推流连接断开: ', code);
- break;
- case -100018:
- console.error('进房失败: ', code, message);
- break;
- case 5000:
- console.log('小程序被挂起: ', code);
- this.exitRoom()
- this.enterRoom()
- break;
- case 1021:
- console.log('网络类型发生变化,需要重新进房', code);
- break;
- case 2007:
- console.log('本地视频播放loading: ', code);
- break;
- case 2004:
- console.log('本地视频播放开始: ', code);
- break;
- default:
- console.log(message, code);
- }
- },
- pusherNetStatusHandlerFun: function(event) {
-
- },
- pusherErrorHandlerFun: function(event) {
- try {
- console.error('pusher error: ');
- const code = event.detail.errCode;
- const message = event.detail.errMsg;
- console.error(code, message);
- } catch (exception) {}
- },
- pusherBGMStartHandlerFun: function(event) {
-
- },
- pusherBGMProgressHandlerFun: function(event) {
-
- },
- pusherBGMCompleteHandlerFun: function(event) {
-
- },
-
- /** --- player event handler --- **/
- playerStateChangeFun: function(event) {
- console.log('playerStateChangeFun');
- },
- playerFullscreenChangeFun: function(event) {
- console.log('playerFullscreenChangeFun');
- },
- playerNetStatusFun: function(event) {
- console.log('playerNetStatusFun');
- let dataset = event.currentTarget.dataset;
- let info = event.detail.info;
- let user = this.users.find(v => v.userid == dataset.userid);
- if(!user) return;
- let stream = user.streams[dataset.streamtype];
- if(!stream) return;
- stream.videoWidth = info.videoWidth;
- stream.videoHeight = info.videoHeight;
- },
- playerAudioVolumeNotifyFun: function(event) {
- console.log('playerAudioVolumeNotifyFun');
- },
- }
- };
- </script>
- <style lang="less" scoped>
- .container {
- width: 100%;
- height: 100%;
- }
- .pusher-container {
- width: 100%;
- height: 100%;
- }
- .player-container{
- width: 100%;
- height: 100%;
- }
- .pusher {
- width: 100%;
- height: 100%;
- }
- .player {
- width: 100%;
- height: 100%;
- }
- </style>
|