feat:
This commit is contained in:
parent
83089af7c7
commit
8af84d8f2d
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ dist/
|
|||||||
**/dist
|
**/dist
|
||||||
**/yarn-error.log
|
**/yarn-error.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.idea
|
||||||
|
9
.idea/markdown.xml
generated
Normal file
9
.idea/markdown.xml
generated
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MarkdownSettings">
|
||||||
|
<enabledExtensions>
|
||||||
|
<entry key="MermaidLanguageExtension" value="true" />
|
||||||
|
<entry key="PlantUMLLanguageExtension" value="true" />
|
||||||
|
</enabledExtensions>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -3,108 +3,109 @@ const koaSend = require('koa-send');
|
|||||||
const statics = require('koa-static');
|
const statics = require('koa-static');
|
||||||
const socket = require('socket.io');
|
const socket = require('socket.io');
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
|
|
||||||
const port = 3000;
|
const httpPort = 8765;
|
||||||
const app = new Koa();
|
const app = new Koa();
|
||||||
|
|
||||||
|
|
||||||
app.use(statics(
|
app.use(statics(
|
||||||
path.join( __dirname, './dist')
|
path.join(__dirname, './dist')
|
||||||
));
|
));
|
||||||
app.use(async (ctx, next) => {
|
app.use(async (ctx, next) => {
|
||||||
if (!/\./.test(ctx.request.url)) {
|
if (!/\./.test(ctx.request.url)) {
|
||||||
await koaSend(
|
await koaSend(
|
||||||
ctx,
|
ctx,
|
||||||
'index.html',
|
'index.html',
|
||||||
{
|
{
|
||||||
root: path.join(__dirname, './'),
|
root: path.join(__dirname, './'),
|
||||||
maxage: 1000 * 60 * 60 * 24 * 7,
|
maxage: 1000 * 60 * 60 * 24 * 7,
|
||||||
gzip: true,
|
gzip: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await next();
|
await next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const httpServer = http.createServer(app.callback()).listen(port, ()=>{
|
const httpServer = http.createServer(app.callback()).listen(httpPort, () => {
|
||||||
console.log('httpServer app started at port ...' + port);
|
console.log('httpServer app started at port ...' + httpPort);
|
||||||
|
});
|
||||||
|
|
||||||
|
const httpIo = socket(httpServer, {
|
||||||
|
ioOptions: {
|
||||||
|
pingTimeout: 10000,
|
||||||
|
pingInterval: 5000,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const options = {
|
|
||||||
ioOptions: {
|
|
||||||
pingTimeout: 10000,
|
|
||||||
pingInterval: 5000,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const httpIo = socket(httpServer, options);
|
|
||||||
// Record<roomId, { userName: string; roomId: string; socketId: string }>
|
// Record<roomId, { userName: string; roomId: string; socketId: string }>
|
||||||
const rooms = {};
|
const rooms = {};
|
||||||
// Record<socketId, sock>
|
// Record<socketId, sock>
|
||||||
const socks = {};
|
const socks = {};
|
||||||
const httpConnectIoCallBack = (sock) => {
|
const httpConnectIoCallBack = (sock) => {
|
||||||
console.log(`sockId:${sock.id}连接成功!!!`);
|
console.log(`sockId:${sock.id}连接成功!!!`);
|
||||||
sock.emit('connectionSuccess', sock.id);
|
sock.emit('connectionSuccess', sock.id);
|
||||||
// 用户断开连接
|
// 用户断开连接
|
||||||
sock.on('userLeave', ({ userName, roomId, sockId} = user)=> {
|
sock.on('userLeave', ({ userName, roomId, sockId } = user) => {
|
||||||
console.log(`userName:${userName}, roomId:${roomId}, sockId:${sockId} 断开了连接...`);
|
console.log(`userName:${userName}, roomId:${roomId}, sockId:${sockId} 断开了连接...`);
|
||||||
if (roomId && rooms[roomId] && rooms[roomId].length) {
|
if (roomId && rooms[roomId] && rooms[roomId].length) {
|
||||||
rooms[roomId] = rooms[roomId].filter(item => item.sockId!==sockId);
|
rooms[roomId] = rooms[roomId].filter(item => item.sockId !== sockId);
|
||||||
httpIo.in(roomId).emit('userLeave', rooms[roomId]);
|
httpIo.in(roomId).emit('userLeave', rooms[roomId]);
|
||||||
console.log(`userName:${userName}, roomId:${roomId}, sockId:${sockId} 离开了房间...`);
|
console.log(`userName:${userName}, roomId:${roomId}, sockId:${sockId} 离开了房间...`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// 用户加入房间
|
// 用户加入房间
|
||||||
sock.on('checkRoom', ({ userName, roomId, sockId})=> {
|
sock.on('checkRoom', ({ userName, roomId, sockId }) => {
|
||||||
rooms[roomId] = rooms[roomId] || [];
|
rooms[roomId] = rooms[roomId] || [];
|
||||||
sock.emit('checkRoomSuccess', rooms[roomId]);
|
sock.emit('checkRoomSuccess', rooms[roomId]);
|
||||||
if (rooms[roomId].length > 1) return false;
|
if (rooms[roomId].length > 1) return false;
|
||||||
rooms[roomId].push({ userName, roomId, sockId});
|
rooms[roomId].push({ userName, roomId, sockId });
|
||||||
sock.join(roomId, () => {
|
sock.join(roomId, () => {
|
||||||
httpIo.in(roomId).emit('joinRoomSuccess', rooms[roomId]);
|
httpIo.in(roomId).emit('joinRoomSuccess', rooms[roomId]);
|
||||||
socks[sockId] = sock;
|
socks[sockId] = sock;
|
||||||
console.log(`userName:${userName}, roomId:${roomId}, sockId:${sockId} 成功加入房间!!!`);
|
console.log(`userName:${userName}, roomId:${roomId}, sockId:${sockId} 成功加入房间!!!`);
|
||||||
});
|
|
||||||
});
|
|
||||||
// 发送视频
|
|
||||||
sock.on('toSendVideo', (user) => {
|
|
||||||
httpIo.in(user.roomId).emit('receiveVideo', user);
|
|
||||||
});
|
|
||||||
// 取消发送视频
|
|
||||||
sock.on('cancelSendVideo', (user) => {
|
|
||||||
httpIo.in(user.roomId).emit('cancelSendVideo', user);
|
|
||||||
});
|
|
||||||
// 接收视频邀请
|
|
||||||
sock.on('receiveVideo', (user) => {
|
|
||||||
httpIo.in(user.roomId).emit('receiveVideo', user);
|
|
||||||
});
|
|
||||||
// 拒绝接收视频
|
|
||||||
sock.on('rejectReceiveVideo', (user) => {
|
|
||||||
httpIo.in(user.roomId).emit('rejectReceiveVideo', user);
|
|
||||||
});
|
|
||||||
// 接听视频
|
|
||||||
sock.on('answerVideo', (user) => {
|
|
||||||
httpIo.in(user.roomId).emit('answerVideo', user);
|
|
||||||
});
|
|
||||||
// 挂断视频
|
|
||||||
sock.on('hangupVideo', (user) => {
|
|
||||||
httpIo.in(user.roomId).emit('hangupVideo', user);
|
|
||||||
});
|
|
||||||
// ======================================
|
|
||||||
// addIceCandidate
|
|
||||||
sock.on('addIceCandidate', (data) => {
|
|
||||||
const toUser = rooms[data.user.roomId].find(item=>item.sockId!==data.user.sockId);
|
|
||||||
console.log('addIceCandidate', toUser)
|
|
||||||
socks[toUser.sockId].emit('addIceCandidate', data.candidate);
|
|
||||||
});
|
|
||||||
sock.on('receiveOffer', (data) => {
|
|
||||||
const toUser = rooms[data.user.roomId].find(item=>item.sockId!==data.user.sockId);
|
|
||||||
socks[toUser.sockId].emit('receiveOffer', data.offer);
|
|
||||||
});
|
|
||||||
sock.on('receiveAnswer', (data) => {
|
|
||||||
const toUser = rooms[data.user.roomId].find(item=>item.sockId!==data.user.sockId);
|
|
||||||
socks[toUser.sockId].emit('receiveAnswer', data.answer);
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
// 发送视频
|
||||||
|
sock.on('toSendVideo', (user) => {
|
||||||
|
httpIo.in(user.roomId).emit('receiveVideo', user);
|
||||||
|
});
|
||||||
|
// 取消发送视频
|
||||||
|
sock.on('cancelSendVideo', (user) => {
|
||||||
|
httpIo.in(user.roomId).emit('cancelSendVideo', user);
|
||||||
|
});
|
||||||
|
// 接收视频邀请
|
||||||
|
sock.on('receiveVideo', (user) => {
|
||||||
|
httpIo.in(user.roomId).emit('receiveVideo', user);
|
||||||
|
});
|
||||||
|
// 拒绝接收视频
|
||||||
|
sock.on('rejectReceiveVideo', (user) => {
|
||||||
|
httpIo.in(user.roomId).emit('rejectReceiveVideo', user);
|
||||||
|
});
|
||||||
|
// 接听视频
|
||||||
|
sock.on('answerVideo', (user) => {
|
||||||
|
httpIo.in(user.roomId).emit('answerVideo', user);
|
||||||
|
});
|
||||||
|
// 挂断视频
|
||||||
|
sock.on('hangupVideo', (user) => {
|
||||||
|
httpIo.in(user.roomId).emit('hangupVideo', user);
|
||||||
|
});
|
||||||
|
// ======================================
|
||||||
|
// addIceCandidate
|
||||||
|
sock.on('addIceCandidate', (data) => {
|
||||||
|
const toUser = rooms[data.user.roomId].find(item => item.sockId !== data.user.sockId);
|
||||||
|
console.log('addIceCandidate', toUser)
|
||||||
|
socks[toUser.sockId].emit('addIceCandidate', data.candidate);
|
||||||
|
});
|
||||||
|
sock.on('receiveOffer', (data) => {
|
||||||
|
const toUser = rooms[data.user.roomId].find(item => item.sockId !== data.user.sockId);
|
||||||
|
socks[toUser.sockId].emit('receiveOffer', data.offer);
|
||||||
|
});
|
||||||
|
sock.on('receiveAnswer', (data) => {
|
||||||
|
const toUser = rooms[data.user.roomId].find(item => item.sockId !== data.user.sockId);
|
||||||
|
socks[toUser.sockId].emit('receiveAnswer', data.answer);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
httpIo.on('connection', httpConnectIoCallBack);
|
httpIo.on('connection', httpConnectIoCallBack);
|
||||||
|
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>webrtc-icon-192x192.png">
|
|
||||||
<title>webrtc-demo</title>
|
<title>webrtc-demo</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script src="<%= BASE_URL %>video-view.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 31 KiB |
@ -1,54 +1,64 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-room-wrapper">
|
<div class="m-room-wrapper">
|
||||||
<div class="can-support-rtc" v-if="canSupportVideo">
|
<div class="can-support-rtc" v-if="canSupportVideo">
|
||||||
<div class="form-area" v-if="showFormArea">
|
<div class="form-area" v-if="showFormArea">
|
||||||
<el-form
|
<el-form
|
||||||
:model="roomForm"
|
:model="roomForm"
|
||||||
:rules="rules"
|
:rules="rules"
|
||||||
ref="roomForm"
|
ref="roomForm"
|
||||||
label-width="100px"
|
label-width="100px"
|
||||||
class="room-form"
|
class="room-form"
|
||||||
>
|
>
|
||||||
<el-form-item label="房间ID" prop="roomId">
|
<el-form-item label="房间ID" prop="roomId">
|
||||||
<el-input v-model.trim="roomForm.roomId" :disabled="!canClickBtn"></el-input>
|
<el-input v-model.trim="roomForm.roomId" :disabled="!canClickBtn"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="姓名" prop="userName">
|
<el-form-item label="姓名" prop="userName">
|
||||||
<el-input v-model.trim="roomForm.userName" :disabled="!canClickBtn"></el-input>
|
<el-input v-model.trim="roomForm.userName" :disabled="!canClickBtn"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="submitForm" :disabled="!canClickBtn">加入房间</el-button>
|
<el-button type="primary" @click="submitForm" :disabled="!canClickBtn">加入房间</el-button>
|
||||||
<el-button @click="resetForm">重置</el-button>
|
<el-button @click="resetForm">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
|
||||||
<div class="list-area" v-if="!showFormArea">
|
|
||||||
<h2>当前房间id: {{ roomForm.roomId }} </h2>
|
|
||||||
<h2>在线人数: {{ roomUsers.length }} </h2>
|
|
||||||
<el-card class="box-card">
|
|
||||||
<div v-for="item in roomUsers" :key="item.sockId" class="item">
|
|
||||||
{{ item.userName }}
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<el-button type="primary" v-if="roomUsers.length > 1 && sockId" @click="toSendVideo">
|
|
||||||
发起视频
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div class="list-area" v-if="!showFormArea">
|
||||||
<h1>当前域名的浏览器不支持WebRTC!</h1>
|
<h2>当前房间id: {{ roomForm.roomId }} </h2>
|
||||||
|
<h2>在线人数: {{ roomUsers.length }} </h2>
|
||||||
|
<el-card class="box-card">
|
||||||
|
<div v-for="item in roomUsers" :key="item.sockId" class="item">
|
||||||
|
{{ item.userName }}
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-button type="primary" v-if="roomUsers.length > 1 && sockId" @click="toSendVideo">
|
||||||
|
发起视频
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<Video
|
||||||
|
:showStartVideoByReceiver="showStartVideoByReceiver"
|
||||||
|
:showStartVideoBySender="showStartVideoBySender"
|
||||||
|
:showVideo="showVideo"
|
||||||
|
@cancelSendVideo="cancelSendVideo"
|
||||||
|
@cancelReceiveVideo="cancelReceiveVideo"
|
||||||
|
@hangupVideo="hangUpVideo"
|
||||||
|
@answerVideo="answerVideo"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<h1>当前域名的浏览器不支持WebRTC!</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import socket from '../utils/socket.js';
|
import socket from '../utils/socket.js';
|
||||||
|
import Video, { setRemoteSteam, setLocalStream } from '@/pages/Video';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Room',
|
name: 'Room',
|
||||||
|
components: { Video },
|
||||||
created () {
|
created () {
|
||||||
if (this.canSupportWebRTC()) {
|
if (this.canSupportWebRTC()) {
|
||||||
this.initSocketEvents();
|
this.initSocketEvents();
|
||||||
this.initVIDEO_VIEWSdk();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@ -68,6 +78,10 @@ export default {
|
|||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
showFormArea: true,
|
showFormArea: true,
|
||||||
|
showVideo: false,
|
||||||
|
showStartVideoByReceiver: null,
|
||||||
|
showStartVideoBySender: null,
|
||||||
|
remoteStream: null,
|
||||||
roomForm: {
|
roomForm: {
|
||||||
roomId: '',
|
roomId: '',
|
||||||
userName: ''
|
userName: ''
|
||||||
@ -137,7 +151,7 @@ export default {
|
|||||||
async getDevices () {
|
async getDevices () {
|
||||||
try {
|
try {
|
||||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
VIDEO_VIEW.showDevicesNameByDevices(devices);
|
console.log('devices', devices);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
const msg = `getDevices error: ${error.name} : ${error.message}`;
|
const msg = `getDevices error: ${error.name} : ${error.message}`;
|
||||||
@ -206,7 +220,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
// TODO: 挂断视频 0-0
|
// TODO: 挂断视频 0-0
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
});
|
});
|
||||||
socket.on('disconnect', (message) => {
|
socket.on('disconnect', (message) => {
|
||||||
this.showFormArea = true;
|
this.showFormArea = true;
|
||||||
@ -214,7 +228,7 @@ export default {
|
|||||||
console.log('client sock disconnect:', message);
|
console.log('client sock disconnect:', message);
|
||||||
socket.emit('userLeave', this.user);
|
socket.emit('userLeave', this.user);
|
||||||
// TODO: 挂断视频 0-0
|
// TODO: 挂断视频 0-0
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
});
|
});
|
||||||
// ================== 视频相关 =====================
|
// ================== 视频相关 =====================
|
||||||
|
|
||||||
@ -222,31 +236,41 @@ export default {
|
|||||||
socket.on('cancelSendVideo', (user) => {
|
socket.on('cancelSendVideo', (user) => {
|
||||||
const infoTips = user.sockId === this.sockId ? '您取消了发送视频' : '对方取消了发送视频';
|
const infoTips = user.sockId === this.sockId ? '您取消了发送视频' : '对方取消了发送视频';
|
||||||
this.$message.info(infoTips);
|
this.$message.info(infoTips);
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
});
|
});
|
||||||
// 接收视频邀请
|
// 接收视频邀请
|
||||||
socket.on('receiveVideo', (sender) => {
|
socket.on('receiveVideo', (sender) => {
|
||||||
if (this.user.sockId === sender.sockId) return false;
|
if (this.user.sockId === sender.sockId) return false;
|
||||||
VIDEO_VIEW.showReceiveVideoModalBySender(sender);
|
this.showStartVideoBySender = sender;
|
||||||
});
|
});
|
||||||
// 拒绝接收视频
|
// 拒绝接收视频
|
||||||
socket.on('rejectReceiveVideo', (user) => {
|
socket.on('rejectReceiveVideo', (user) => {
|
||||||
const infoTips = user.sockId === this.sockId ? '您拒绝了接收视频' : '对方拒绝了接收视频';
|
const infoTips = user.sockId === this.sockId ? '您拒绝了接收视频' : '对方拒绝了接收视频';
|
||||||
this.$message.info(infoTips);
|
this.$message.info(infoTips);
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
});
|
});
|
||||||
// 接听视频
|
// 接听视频
|
||||||
socket.on('answerVideo', async (user) => {
|
socket.on('answerVideo', async (user) => {
|
||||||
VIDEO_VIEW.showInvideoModal();
|
this.showVideo = true;
|
||||||
// 创建本地视频流信息
|
// 创建本地视频流信息
|
||||||
this.localStream = await this.createLocalVideoStream();
|
this.localStream = await this.createLocalVideoStream();
|
||||||
document.querySelector('#echat-local').srcObject = this.localStream;
|
setLocalStream(this.localStream);
|
||||||
// Link: https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection
|
// Link: https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection
|
||||||
// RTCPeerConnection 接口代表一个由本地计算机到远端的 WebRTC 连接
|
// RTCPeerConnection 接口代表一个由本地计算机到远端的 WebRTC 连接
|
||||||
// 呼叫方发送一个 offer(请求),被呼叫方发出一个 answer(应答)来回答请求
|
// 呼叫方发送一个 offer(请求),被呼叫方发出一个 answer(应答)来回答请求
|
||||||
this.peer = new RTCPeerConnection();
|
this.peer = new RTCPeerConnection();
|
||||||
console.log(this.peer);
|
console.log(this.peer);
|
||||||
this.initPeerListen();
|
this.peer.onicecandidate = (event) => {
|
||||||
|
if (event.candidate) {
|
||||||
|
socket.emit('addIceCandidate', { candidate: event.candidate, user: this.user });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.peer.onaddstream = (event) => {
|
||||||
|
// 拿到对方的视频流
|
||||||
|
setRemoteSteam(event.stream);
|
||||||
|
};
|
||||||
|
this.peer.onclose = () => {
|
||||||
|
};
|
||||||
// Adding a local stream won't trigger the onaddstream callback
|
// Adding a local stream won't trigger the onaddstream callback
|
||||||
this.peer.addStream(this.localStream);
|
this.peer.addStream(this.localStream);
|
||||||
if (user.sockId === this.sockId) {
|
if (user.sockId === this.sockId) {
|
||||||
@ -266,9 +290,9 @@ export default {
|
|||||||
this.$message.info(infoTips);
|
this.$message.info(infoTips);
|
||||||
this.peer.close();
|
this.peer.close();
|
||||||
this.peer = null;
|
this.peer = null;
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
document.querySelector('#echat-remote-1').srcObject = null;
|
setRemoteSteam(null);
|
||||||
document.querySelector('#echat-local').srcObject = null;
|
setLocalStream(null);
|
||||||
});
|
});
|
||||||
//
|
//
|
||||||
socket.on('addIceCandidate', async (candidate) => {
|
socket.on('addIceCandidate', async (candidate) => {
|
||||||
@ -294,7 +318,7 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$refs.roomForm.validate((valid) => {
|
this.$refs.roomForm.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
// 检查该房间人数
|
// 检查该房间人数
|
||||||
this.canClickBtn = false;
|
this.canClickBtn = false;
|
||||||
socket.emit('checkRoom', {
|
socket.emit('checkRoom', {
|
||||||
roomId: this.roomForm.roomId,
|
roomId: this.roomForm.roomId,
|
||||||
@ -314,50 +338,26 @@ export default {
|
|||||||
// 发送视频
|
// 发送视频
|
||||||
toSendVideo () {
|
toSendVideo () {
|
||||||
socket.emit('toSendVideo', this.user);
|
socket.emit('toSendVideo', this.user);
|
||||||
VIDEO_VIEW.showStartVideoModalByReceiver(this.receiveUser);
|
this.showStartVideoByReceiver = this.receiveUser;
|
||||||
},
|
},
|
||||||
initVIDEO_VIEWSdk () {
|
hideAllVideoModal () {
|
||||||
const configOptios = {
|
this.showVideo = false;
|
||||||
startVideoCancelCb: this.startVideoCancelCb,
|
this.showStartVideoByReceiver = null;
|
||||||
receiveVideoCancelCb: this.receiveVideoCancelCb,
|
this.showStartVideoBySender = null;
|
||||||
receiveVideoAnswerCb: this.receiveVideoAnswerCb,
|
|
||||||
hangUpVideoCb: this.hangUpVideoCb,
|
|
||||||
openMikeCb: this.openMikeCb,
|
|
||||||
closeMikeCb: this.closeMikeCb,
|
|
||||||
openCammerCb: this.openCammerCb,
|
|
||||||
closeCammerCb: this.closeCammerCb,
|
|
||||||
toScreenCb: this.toScreenCb,
|
|
||||||
};
|
|
||||||
VIDEO_VIEW.configCallBack(configOptios);
|
|
||||||
},
|
},
|
||||||
startVideoCancelCb () {
|
cancelSendVideo () {
|
||||||
socket.emit('cancelSendVideo', this.user);
|
socket.emit('cancelSendVideo', this.user);
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
},
|
},
|
||||||
receiveVideoCancelCb () {
|
cancelReceiveVideo () {
|
||||||
socket.emit('rejectReceiveVideo', this.user);
|
socket.emit('rejectReceiveVideo', this.user);
|
||||||
VIDEO_VIEW.hideAllVideoModal();
|
this.hideAllVideoModal();
|
||||||
},
|
},
|
||||||
receiveVideoAnswerCb () {
|
answerVideo () {
|
||||||
socket.emit('answerVideo', this.user);
|
socket.emit('answerVideo', this.user);
|
||||||
},
|
},
|
||||||
hangUpVideoCb () {
|
hangUpVideo () {
|
||||||
socket.emit('hangupVideo', this.user);
|
socket.emit('hangupVideo', this.user);
|
||||||
},
|
|
||||||
openMikeCb () {
|
|
||||||
|
|
||||||
},
|
|
||||||
closeMikeCb () {
|
|
||||||
|
|
||||||
},
|
|
||||||
openCammerCb () {
|
|
||||||
|
|
||||||
},
|
|
||||||
closeCammerCb () {
|
|
||||||
|
|
||||||
},
|
|
||||||
toScreenCb () {
|
|
||||||
|
|
||||||
},
|
},
|
||||||
async createLocalVideoStream () {
|
async createLocalVideoStream () {
|
||||||
const constraints = { audio: true, video: true };
|
const constraints = { audio: true, video: true };
|
||||||
@ -366,29 +366,20 @@ export default {
|
|||||||
console.log('localStream:', localStream);
|
console.log('localStream:', localStream);
|
||||||
return localStream;
|
return localStream;
|
||||||
},
|
},
|
||||||
initPeerListen () {
|
|
||||||
this.peer.onicecandidate = (event) => {
|
|
||||||
if (event.candidate) { socket.emit('addIceCandidate', { candidate: event.candidate, user: this.user }); }
|
|
||||||
};
|
|
||||||
this.peer.onaddstream = (event) => {
|
|
||||||
// 拿到对方的视频流
|
|
||||||
document.querySelector('#echat-remote-1').srcObject = event.stream;
|
|
||||||
};
|
|
||||||
this.peer.onclose = () => {
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.m-room-wrapper{
|
.m-room-wrapper {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-room-wrapper .box-card {
|
.m-room-wrapper .box-card {
|
||||||
width: 480px;
|
width: 480px;
|
||||||
}
|
}
|
||||||
.m-room-wrapper .box-card .item{
|
|
||||||
padding: 18px 0;
|
.m-room-wrapper .box-card .item {
|
||||||
|
padding: 18px 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
111
webrtc-static/src/pages/Video.vue
Normal file
111
webrtc-static/src/pages/Video.vue
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
<template>
|
||||||
|
<div class="video">
|
||||||
|
<div v-if="showVideo">
|
||||||
|
<div class="videoWrapper">
|
||||||
|
<video autoplay class="remoteStream" id="remoteStream"></video>
|
||||||
|
<video autoplay class="localStream" id="localStream"></video>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button type="danger" @click="clickHangup">挂断</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!showVideo && showStartVideoByReceiver" class="modal">
|
||||||
|
<div class="desc">等待{{ showStartVideoByReceiver.userName }}接受视频通话邀请</div>
|
||||||
|
<div class="avatar">
|
||||||
|
<el-avatar icon="el-icon-user-solid"></el-avatar>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button type="danger" @click="cancelSendVideo">挂断</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!showVideo && showStartVideoBySender" class="modal">
|
||||||
|
<div class="avatar">
|
||||||
|
<el-avatar icon="el-icon-user-solid"></el-avatar>
|
||||||
|
</div>
|
||||||
|
<div class="desc">{{ showStartVideoBySender.userName }}邀请您进行视频通话</div>
|
||||||
|
<div>
|
||||||
|
<el-button type="primary" @click="clickAnswer">接听</el-button>
|
||||||
|
<el-button type="danger" @click="cancelReceiveVideo">挂断</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'VideoView',
|
||||||
|
props: ['devices', 'showVideo', 'showStartVideoByReceiver', 'showStartVideoBySender', 'remoteStream', 'localStream'],
|
||||||
|
methods: {
|
||||||
|
cancelSendVideo () {
|
||||||
|
this.$emit('cancelSendVideo');
|
||||||
|
},
|
||||||
|
cancelReceiveVideo () {
|
||||||
|
this.$emit('cancelReceiveVideo');
|
||||||
|
},
|
||||||
|
clickHangup () {
|
||||||
|
this.$emit('hangupVideo');
|
||||||
|
},
|
||||||
|
clickAnswer () {
|
||||||
|
this.$emit('answerVideo');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export function setLocalStream (stream) {
|
||||||
|
document.querySelector('#localStream').srcObject = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRemoteSteam (stream) {
|
||||||
|
document.querySelector('#remoteStream').srcObject = stream;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.video {
|
||||||
|
width: 500px;
|
||||||
|
height: 440px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
video {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.videoWrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 500px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.localStream {
|
||||||
|
width: 150px;
|
||||||
|
height: 100px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remoteStream {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,4 +1,4 @@
|
|||||||
import io from 'socket.io-client';
|
import io from 'socket.io-client';
|
||||||
const host = 'localhost:3000';
|
const host = 'http://localhost:8765';
|
||||||
const socket = io.connect(host);
|
const socket = io.connect(host);
|
||||||
export default socket;
|
export default socket;
|
||||||
|
Loading…
Reference in New Issue
Block a user