<template>
<div style="height: 100vh;background: #000;">
<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, // 录制后的视频 URL
isRecording: false, // 是否正在录制
currentDeviceId: null, // 当前摄像头设备 ID
currentText: "front", // front前 after后
devices: [], // 设备列表
timer: null, // 计时器,用于限制录制时间
timernum: 30, // 计时器,用于限制录制时间
maxFileSize: 100 * 1024 * 1024, // 100MB
};
},
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);
// 检查文件大小是否超过 95MB
const totalSize = this.recordedChunks.reduce((acc, chunk) => acc + chunk.size, 0);
// this.$toast(`大小:`+ (totalSize/1024/1024))
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); // 60秒后停止录制
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();
// 切换到下一个摄像头设备(前后切换)
if (this.currentText === "front") {
this.currentDeviceId = this.devices[3].deviceId;
this.currentText = "after";
} else {
this.currentDeviceId = this.devices[0].deviceId;
this.currentText = "front";
}
// 获取新的摄像头流
this.mediaStream = await navigator.mediaDevices.getUserMedia({
video: { deviceId: this.currentDeviceId }
});
const videoElement = this.$refs.video;
videoElement.srcObject = this.mediaStream;
} catch (error) {
console.error("无法切换摄像头:", 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>