feat: 切换摄像头

This commit is contained in:
Eleanor Mao 2022-07-05 15:58:51 +08:00
parent 8af84d8f2d
commit 847d8a6681
3 changed files with 84 additions and 10 deletions

1
sdp Normal file

File diff suppressed because one or more lines are too long

View File

@ -34,6 +34,8 @@
</el-button> </el-button>
</div> </div>
<Video <Video
:cameras="cameras"
:currentCamera="currentCamera"
:showStartVideoByReceiver="showStartVideoByReceiver" :showStartVideoByReceiver="showStartVideoByReceiver"
:showStartVideoBySender="showStartVideoBySender" :showStartVideoBySender="showStartVideoBySender"
:showVideo="showVideo" :showVideo="showVideo"
@ -41,6 +43,7 @@
@cancelReceiveVideo="cancelReceiveVideo" @cancelReceiveVideo="cancelReceiveVideo"
@hangupVideo="hangUpVideo" @hangupVideo="hangUpVideo"
@answerVideo="answerVideo" @answerVideo="answerVideo"
@cameraChange="cameraChange"
/> />
</div> </div>
<div v-else> <div v-else>
@ -79,9 +82,11 @@ export default {
return { return {
showFormArea: true, showFormArea: true,
showVideo: false, showVideo: false,
devices: [],
showStartVideoByReceiver: null, showStartVideoByReceiver: null,
showStartVideoBySender: null, showStartVideoBySender: null,
remoteStream: null, remoteStream: null,
currentCamera: 'default',
roomForm: { roomForm: {
roomId: '', roomId: '',
userName: '' userName: ''
@ -123,6 +128,9 @@ export default {
receiveUser () { receiveUser () {
return this.roomUsers.find(item => item.sockId !== this.sockId); return this.roomUsers.find(item => item.sockId !== this.sockId);
}, },
cameras () {
return this.devices.filter(i => i.kind === 'videoinput');
}
}, },
methods: { methods: {
canSupportWebRTC () { canSupportWebRTC () {
@ -151,6 +159,7 @@ export default {
async getDevices () { async getDevices () {
try { try {
const devices = await navigator.mediaDevices.enumerateDevices(); const devices = await navigator.mediaDevices.enumerateDevices();
this.devices = devices;
console.log('devices', devices); console.log('devices', devices);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -359,10 +368,28 @@ export default {
hangUpVideo () { hangUpVideo () {
socket.emit('hangupVideo', this.user); socket.emit('hangupVideo', this.user);
}, },
async cameraChange (deviceId) {
const localStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: {
deviceId
}
});
const videoTrack = localStream.getVideoTracks()[0];
const sender = this.peer.getSenders().find(function (s) {
return s.track.kind == videoTrack.kind;
});
console.log('found sender:', sender);
sender.replaceTrack(videoTrack);
this.localStream = localStream;
setLocalStream(localStream);
},
async createLocalVideoStream () { async createLocalVideoStream () {
const constraints = { audio: true, video: true };
// Link: https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia // Link: https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia
const localStream = await navigator.mediaDevices.getUserMedia(constraints); const localStream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true
});
console.log('localStream:', localStream); console.log('localStream:', localStream);
return localStream; return localStream;
}, },

View File

@ -5,9 +5,20 @@
<video autoplay class="remoteStream" id="remoteStream"></video> <video autoplay class="remoteStream" id="remoteStream"></video>
<video autoplay class="localStream" id="localStream"></video> <video autoplay class="localStream" id="localStream"></video>
</div> </div>
<div> <div class="control">
<el-select :value="currentCamera" @change="changeCamera">
<el-option value="default">系统默认</el-option>
<el-option
v-for="item in cameras"
:key="item.deviceId"
:label="item.label"
:value="item.deviceId">
</el-option>
</el-select>
<el-button type="success" @click="takePhoto">拍照</el-button>
<el-button type="danger" @click="clickHangup">挂断</el-button> <el-button type="danger" @click="clickHangup">挂断</el-button>
</div> </div>
<canvas id="photo"/>
</div> </div>
<div v-if="!showVideo && showStartVideoByReceiver" class="modal"> <div v-if="!showVideo && showStartVideoByReceiver" class="modal">
<div class="desc">等待{{ showStartVideoByReceiver.userName }}接受视频通话邀请</div> <div class="desc">等待{{ showStartVideoByReceiver.userName }}接受视频通话邀请</div>
@ -34,28 +45,49 @@
<script> <script>
export default { export default {
name: 'VideoView', name: 'VideoView',
props: ['devices', 'showVideo', 'showStartVideoByReceiver', 'showStartVideoBySender', 'remoteStream', 'localStream'], props: ['currentCamera', 'cameras', 'showVideo', 'showStartVideoByReceiver', 'showStartVideoBySender', 'remoteStream', 'localStream'],
methods: { methods: {
cancelSendVideo () { cancelSendVideo() {
this.$emit('cancelSendVideo'); this.$emit('cancelSendVideo');
}, },
cancelReceiveVideo () { cancelReceiveVideo() {
this.$emit('cancelReceiveVideo'); this.$emit('cancelReceiveVideo');
}, },
clickHangup () { clickHangup() {
this.$emit('hangupVideo'); this.$emit('hangupVideo');
}, },
clickAnswer () { clickAnswer() {
this.$emit('answerVideo'); this.$emit('answerVideo');
},
takePhoto() {
const canvas = document.querySelector('#photo');
const context = canvas.getContext('2d');
const video = document.querySelector('#remoteStream');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
const data = canvas.toDataURL('image/png');
const a = document.createElement('a');
a.download = 'photo.png';
a.href = data;
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
});
},
changeCamera(deviceId) {
this.$emit('cameraChange', deviceId);
} }
} }
}; };
export function setLocalStream (stream) { export function setLocalStream(stream) {
document.querySelector('#localStream').srcObject = stream; document.querySelector('#localStream').srcObject = stream;
} }
export function setRemoteSteam (stream) { export function setRemoteSteam(stream) {
document.querySelector('#remoteStream').srcObject = stream; document.querySelector('#remoteStream').srcObject = stream;
} }
</script> </script>
@ -108,4 +140,18 @@ video {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
#photo {
width: 500px;
height: 400px;
position: fixed;
top: -5000px;
left: -5000px;
}
.control {
display: flex;
flex-direction: row;
justify-content: space-around;
}
</style> </style>