<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].deviceId
this.mediaStream = await navigator.mediaDevices.getUserMedia({
video: { deviceId: this.currentDeviceId }
})
const videoElement = this.$refs.video
videoElement.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 = 0
if (this.devices.length == 2) {
currentIndex = this.devices.findIndex(device => device.deviceId === this.currentDeviceId)
const nextIndex = (currentIndex + 1) % this.devices.length
this.currentDeviceId = this.devices[nextIndex].deviceId
} else if (this.devices.length > 2) {
if (this.currentText) {
this.currentDeviceId = this.devices[1].deviceId
this.currentText = false
} else {
this.currentDeviceId = this.devices[0].deviceId
this.currentText = true
}
}
this.mediaStream = await navigator.mediaDevices.getUserMedia({
video: { deviceId: this.currentDeviceId }
})
const videoElement = this.$refs.video
videoElement.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>