目录

实时录像和拍照并发送给后端

目录

实时录像和拍照并发送给后端

利用navigator.mediaDevices调用摄像头实现摄像

<template>
  <div>
    <div style="position: fixed; right: 10px; bottom: 10px;">
      <video ref="video" width="200" height="150" autoplay></video>
    </div>
    <canvas ref="canvas" style="display: none;"></canvas>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import axios from 'axios'

const video = ref(null)
const canvas = ref(null)

let mediaRecorder
let chunks = []

// 获取摄像头权限并实时显示摄像头内容
navigator.mediaDevices.getUserMedia({ video: true })
.then((stream) => {
video.value.srcObject = stream;
startRecording();
})
.catch((error) => {
console.error('Error accessing media devices: ', error);
});

// 定时拍摄视频并发送给后台
const recordingInterval = 60000; // 修改为 1 分钟
setInterval(() => {
if (mediaRecorder && mediaRecorder.state === "inactive") {
startRecording();
}
}, recordingInterval);

const startRecording = () => {
if (!video.value) return;

const stream = video.value.srcObject;
if (!stream) return;

mediaRecorder = new MediaRecorder(stream);
mediaRecorder.ondataavailable = (e) => {
chunks.push(e.data);
};
mediaRecorder.onstop = async () => {
const blob = new Blob(chunks, { type: 'video/webm' });
chunks = [];

    const photoData = await takePhoto(); // 拍照并等待图片数据
    saveData(blob, photoData); // 发送视频和图片数据

};
mediaRecorder.start();
setTimeout(() => {
mediaRecorder.stop();
}, 10000); // 录制 10 秒
};

const takePhoto = () => {
return new Promise((resolve) => {
const videoElement = video.value;
const canvasElement = canvas.value;
const context = canvasElement.getContext('2d');
canvasElement.width = videoElement.videoWidth;
canvasElement.height = videoElement.videoHeight;
context.drawImage(videoElement, 0, 0, canvasElement.width, canvasElement.height);
resolve(canvasElement.toDataURL('image/png'));
})
};

const saveData = (videoBlob, photoData) => {
const formData = new FormData()
const photoBlob = dataURLToBlob(photoData)
const photoFormData = new FormData()
formData.append('video', videoBlob, 'video.webm')
photoFormData.append('image', photoBlob, 'image.png')

const sendData = [axios.post('http://localhost:3000/video', formData), axios.post('http://localhost:3000/image', photoFormData)]

Promise.all(sendData).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})

};

const dataURLToBlob = (dataURL) => {
const byteString = atob(dataURL.split(',')[1]);
const mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: mimeString });
}
</script>

node 代码

const express = require('express');
const path = require('path');
const multer = require('multer');

const app = express();

// 允许跨域请求
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5173');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
next();
});

// 配置 multer 中间件
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/'); // 上传的文件存储在 uploads/ 目录中
},
// filename: function (req, file, cb) {
// cb(null, file.originalname); // 保持上传的文件名
// }
filename: function (req, file, cb) {
const fileExt = path.extname(file.originalname);
const fileName = path.parse(file.originalname).name;
cb(null, `${fileName}${fileExt}`)
}
});
const upload = multer({ storage: storage });

app.post('/video', upload.single('video'), (req, res) => {
if (!req.file) {
return res.status(400).send({
code: 400,
message: 'No file uploaded.'
})
}

console.log(req.file)
res.send({
code: 200,
message: 'success',
filePath: req.file.path
})
})

app.post('/image', upload.single('image'), (req, res) => {
if (!req.file) {
return res.status(400).send({
code: 400,
message: 'No file uploaded.'
});
}

console.log(req.file);
res.send({
code: 200,
message: 'success',
filePath: req.file.path
});
});

// 处理客户端提交的视频
app.post('/submit-answers', upload.single('video'), (req, res) => {
if (!req.file) {
res.status(400).json({ error: 'No video file provided' });
return;
}

// 这里可以对上传的视频进行进一步的处理,例如将视频信息保存到数据库中

res.json({ message: '上传成功!' });

});

// 启动服务器
const port = 3000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});