feat: 切换摄像头
This commit is contained in:
parent
8af84d8f2d
commit
847d8a6681
@ -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;
|
||||||
},
|
},
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user