517 lines
15 KiB
Vue
517 lines
15 KiB
Vue
<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>
|