| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744 |
- <template>
- <view class="video_box" :style="'height:' + phoneHeight + 'px'">
- <!-- 本地预览视图 -->
- <view class="video_me" v-show="allUserViewObjectList.length > 0">
- <!-- <view class="video_me" v-if="videoShow"> -->
- <zego-local-view :viewMode="publisherViewModeIndex"
- style="width: 150px; height: 200px; flex: 1; position: fixed; right: 0; top: 65px;">
- </zego-local-view>
- </view>
- <!-- 服务器传来的预览图 -->
- <view class="video_you" v-for="(item, index) in allUserViewObjectList" :key="item.streamID">
- <!-- <view class="video_you"> -->
- <zego-remote-view v-if="item.streamID" :streamID="item.streamID" :viewMode="item.viewMode"
- style="width:600px;height:600px;">
- </zego-remote-view>
- </view>
- <view class="video_btn">
- <view class="video_imgList">
- <view class="video_imgList1">
- <view class="video_view" @click="turn">
- <image class="video_view_img" src="../../static/image/9.png" mode=""></image>
- </view>
- <text class="video_view_txt">翻转镜头</text>
- </view>
- <!-- <view class="video_imgList2" v-if="CameraShow">
- <view class="video_view" @click="closeCamera">
- <image class="video_view_img" src="../../static/image/11.png" mode=""></image>
- </view>
- <text class="video_view_txt" style="margin: 0 0 0 30rpx;">静音</text>
- </view>
- <view class="video_imgList2" v-else>
- <view class="video_view" @click="openCamera">
- <image class="video_view_img" src="../../static/image/12.png" mode=""></image>
- </view>
- <text class="video_view_txt" style="margin: 0 0 0 30rpx;">开启</text>
- </view> -->
- <image @click="offVideo(false,true)" style="width: 50px; height: 50px; margin: 0 0 0 330rpx;"
- src="../../static/image/10.png" mode=""></image>
- </view>
- <!-- <image @click="offVideo()" style="width: 50px; height: 50px; margin: 0 0 0 330rpx;"
- src="../../static/image/10.png" mode=""></image> -->
- </view>
- <!-- 消息提醒 -->
- <u-toast ref="uToast"></u-toast>
- </view>
- </template>
- <script>
- import {
- mapState,
- mapMutations
- } from 'vuex'
- import store from '@/store/index.js'; //需要引入store
- let App = getApp();
- // var API = App.globalData.socketTask;
- var API = App.globalData;
- import permision from "@/zego-express-video-uniapp/permission.js";
- import ZegoExpressEngine from '@/zego-express-video-uniapp/lib/ZegoExpressEngine';
- import {
- ZegoScenario,
- ZegoRoomState,
- ZegoUpdateType,
- // ZegoViewMode,
- ZegoVideoCodecID,
- ZegoRemoteDeviceState
- } from '@/zego-express-video-uniapp/lib/ZegoExpressDefines'
- import {
- AppID,
- AppSign
- } from '@/zego-express-video-uniapp/KeyCenter.js'
- import ZegoLocalView from '@/zego-express-video-uniapp/zego-view/ZegoLocalView';
- import ZegoRemoteView from '@/zego-express-video-uniapp/zego-view/ZegoRemoteView';
- import {
- assign,
- forEach
- } from 'lodash-es';
- export default {
- data() {
- return {
- phoneHeight: '', // 获取当前的屏幕高度
- // 即构
- publisherViewModeIndex: 0, // 本地预览图
- viewModeA: 0, // 服务器预览图
- serveViewModeIndex: "", // 服务器拉流预览图
- engine: undefined,
- videoObj: null,
- userid: "Uni" + Math.floor(Math.random() * 1000000).toString(),
- isPublishingStream: false,
- shotShow: false, // 翻转镜头
- videoShow: false, // 切换视频显示
- allStreamList: [],
- allUserViewObjectList: [],
- CameraShow: true, // 镜头开启关闭
- playerStreamID: 0,
- isPendingExit: false
- }
- },
- computed: {
- ...mapState({
- isVideoCallRefused: state => state.isVideoCallRefused,
- currentReceiveUserID: state => state.currentReceiveUserID
- })
- },
- components: {
- ZegoLocalView: ZegoLocalView,
- ZegoRemoteView: ZegoRemoteView
- },
- watch: {
- // allUserViewObjectList(val) {
- // var that = this
- // if (val.length > 0) {
- // val.forEach((item) => {
- // if (item.streamID) {
- // this.tensile(item)
- // return true
- // }
- // })
- // }
- // }
- isVideoCallRefused(val) {
- console.warn(val, 'isVideoCallRefused video nvue')
- if (val) {
- this.offVideo(true)
- }
- }
- },
- methods: {
- ...mapMutations(['updateIsRefusedCall', 'updateTalkingStatus', 'updateOccupyedStatus']),
- // 即构 - 视频通话 初始化
- async setup() {
- var that = this
- // 创建引擎
- let profile = {
- appID: AppID,
- appSign: AppSign,
- scenario: ZegoScenario.General
- }
- this.engine = await ZegoExpressEngine.createEngineWithProfile(profile);
- this.engine.useFrontCamera(this.shotShow); // 设置前后摄像头
- // console.log(this.engine)
- if (this.isPendingExit) {
- await this.offVideo(true)
- }
- this.addListeners();
- // console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + that.videoObj.room_id)
- const userID = (that.userid = that.videoObj.room_id + that.videoObj.user_id)
- console.log(userID, that.userid)
- await this.engine.loginRoom(that.videoObj.room_id, {
- userID,
- userName: that.videoObj.user_id + '-' +
- that.videoObj.real_name
- }, {
- isUserStatusNotify: true
- }).then(res => {
- console.log(res, 'login room -------------')
- }).catch(err => {
- console.error(err, 'login room')
- });
- },
- // 即构 - 翻转镜头
- turn() {
- this.shotShow = !this.shotShow
- this.engine.useFrontCamera(this.shotShow)
- },
- // 即构 - 关闭镜头 - 停止拉流 、推流
- closeCamera() {
- this.allStreamList.forEach((item) => {
- // this.notTensile(item.streamID); // 停止拉流
- item.muteAudio = !item.muteAudio;
- this.engine.mutePlayStreamAudio(item.streamID, item.muteAudio);
- })
- // // 停止推流
- this.CameraShow = false
- },
- // 即构 - 开启镜头 - 开启拉流、推流
- openCamera() {
- console.log('开启摄像头')
- this.allStreamList.forEach((item) => {
- // this.engine.startPlayingStream(item.streamID); // 开始拉流
- item.muteAudio = !item.muteAudio;
- this.engine.mutePlayStreamAudio(item.streamID, item.muteAudio);
- })
- // // 开始推流
- // this.engine.startPreview();
- // this.engine.startPublishingStream(this.videoObj.room_id);
- this.CameraShow = true
- },
- // 切换视频显示
- changeShow() {
- this.videoShow = !this.videoShow
- // this.onPublish()
- this.engine.startPreview();
- this.engine.startPublishingStream(this.userid);
- this.publishBtnName = "Stop Publishing";
- console.log(this.videoShow)
- },
- // 即构 - 视频通话 监听房间
- addListeners() {
- console.log('开始监听房间了啊')
- var that = this
- // console.log(this.allStreamList, '------------------')
- // 房间状态变化通知
- this.engine.on("roomStateUpdate", (roomID, state, errorCode, extendedData) => {
- console.log('房间状态变化', state)
- if (state == ZegoRoomState.Connected) {
- // 与房间连接成功,只有当房间状态是连接成功时,才能进行推流、拉流等操作。
- // 接下来的“预览并推流”的代码写在这里
- console.log("房间连接成功");
- }
- if (state == ZegoRoomState.DisConnected) {
- // 与房间断开了连接
- console.log("与房间断开连接");
- }
- if (state == ZegoRoomState.Connecting) {
- // 与房间尝试连接中
- console.log("与房间尝试连接中");
- }
- });
- // 房间用户变化通知
- this.engine.on("roomUserUpdate", (roomID, updateType, userList) => {
- console.log(updateType, ZegoUpdateType.Delete, 'roomUserUpdate')
- console.log(userList)
- console.log("有其他用户进出房间");
- if (updateType == ZegoUpdateType.Add) {
- console.log('进入了啊AAAAAAAAAA')
- for (let user of userList) {
- let payload = assign({
- streamID: ''
- }, user)
- for (let stream of this.allStreamList) {
- if (user.userID == stream.user.userID) {
- payload.streamID = stream.streamID
- if (!this.playerStreamID) {
- this.playerStreamID = stream.streamID;
- this.tensile(payload)
- }
- }
- }
- const index = this.allUserViewObjectList.findIndex(item => item.userID === payload
- .userID)
- console.log('-----------------------all user view object list ', index, payload)
- if (index === -1) {
- this.allUserViewObjectList.push(payload);
- }
- }
- } else if (updateType == ZegoUpdateType.Delete) {
- this.allUserViewObjectList = this.allUserViewObjectList.filter((object) => {
- for (let user of userList) {
- if (user.userID == object.userID) {
- return false;
- }
- }
- return true;
- });
- }
- if (updateType == "1") {
- // 有其他用户退出房间
- this.offVideo()
- }
- });
- // 房间内其他用户推的流变化通知
- this.engine.on("roomStreamUpdate", (roomID, updateType, streamList) => {
- // if (updateType == "0") {
- // // 流新增,开始拉流
- // this.tensile(streamList[0].streamID)
- // } else if (updateType == "1") {
- // // 流删除,停止拉流
- // this.notTensile(streamList[0].streamID);
- // }
- console.log('进入了啊BBBBBBBBBBBBBBBBBBBBBBB')
- console.log('---------updateType-----------', updateType)
- console.log('---------streamList-----------', streamList)
- console.log('---------ZegoUpdateType-----------', ZegoUpdateType)
- console.log('---------ZegoUpdateType.Add-----------', ZegoUpdateType.Add)
- console.log('---------ZegoUpdateType.Delete-----------', ZegoUpdateType.Delete)
- console.log('---------allUserViewObjectList-----------', this.allUserViewObjectList)
- if (updateType == ZegoUpdateType.Add) {
- for (let object of this.allUserViewObjectList) {
- for (let stream of streamList) {
- if (object.userID == stream.user.userID) {
- object.streamID = stream.streamID;
- if (!this.playerStreamID) {
- this.playerStreamID = stream.streamID
- this.tensile(object)
- }
- }
- }
- }
- this.allStreamList = this.allStreamList.concat(streamList);
- console.log(this.allStreamList, '-------------')
- } else if (updateType == ZegoUpdateType.Delete) {
- for (let object of this.allUserViewObjectList) {
- for (let stream of streamList) {
- if (object.streamID == stream.streamID) {
- object.streamID = undefined;
- }
- }
- }
- this.allStreamList = this.allStreamList.filter((object) => {
- for (let stream of streamList) {
- if (object.streamID == stream.streamID) {
- return false;
- }
- }
- return true;
- });
- }
- });
- // 拉流质量回调
- this.engine.on("playerQualityUpdate", (streamID, quality) => {
- console.log('拉流质量回调');
- console.log(streamID, quality);
- // if (this.videoShow == false) {
- // setTimeout(() => {
- // that.videoShow = true
- // console.log(that.videoShow, '要打开推流的视频窗口了啊')
- // }, 3500)
- // }
- });
- // 拉流后的事件回调
- this.engine.on("playerStateUpdate", (streamID, state, errorCode, extendedData) => {
- console.warn('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + '拉流后的事件触发了start')
- console.warn(streamID, state, errorCode, extendedData, this.playerStreamID)
- console.warn('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>' + '拉流后的事件触发end')
- })
- this.engine.on('playerRecvVideoFirstFrame', (streamID) => {
- console.warn('playerRecvVideoFirstFrame- 拉流端视频接收首帧回调', streamID)
- })
- this.engine.on('playerRenderVideoFirstFrame', (streamID) => {
- console.warn('playerRenderVideoFirstFrame- 拉流端渲染完视频首帧回调', streamID)
- })
- this.engine.on('publisherStateUpdate', (streamID, state, errorCode, extendedData) => {
- console.warn('publisherStateUpdate 推流状态回调', streamID, state, errorCode, extendedData)
- })
- this.engine.on('publisherCapturedVideoFirstFrame', (channel) => {
- console.warn('publisherCapturedVideoFirstFrame 推流端视频采集首帧回调', channel)
- })
- this.engine.on('remoteCameraStateUpdate', (streamID, state) => {
- console.warn('remoteCameraStateUpdate 远端摄像头设备状态通知', streamID, state)
- })
- },
- tensile(item) {
- console.warn('---------------------------- 拉流start -----------------------')
- console.log(this.allStreamList)
- console.log(item, item.streamID)
- console.log(this.allUserViewObjectList)
- // 拉流点击快于推流时,需要等流更新后重新拉
- // startPlayingStream 在 play.js文件
- // this.startPlayingStream(this.playStreamID);
- this.engine.startPlayingStream(item.streamID)
- console.warn('---------------------------- 拉流start1 -----------------------', this.playerStreamID)
- console.warn('---------------------------- 拉流start end -----------------------')
- },
- // 停止拉流
- notTensile(roomId) {
- this.serveViewModeIndex = roomId
- this.engine.stopPlayingStream(roomId)
- },
- // 推流 - 展示视图 - 本地视频流
- onPublish() {
- if (this.isPublishingStream) {
- // 停止推流
- this.engine.stopPreview();
- this.engine.stopPublishingStream();
- } else {
- console.log('开始推流了啊', this.isPublishingStream)
- // 开始推流
- this.engine.startPreview();
- // 设置编码格式
- // let videoConfig = {};
- // videoConfig.codecID = ZegoVideoCodecID.VP8;
- // this.engine.setVideoConfig(videoConfig);
- // 设置编码格式
- // this.engine.startPublishingStream(this.videoObj.room_id);
- console.log(this.userid)
- this.engine.startPublishingStream(this.userid).then(res => {
- console.log(res, 'start publish stream ------------------1')
- }).catch(err => {
- console.error(err)
- });;
- // this.videoShow = true
- }
- this.isPublishingStream = !this.isPublishingStream;
- },
- // 挂断退出
- async offVideo(isRefused = false, isNotice = true) {
- console.warn('进入了啊offVideo', this.engine)
- this.updateIsRefusedCall(false);
- this.updateTalkingStatus(false);
- this.updateOccupyedStatus(false);
- if (!this.engine) {
- console.warn('挂断退出 ------- 12131312')
- this.isPendingExit = true;
- } else {
- this.isPendingExit = false;
- }
- var that = this
- if (that.videoObj && !that.videoObj.room_id || !that.videoObj) {
- return
- }
- this.engine.logoutRoom(that.videoObj.room_id); // 退出房间
-
- const execExit = () => {
- console.log('---------------- exec exit')
- setTimeout(() => {
- that.videoShow = true
- that.allStreamList = [];
- that.allUserViewObjectList = [];
- var obj = {}
- // obj = {
- // 'action': 'read', // 动作标识,必填
- // 'send_user_id': that.videoObj.user_id, // 接收人用户id, 非必填
- // 'data': {}
- // }
- console.warn('-----------off video 接收人用户id-------------', that.videoObj
- .user_id, API)
- obj = {
- 'action': 'list', // 动作标识,必填
- 'type': '当前为挂断',
- 'recv_user_id': that.videoObj.user_id, // 接收人用户id, 非必填
- 'data': {}
- }
-
- if (!isRefused) {
-
- API.socketTask.send({
- data: JSON.stringify(obj),
- async success(res) {
- console.log("消息发送成功");
- },
- });
- }
-
- if (isNotice) {
- console.log(this.videoObj, 'is notice')
-
- if (!that.currentReceiveUserID) {
- console.warn('当前连接的用户不存在,不是本人发起的通话.')
- } else {
- const socketData = {
- action: 'reject_video', // 动作标识,必填
- recv_user_id: that
- .currentReceiveUserID, // 接收人用户id, 非必填
- data: {},
- }
-
- API.socketTask.send({
- data: JSON.stringify(socketData),
- async success(res) {
- console.log(
- 'reject_video 消息发送成功 reject_video')
- },
- })
- }
-
- }
-
- this.handleBack()
- }, 1500)
- }
-
- this.$refs.uToast.show({
- type: 'default',
- message: isRefused ? '对方正忙' : '结束视频通话!',
- })
- console.log('------------------------------------------ exec exit exec before')
- execExit()
- // if (isRefused) {
- // uni.showModal({
- // title: '提示',
- // content: isRefused ? '对方正忙' : '结束视频通话!',
- // showCancel: false,
- // confirmText: '好',
- // success: (res) => {
- // execExit()
- // },
- // fail: () => {
- // this.handleBack()
- // }
- // });
- // } else {
- // this.$refs.uToast.show({
- // type: 'default',
- // message: isRefused ? '对方正忙' : '结束视频通话!',
- // })
- // console.log('------------------------------------------ exec exit exec before')
- // execExit()
- // }
-
- // uni.redirectTo({
- // url: "/pages/response/index"
- // })
- },
- // 删除this.engine对象, 删除即构
- async destroyEngine() {
- this.engine = undefined;
- ZegoExpressEngine.destroyEngine();
- },
- handleBack() {
- const pages = getCurrentPages();
- if (pages.length < 3) {
- uni.switchTab({
- url: '/pages/response/index',
- success(res) {
- console.warn(res, '返回上一页成功,当前页面:视频通话页面 ')
- },
- fail(err) {
- console.error(err)
- },
- complete() {
- console.warn('返回上一页执行完成,当前页面:视频通话页面 ')
- }
- })
- } else {
- uni.navigateBack({
- delta: 1
- })
- }
- }
- },
- async onLoad(optinos) {
- console.log('onload -------------- 1213', this.isVideoCallRefused)
- if (this.isVideoCallRefused) {
- this.$refs.uToast.show({
- type: 'default',
- message: '对方正忙',
- })
-
- setTimeout(() => {
- this.handleBack();
- }, 1500)
- // uni.showModal({
- // title: '提示',
- // content: '对方正忙',
- // showCancel: false,
- // confirmText: '好',
- // success: (res) => {
- // setTimeout(() => {
- // this.handleBack();
- // }, 1500)
- // },
- // fail: () => {
- // this.handleBack()
- // }
- // });
- return
- }
- var that = this
- that.videoObj = JSON.parse(optinos.videoObj)
- // // console.log(that.videoObj)
- // // 即构 - 视频通话
- // // 获取系统信息同步接口
- if (uni.getSystemInfoSync().platform === 'android') {
- await permision.requestAndroidPermission('android.permission.RECORD_AUDIO');
- await permision.requestAndroidPermission('android.permission.CAMERA');
- }
- await this.setup()
- this.onPublish(); // 推流
- uni.getSystemInfo({ //异步获取。
- success(res) {
- // that.phoneHeight = res.windowHeight - 13; //窗口高度
- that.phoneHeight = res.windowHeight; //窗口高度
- }
- });
- },
- async onShow() {
- await this.setup();
- },
- // 监听页面返回
- onBackPress() {
- console.log('返回了!')
- this.offVideo(); // 挂断退出
- this.destroyEngine(); // 删除this.engine对象,删除即构
- },
- // 页面卸载 - 生命周期
- onUnload() {
- this.updateTalkingStatus(false);
- this.destroyEngine();
- console.log('onUnload');
- },
- }
- </script>
- <style lang="scss">
- .video_box {
- background: #000;
- width: 1200rpx;
- position: relative;
- z-index: 0;
- // .video_you {
- .video_me {
- background: #000;
- width: 150px;
- height: 200px;
- position: fixed;
- right: 0;
- top: 65px;
- z-index: 2000;
- }
- .video_you {
- background: #000;
- width: 1200rpx;
- height: 600rpx;
- position: absolute;
- right: 0;
- bottom: 0;
- z-index: 1;
- }
- .video_btn {
- position: fixed;
- bottom: 35rpx;
- left: 0;
- width: 750rpx;
- .video_imgList {
- display: flex;
- flex-direction: row;
- justify-content: space-around;
- // 翻转
- .video_imgList1 {
- .video_view {
- background: rgba(0, 0, 0, .5);
- border-radius: 50px;
- width: 50px;
- height: 50px;
- margin: 0 auto;
- .video_view_img {
- height: 15px;
- width: 20px;
- margin: 36rpx 0 0 33rpx;
- }
- }
- .video_view_txt {
- color: #fff;
- font-size: 14px;
- line-height: 30px;
- text-align: center;
- }
- }
- // 语音通话
- .video_imgList2 {
- .video_view {
- background: rgba(0, 0, 0, .5);
- border-radius: 50px;
- width: 50px;
- height: 50px;
- margin: 0 0 0 30rpx;
- .video_view_img {
- height: 25px;
- width: 25px;
- margin: 24rpx 0 0 25rpx;
- }
- }
- .video_view_txt {
- color: #fff;
- font-size: 14px;
- line-height: 30px;
- text-align: center;
- }
- }
- }
- }
- }
- </style>
|