Files
im-system/hd-glasses-app/src/pages/call_room.vue
2023-11-09 11:12:08 +08:00

517 lines
15 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="videoRoomContainer">
<div class="wrapper">
<video ref="videoStreamtopVideo" width="100%" autoplay></video>
<div class="swiper-container">
<div class="swiper-wrapper">
<template v-for="(item,index) in videoRoomSteamList">
<div :key="item.webrtcUrl" class="swiper-slide">
<video class="remoteVideo" :ref="'videoStream'+item.publishId" width="100%" autoplay
@click="videoClickAction(item.publishId)"></video>
</div>
</template>
</div>
</div>
<div class="actionBtnList">
<div @click="closeVoice">
<div class="actionBtn">
<img :src="voiceImg">
</div>
</div>
<div @click="closeCamera">
<div class="actionBtn">
<img :src="cameraImg">
</div>
</div>
<div @click="switchCamera">
<div class="actionBtn">
<img :src="switchCameraImg">
</div>
</div>
<div @click="videoDownAction">
<div class="actionBtn callDownBox">
<img :src="callDwonImg">
</div>
</div>
</div>
</div>
<!-- <video ref="localVideo" id="rtc_media_local_player" width="310" autoplay muted controls></video>-->
<!-- <van-button type="primary" @click="playVideo">主要按钮</van-button>-->
<!-- <van-button type="primary" @click="beginPublish">开始推流</van-button>-->
</div>
</template>
<script>
import axios from "axios";
import Swiper from 'swiper'; // 注意引入的是Swiper
import 'swiper/css/swiper.min.css' // 注意这里的引入
import {Notify, Dialog} from 'vant';
import {getStatisFileUrl} from '../utils/publicFun'
/* eslint-disable */
export default {
name: "call_room",
data() {
return {
value: "webrtc://119.45.242.222/live/livestream123",
isPublish: 0,
isPlayer: 0,
uid: 0,
roomId: 0,
roomTimer: null,
topVideo: "",
videoRoomSteamList: [],
oldVideoStreamList: [],
swiperInstance: null,
publishSdk: null,
publistUrl: "",
constraints: {
audio: true,
video: {
// deviceId: {
// exact: "136e115ef37b7ec8361207a61d42cd39818381aa0e99728e35eb9746bedce6b4"
// },
width: {ideal: 320, max: 576}
}
},
cameraDevices: [],
cameraIndex: 0,
isCloseCamera: false,
isCloseVoice: false,
voiceImg: "",
cameraImg: "",
switchCameraImg: "",
callDwonImg: "",
showConfirmDialog: 0,
inviteName: 0,
showInviteConfirmDialog: 0,
};
},
mounted() {
console.log(location.href)
console.log(location.href)
console.log(location.href)
this.isPublish = this.$route.query.isPublish;
this.isPlayer = this.$route.query.isPlayer;
this.uid = this.$route.query.uid;
this.roomId = this.$route.query.room;
this.inviteName = this.$route.query.inviteName || '';
this.topVideo = this.uid;
this.showConfirmDialog = this.$route.query.showConfirmDialog;
this.showInviteConfirmDialog = this.$route.query.showInviteConfirmDialog;
this.voiceImg = getStatisFileUrl("/media/voice_open.png")
this.cameraImg = getStatisFileUrl("/media/camera_open.png")
this.switchCameraImg = getStatisFileUrl("/media/switch.png")
this.callDwonImg = getStatisFileUrl("/media/call_down.png")
this.token = this.$route.query.token || "";
if (this.token > 10) {
localStorage.setItem("hd_token", this.token)
}
if (this.showConfirmDialog == 1) {
Dialog.confirm({
title: '是否接受?',
message: `${this.inviteName}邀请你加入视频聊天`,
})
.then(() => {
this.init();
// on confirm
})
.catch(() => {
location.href = "uniwebview://action?function=refuseVideoInvite";
// on cancel
});
} else if (this.showInviteConfirmDialog == 1) {
Dialog.confirm({
title: '提示',
message: `确认是否发起视频聊天?`,
})
.then(() => {
this.init();
// on confirm
})
.catch(() => {
window.history.go(-1);
// on cancel
});
} else {
this.init();
}
},
beforeDestroy() {
clearInterval(this.roomTimer);
this.roomTimer = null;
this.leaveRoom();
},
methods: {
init() {
Notify({
message: '如视频不能播放,请点击视频列表中对应的用户上方的小视频',
duration: 10000,
type: 'primary'
});
if (this.isPublish == 1) {
this.beginPublish()
}
if (this.isPlayer == 1) {
this.getRoomVideoList();
this.roomTimer = setInterval(() => {
this.getRoomVideoList();
}, 2000)
}
this.swiperInstance = new Swiper('.swiper-container', {
slidesPerView: 4,
spaceBetween: 30,
observer: true,
on: {},
})
},
closeVoice() {
this.constraints.audio = false;
//如果声音是开启状态
if (!this.isCloseVoice) {
// 关闭声音
this.isCloseVoice = true
this.voiceImg = getStatisFileUrl("/media/voice_close.png")
} else {
// 打开声音
this.isCloseVoice = false;
this.constraints.audio = true
this.voiceImg = getStatisFileUrl("/media/voice_open.png")
}
this.beginPublish()
},
closeCamera() {
this.constraints.video = false;
//如果视频是开启状态
if (!this.isCloseCamera) {
this.constraints.video = false
this.isCloseCamera = true
this.cameraImg = getStatisFileUrl("/media/camera_close.png")
} else {
let deviceId = {
exact: ""
}
deviceId.exact = this.cameraDevices[this.cameraIndex].deviceId
this.constraints.video = {}
this.constraints.video.deviceId = deviceId
this.isCloseCamera = false
this.cameraImg = getStatisFileUrl("/media/camera_open.png")
}
this.beginPublish()
},
switchCamera() {
let self = this;
self.cameraIndex = self.cameraIndex + 1 == self.cameraDevices.length ? 0 : self.cameraIndex + 1
let deviceId = {
exact: ""
}
deviceId.exact = self.cameraDevices[self.cameraIndex].deviceId
self.constraints.video.deviceId = deviceId
this.beginPublish()
},
gotDevices(deviceInfos) {
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'audioinput') {
// console.log(option)
// console.log(deviceInfo)
} else if (deviceInfo.kind === 'audiooutput') {
// console.log(option)
// console.log(deviceInfo)
} else if (deviceInfo.kind === 'videoinput') {
this.cameraDevices.push(deviceInfo)
} else {
console.log('Some other kind of source/device: ', deviceInfo);
}
}
},
handleError(error) {
console.log('navigator.getUserMedia error: ', error);
},
beginPublish() {
let _this = this;
//http://localhost:8080/hd-glasses-app/#/call_room?isPublish=1&isPlayer=1&uid=123&room=call_room
// var query = parse_query_string();
const publistUrl = process.env.VUE_APP_SRS_URL + this.roomId + "/" + this.uid;
_this.publistUrl = publistUrl;
// srs_init_rtc("#txt_url", publistUrl);
navigator.mediaDevices.enumerateDevices().then(this.gotDevices).catch(this.handleError);
if (_this.publishSdk) {
_this.publishSdk.close();
}
_this.publishSdk = null;
_this.publishSdk = new SrsRtcPublisherAsync();
// 绑定本地视频流
// const localVideo = this.$refs.localVideo;
// localVideo.srcObject = null;
// localVideo.srcObject = sdk.stream;
_this.publishSdk.publish(publistUrl, _this.constraints).then((session) => {
_this.joinRoom()
}).catch(function (reason) {
console.error(reason)
// Throw by sdk.
// See https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#exceptions
if (reason instanceof DOMException) {
if (reason.name === 'NotFoundError') {
alert(`找不到麦克风和摄像头设备getUserMedia ${reason.name} ${reason.message}`);
} else if (reason.name === 'NotAllowedError') {
alert(`你禁止了网页访问摄像头和麦克风getUserMedia ${reason.name} ${reason.message}`);
} else if (['AbortError', 'NotAllowedError', 'NotFoundError', 'NotReadableError', 'OverconstrainedError', 'SecurityError', 'TypeError'].includes(reason.name)) {
alert(`getUserMedia ${reason.name} ${reason.message}`);
}
}
_this.publishSdk.close();
console.error(reason);
});
},
playVideo(publishId = "", url = "") {
let _this = this;
let sdk = null;
let video = null;
// const _key=`${}`
video = eval('this.$refs.videoStream' + publishId)[0]
// const video = this.$refs[_key];
if (video.srcObject != null) {
return false;
}
// console.warn(video.srcObject )
// console.warn(video.srcObject )
// console.warn(video.srcObject )
// console.warn(video.srcObject )
// console.warn(video.srcObject )
var query = parse_query_string();
srs_init_rtc("#txt_url", this.value);
if (sdk) {
sdk.close();
}
sdk = new SrsRtcPlayerAsync();
if (this.topVideo == publishId) {
const topVideo = this.$refs.videoStreamtopVideo
topVideo.srcObject = sdk.stream;
topVideo.onloadedmetadata = function (e) {
topVideo.volume = 0
topVideo.play();
};
}
video.srcObject = sdk.stream;
video.onloadedmetadata = function (e) {
if (publishId == _this.uid)
video.volume = 0
video.play();
};
// $('#rtc_media_player').prop('srcObject', sdk.stream);
// Optional callback, SDK will add track to stream.
// sdk.ontrack = function (event) { console.log('Got track', event); sdk.stream.addTrack(event.track); };
// For example: webrtc://r.ossrs.net/live/livestream
// var url = this.value
sdk.play(url).then(function (session) {
// $('#sessionid').html(session.sessionid);
// $('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
}).catch(function (reason) {
sdk.close();
$('#rtc_media_player').hide();
console.error(reason);
});
},
getRoomVideoList() {
axios({
method: "post",
url: process.env.VUE_APP_IM_API_URL + "/room/getRoomInfo",
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
// mode: 'no-cors',
data: {
roomId: this.roomId
},
}).then(res => {
if (res.status == 200) {
this.generateVideoRoomStream(res.data.data)
}
})
},
leaveRoom() {
axios({
method: "post",
url: process.env.VUE_APP_IM_API_URL + "/room/leaveRoom",
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
data: {
roomId: this.roomId,
publishId: this.uid,
type: 'webrtc'
},
}).then(res => {
console.log(res)
})
},
joinRoom() {
axios({
method: "post",
url: process.env.VUE_APP_IM_API_URL + "/room/joinRoom",
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
// mode: 'no-cors',
data: {
roomId: this.roomId,
publishId: this.uid,
type: 'webrtc',
webrtcUrl: process.env.VUE_APP_SRS_URL + this.roomId + "/" + this.uid
},
}).then(res => {
console.log(res)
})
},
generateVideoRoomStream(videoList) {
let hasUpdate = false;
if (this.oldVideoStreamList == null) {
this.oldVideoStreamList = videoList;
} else {
if (JSON.stringify(this.oldVideoStreamList) != JSON.stringify(videoList)) {
hasUpdate = true
}
}
this.oldVideoStreamList = videoList;
this.videoRoomSteamList = videoList;
setTimeout(() => {
videoList.map((item) => {
this.playVideo(item.publishId, item.webrtcUrl)
})
if (hasUpdate) {
this.swiperInstance.update();
console.log("数据有变化更新swipper")
//视频流有变化,检查置顶用户是否以及走掉
this.updateTopVideoStream();
}
}, 1000)
//videoSteamList
},
videoClickAction(publishId) {
this.topVideo = publishId;
var video = eval('this.$refs.videoStream' + publishId)[0]
video.play();
console.log(video.srcObject)
this.$refs.videoStreamtopVideo.srcObject = video.srcObject;
},
//讲列表有人下线判断top流是否正常如果不正常则把列表第一个移到Top
updateTopVideoStream() {
console.log(this.$refs.videoStreamtopVideo.srcObject)
let topVideo = this.oldVideoStreamList.find(item => item.publishId == this.topVideo)
//如果置顶用户已经走掉,则把用户自己的视频置顶
if (topVideo == undefined) {
var video = eval('this.$refs.videoStream' + this.uid)[0]
this.$refs.videoStreamtopVideo.srcObject = video.srcObject;
}
},
videoDownAction() {
location.href = "uniwebview://action?function=restartCamera";
this.publishSdk.close();
if (this.showConfirmDialog == 1) {
console.log("挂断视频")
location.href = "uniwebview://action?function=refuseVideoInvite";
} else {
window.history.go(-1);
}
}
}
}
</script>
<style lang="less">
.videoRoomContainer {
width: 100vw;
height: 100vh;
background-color: #333030;
}
.slide {
height: 200px;
width: 200px;
}
.swiper-slide {
background: #000000;
width: 200px;
height: 180px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-right: 20px;
.remoteVideo {
width: 100%;
height: auto;
}
}
.actionBtnList {
margin-top: 50px;
display: flex;
flex-direction: row;
justify-content: space-around;
font-size: 16px;
.actionBtn {
width: 100px;
height: 100px;
border-radius: 100%;
background: #000000;
display: flex;
justify-content: center;
align-items: center;
img {
width: 50%;
height: 50%;
}
}
}
.callDownBox {
background: #DA4C4B !important;
}
</style>