<template><div style="height: 100vh;background: #000;"><span style="color: #fff;font-size: 18px;">切换数量:{{ devices.length }}</span><video ref="video" autoplay muted playsinline></video><div class="video_btn"><van-button round @click="start" type="info">{{ isRecording ? `${timernum}秒后停止录制` : '开始录制' }}</van-button><van-button round @click="switchCamera" :disabled="isRecording">切换摄像头</van-button></div><video v-if="recordedVideoUrl" :src="recordedVideoUrl" controls></video></div>
</template><script>
export default {data() {return {mediaStream: null, mediaRecorder: null, recordedChunks: [], recordedVideoUrl: null, isRecording: false, currentDeviceId: null, currentText: true, devices: [], timer: null, timernum: 30, maxFileSize: 100 * 1024 * 1024, }},mounted() {this.startCamera()},methods: {async startCamera() {try {const devices = await navigator.mediaDevices.enumerateDevices()this.devices = devices.filter(device => device.kind === "videoinput")if (this.devices.length === 0) {throw new Error("没有找到摄像头设备")}this.currentDeviceId = this.devices[0].deviceIdthis.mediaStream = await navigator.mediaDevices.getUserMedia({video: { deviceId: this.currentDeviceId }})const videoElement = this.$refs.videovideoElement.srcObject = this.mediaStream} catch (error) {console.error("无法访问摄像头:", error)}},start() {if (this.isRecording) {this.stopRecording()} else {this.startRecording()}},startRecording() {if (this.mediaStream) {this.mediaRecorder = new MediaRecorder(this.mediaStream)this.recordedChunks = []this.mediaRecorder.ondataavailable = (event) => {if (event.data.size > 0) {this.recordedChunks.push(event.data)const totalSize = this.recordedChunks.reduce((acc, chunk) => acc + chunk.size, 0)if (totalSize > this.maxFileSize) {this.stopRecording()}}}this.mediaRecorder.onstop = () => {const blob = new Blob(this.recordedChunks, { type: "video/webm" })this.recordedVideoUrl = URL.createObjectURL(blob)}this.timer = setInterval(() => {this.settime()}, 1000) this.mediaRecorder.start()this.isRecording = true}},settime() {if (this.timernum < 1) {this.stopRecording()clearInterval(this.timer)return} else {this.timernum--}},stopRecording() {if (this.mediaRecorder) {this.mediaRecorder.stop()clearInterval(this.timer) this.isRecording = false}this.timernum = 30},async switchCamera() {try {this.stopStream()const devices = await navigator.mediaDevices.enumerateDevices()this.devices = devices.filter(device => device.kind === "videoinput")let currentIndex = 0if (this.devices.length == 2) {currentIndex = this.devices.findIndex(device => device.deviceId === this.currentDeviceId)const nextIndex = (currentIndex + 1) % this.devices.lengththis.currentDeviceId = this.devices[nextIndex].deviceId} else if (this.devices.length > 2) {if (this.currentText) {this.currentDeviceId = this.devices[1].deviceIdthis.currentText = false} else {this.currentDeviceId = this.devices[0].deviceIdthis.currentText = true}}this.mediaStream = await navigator.mediaDevices.getUserMedia({video: { deviceId: this.currentDeviceId }})const videoElement = this.$refs.videovideoElement.srcObject = this.mediaStream} catch (error) {this.$toast('无法切换摄像头' + error)}},stopStream() {if (this.mediaStream) {const tracks = this.mediaStream.getTracks()tracks.forEach(track => track.stop())}}}
}
</script><style>
.video_btn {position: fixed;bottom: 30px;z-index: 99;display: flex;justify-content: space-around;align-items: center;width: 100%;max-width: 640px;margin: 0 auto;
}video {width: 100%;height: 80vh;max-width: 640px;margin: 0 auto;
}
</style>