如何在Express+AngularJS移动端网站实现音视频录制与保存
解决方案:AngularJS + Express + RecordRTC 实现移动端视频录制与保存
看起来你已经搭好了基础框架,我来帮你补全完整的实现流程——从前端模态框录制视频,到后端Express接收并保存到文件夹,一步到位解决问题。
1. 完善前端 AngularJS 代码
先把你的 video.partial.html 补全,加入模态框、录制控件和视频预览区:
<script src="./../../node_modules/recordrtc/RecordRTC.js"></script> <div ng-controller="index"> <button ng-click="openVideoModal()">Add Video</button> <!-- 视频录制模态框 --> <div class="modal fade" id="videoRecordModal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">录制视频</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <!-- 视频预览区域(移动端要加playsinline避免全屏) --> <video id="previewVideo" autoplay playsinline controls style="width:100%;"></video> <div class="mt-3"> <button ng-click="startRecording()" class="btn btn-primary" ng-disabled="isRecording">开始录制</button> <button ng-click="stopRecording()" class="btn btn-danger" ng-disabled="!isRecording">停止录制</button> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button> <button type="button" class="btn btn-success" ng-click="saveVideo()" ng-disabled="!recordedBlob">保存视频</button> </div> </div> </div> </div> </div>
然后补全 app.js 里的控制器逻辑,处理录制、预览和上传:
var app = angular.module('myApp', ['ngRoute', 'ngMaterial', 'ui.bootstrap']); app.controller('index', ['$scope', '$http', function($scope, $http) { $scope.isRecording = false; $scope.recordedBlob = null; let recordRTCInstance = null; // 打开录制模态框并初始化摄像头 $scope.openVideoModal = function() { $('#videoRecordModal').modal('show'); // 请求摄像头和麦克风权限 navigator.mediaDevices.getUserMedia({ video: true, audio: true }) .then(stream => { const previewVideo = document.getElementById('previewVideo'); previewVideo.srcObject = stream; // 初始化 RecordRTC recordRTCInstance = RecordRTC(stream, { type: 'video', mimeType: 'video/webm' // 移动端兼容性较好的格式,也可改为video/mp4 }); }) .catch(err => { alert('无法访问摄像头/麦克风:' + err.message); $('#videoRecordModal').modal('hide'); }); }; // 开始录制 $scope.startRecording = function() { $scope.isRecording = true; recordRTCInstance.startRecording(); }; // 停止录制并生成预览 $scope.stopRecording = function() { $scope.isRecording = false; recordRTCInstance.stopRecording(() => { $scope.recordedBlob = recordRTCInstance.getBlob(); // 切换预览为录制好的视频 const previewVideo = document.getElementById('previewVideo'); previewVideo.src = URL.createObjectURL($scope.recordedBlob); $scope.$apply(); // 手动触发Angular脏检查更新视图 }); }; // 上传视频到后端 $scope.saveVideo = function() { if (!$scope.recordedBlob) return; const formData = new FormData(); formData.append('video', $scope.recordedBlob, `user_video_${Date.now()}.webm`); $http.post('/api/save-video', formData, { headers: { 'Content-Type': undefined }, // 让Angular自动处理FormData的Content-Type transformRequest: angular.identity }) .then(res => { alert('视频保存成功!'); $('#videoRecordModal').modal('hide'); // 清理资源 URL.revokeObjectURL($scope.recordedBlob); $scope.recordedBlob = null; recordRTCInstance.stream.getTracks().forEach(track => track.stop()); recordRTCInstance = null; }) .catch(err => { alert('视频保存失败:' + err.data?.message || '未知错误'); }); }; // 模态框关闭时自动清理资源 $('#videoRecordModal').on('hidden.bs.modal', () => { if (recordRTCInstance) { recordRTCInstance.stream.getTracks().forEach(track => track.stop()); recordRTCInstance = null; } $scope.isRecording = false; $scope.recordedBlob = null; $scope.$apply(); }); }]);
2. 后端 Express 实现视频保存
首先安装处理文件上传的 multer 中间件:
npm install multer --save
然后在你的 Express 主文件(比如 server.js)中添加上传路由:
const express = require('express'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const app = express(); // 配置 multer 存储规则 const storage = multer.diskStorage({ destination: (req, file, cb) => { const uploadDir = path.join(__dirname, 'uploads'); // 如果uploads文件夹不存在则自动创建 if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true }); cb(null, uploadDir); }, filename: (req, file, cb) => { // 自定义文件名,避免重复 const ext = path.extname(file.originalname); cb(null, `video_${Date.now()}${ext}`); } }); const upload = multer({ storage: storage, limits: { fileSize: 100 * 1024 * 1024 } // 限制文件大小为100MB,可按需调整 }); // 处理视频上传的接口 app.post('/api/save-video', upload.single('video'), (req, res) => { if (!req.file) { return res.status(400).json({ message: '未上传视频文件' }); } res.status(200).json({ message: '视频保存成功', filePath: req.file.path }); }); // 启动服务器 const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`服务器运行在端口 ${PORT}`); });
3. 关键注意事项
- HTTPS 要求:移动端浏览器在非HTTPS环境下会禁止访问摄像头,测试时请确保用HTTPS或者localhost(本地开发例外)。
- 格式兼容性:
video/webm在大部分现代浏览器支持,如果需要MP4格式,可以把RecordRTC的mimeType改为video/mp4,但部分移动端可能需要额外编码支持。 - 资源清理:录制完成或模态框关闭时一定要停止媒体流,避免占用设备摄像头/麦克风资源。
内容的提问来源于stack exchange,提问作者Sumit
相关产品推荐
相关产品推荐

