Browse Source

视频聊天功能-开发中

master
xie.bx 3 years ago
parent
commit
43b6c5e27d
  1. 86
      im-ui/src/components/chat/ChatPrivateVideo.vue
  2. 2
      im-ui/src/components/chat/VideoAcceptor.vue
  3. 1
      im-ui/src/main.js

86
im-ui/src/components/chat/ChatPrivateVideo.vue

@ -1,17 +1,20 @@
<template> <template>
<el-dialog :title="title" :visible.sync="visible" width="800px" :before-close="handleClose"> <el-dialog v-dialogDrag :title="title" top="5vh"
:close-on-click-modal="false"
:close-on-press-escape="false"
:visible.sync="visible" width="50%" height="70%" :before-close="handleClose">
<div class="chat-video"> <div class="chat-video">
<div class="chat-video-box"> <div class="chat-video-box">
<div class="chat-video-friend" v-loading="loading" element-loading-text="等待对方接听..." element-loading-spinner="el-icon-loading" <div class="chat-video-friend" v-loading="loading" element-loading-text="等待对方接听..." element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.9)"> element-loading-background="rgba(0, 0, 0, 0.5)">
<head-image class="friend-head-image" :id="this.friend.id" :size="80" :url="this.friend.headImage"></head-image>
<video ref="friendVideo" autoplay=""></video> <video ref="friendVideo" autoplay=""></video>
</div> </div>
<div class="chat-video-mine"> <div class="chat-video-mine">
<video ref="mineVideo" autoplay=""></video> <video ref="mineVideo" autoplay=""></video>
</div> </div>
</div> </div>
<div class="chat-video-controllbar"> <div class="chat-video-controllbar">
<div v-show="state=='CONNECTING'" title="取消呼叫" class="icon iconfont icon-phone-reject reject" style="color: red;" <div v-show="state=='CONNECTING'" title="取消呼叫" class="icon iconfont icon-phone-reject reject" style="color: red;"
@click="cancel()"></div> @click="cancel()"></div>
<div v-show="state=='CONNECTED'" title="挂断" class="icon iconfont icon-phone-reject reject" style="color: red;" <div v-show="state=='CONNECTED'" title="挂断" class="icon iconfont icon-phone-reject reject" style="color: red;"
@ -24,8 +27,11 @@
</template> </template>
<script> <script>
import HeadImage from '../common/HeadImage.vue';
export default { export default {
name: 'chatVideo', name: 'chatVideo',
components: {HeadImage},
props: { props: {
visible: { visible: {
type: Boolean type: Boolean
@ -45,6 +51,8 @@
stream: null, stream: null,
loading: false, loading: false,
peerConnection: null, peerConnection: null,
videoTime: 0,
videoTimer: null,
state: 'NOT_CONNECTED', state: 'NOT_CONNECTED',
candidates: [], candidates: [],
configuration: { configuration: {
@ -73,7 +81,6 @@
} }
return; return;
} }
// //
this.openCamera((stream) => { this.openCamera((stream) => {
// webrtc // webrtc
@ -85,14 +92,7 @@
// //
this.accept(this.offer); this.accept(this.offer);
} }
this.timerx && clearInterval(this.timerx);
this.timerx = setInterval(() => {
console.log(this.peerConnection.iceConnectionState);
console.log(this.peerConnection.iceGatheringState);
}, 3000)
}); });
}, },
openCamera(callback) { openCamera(callback) {
navigator.getUserMedia({ navigator.getUserMedia({
@ -112,7 +112,6 @@
}, },
closeCamera() { closeCamera() {
if (this.stream) { if (this.stream) {
this.stream.getTracks().forEach((track) => { this.stream.getTracks().forEach((track) => {
track.stop(); track.stop();
}); });
@ -143,8 +142,12 @@
this.peerConnection.addTrack(track, stream); this.peerConnection.addTrack(track, stream);
}); });
} }
this.peerConnection.oniceconnectionstatechange = function(event) { this.peerConnection.oniceconnectionstatechange = (event) => {
console.log("ICE connection status changed : " + event.target.iceConnectionState) let state = event.target.iceConnectionState;
console.log("ICE connection status changed : " + state)
if(state == 'connected'){
this.resetTime();
}
}; };
}, },
@ -258,13 +261,21 @@
this.closeCamera(); this.closeCamera();
this.loading = false; this.loading = false;
this.state = 'NOT_CONNECTED'; this.state = 'NOT_CONNECTED';
this.videoTime = 0;
this.videoTimer && clearInterval(this.videoTimer);
this.candidates = []; this.candidates = [];
this.$store.commit("setUserState", this.$enums.USER_STATE.FREE); this.$store.commit("setUserState", this.$enums.USER_STATE.FREE);
this.$refs.friendVideo.srcObject = null; this.$refs.friendVideo.srcObject = null;
this.peerConnection.close(); this.peerConnection.close();
this.peerConnection.onicecandidate = null; this.peerConnection.onicecandidate = null;
this.peerConnection.onaddstream = null; this.peerConnection.onaddstream = null;
},
resetTime(){
this.videoTime = 0;
this.videoTimer && clearInterval(this.videoTimer);
this.videoTimer = setInterval(()=>{
this.videoTime++;
},1000)
}, },
handleClose() { handleClose() {
if (this.state == 'CONNECTED') { if (this.state == 'CONNECTED') {
@ -286,6 +297,7 @@
window.RTCIceCandidate = window.RTCIceCandidate || window.webkitRTCIceCandidate || window.mozRTCIceCandidate; window.RTCIceCandidate = window.RTCIceCandidate || window.webkitRTCIceCandidate || window.mozRTCIceCandidate;
return !!window.RTCPeerConnection; return !!window.RTCPeerConnection;
} }
}, },
watch: { watch: {
visible: { visible: {
@ -294,43 +306,67 @@
this.init(); this.init();
// //
this.$store.commit("setUserState", this.$enums.USER_STATE.BUSY); this.$store.commit("setUserState", this.$enums.USER_STATE.BUSY);
console.log(this.$store.state.userStore.state)
} }
} }
} }
}, },
computed: { computed: {
title() { title() {
return `视频聊天-${this.friend.nickName}`; let strTitle = `视频聊天-${this.friend.nickName}`;
if(this.state == 'CONNECTED'){
strTitle += `(${this.currentTime})`;
}
return strTitle;
},
currentTime(){
let currentTime = 0;
if(this.state == 'CONNECTED' && this.videoTime){
currentTime = Math.floor(this.videoTime);
}
let min = Math.floor(currentTime/60);
let sec = currentTime%60;
let strTime = min<10?"0":"";
strTime += min;
strTime += ":"
strTime += sec<10?"0":"";
strTime += sec;
return strTime;
} }
} }
} }
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.chat-video { .chat-video {
position: relative;
.chat-video-box { .chat-video-box {
position: relative; position: relative;
border: #2C3E50 solid 1px; border: #4880b9 solid 1px;
background-color: #eeeeee; background-color: #eeeeee;
.chat-video-friend { .chat-video-friend {
height: 600px; height: 70vh;
.friend-head-image {
position: absolute;
}
video { video {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: fill;
} }
} }
.chat-video-mine { .chat-video-mine {
position: absolute; position: absolute;
z-index: 99999; z-index: 99999;
width: 200px; width: 25vh;
right: 0; right: 0;
bottom: 0; bottom: 0;
box-shadow: 0px 0px 5px #ccc;
background-color: #cccccc;
video { video {
width: 100%; width: 100%;
} }

2
im-ui/src/components/chat/VideoAcceptor.vue

@ -93,7 +93,7 @@
bottom: 1px; bottom: 1px;
width: 250px; width: 250px;
height: 250px; height: 250px;
padding: 10px; padding: 20px;
text-align: center; text-align: center;
background-color: #eeeeee; background-color: #eeeeee;
border: #dddddd solid 1px; border: #dddddd solid 1px;

1
im-ui/src/main.js

@ -10,6 +10,7 @@ import emotion from './api/emotion.js';
import element from './api/element.js'; import element from './api/element.js';
import store from './store'; import store from './store';
import * as enums from './api/enums.js'; import * as enums from './api/enums.js';
import './utils/directive/dialogDrag';
Vue.use(ElementUI); Vue.use(ElementUI);

Loading…
Cancel
Save