You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Node.js+Multer将Blob URL转存为WebM/MP4视频到服务器

问题

通过HTML5录制视频得到Blob URL(如blob:http://localhost:3000/xxx),想用Node.js将视频上传至服务器。当前前端上传的是Blob URL字符串,后端用Multer接收时仅拿到URL而非视频数据,上传失败。如何将Blob URL转换为WebM/MP4视频并保存到服务器文件夹?

原代码展示

前端代码

camera_stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = camera_stream;
media_recorder = new MediaRecorder(camera_stream, { mimeType: 'video/webm' });
media_recorder.addEventListener('dataavailable', function(e) {
    blobs_recorded.push(e.data);
});


let video_local = URL.createObjectURL(new Blob(blobs_recorded, { type: 'video/webm' }));
var fd = new FormData();
fd.append('name', 'test.webm');
fd.append('data', video_local);
$.ajax({
    type: 'POST',
    url: '/cam',
    data: fd,
    cache : false,
    contentType : false,
    processData : false
}).done(function(data) {
    console.log('success');
});

Node.js及Multer代码

router.post('/cam',upload.single("data"),(req,res)=>{
    console.log(req.body);
})

当前Multer输出结果

[Object: null prototype] {
  name: 'test.webm',
  data: 'blob:http://localhost:3000/a1ce2f38-2cc1-4216-979b-90e574d11b75'
}
原因分析

Blob URL只是浏览器生成的本地临时引用,本质是字符串,并非实际的视频文件数据。直接上传这个URL,后端自然无法获取到视频内容。

解决方案

前端修改:直接上传Blob对象

不需要生成Blob URL,直接把录制得到的Blob(或合并后的Blob)添加到FormData中,Multer才能识别为文件。

修改后的前端代码:

camera_stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = camera_stream;
media_recorder = new MediaRecorder(camera_stream, { mimeType: 'video/webm' });
const blobs_recorded = [];

media_recorder.addEventListener('dataavailable', function(e) {
    blobs_recorded.push(e.data);
});

// 录制停止后触发上传逻辑
media_recorder.stop();
media_recorder.addEventListener('stop', function() {
    // 合并所有录制片段为完整视频Blob
    const videoBlob = new Blob(blobs_recorded, { type: 'video/webm' });
    var fd = new FormData();
    // 直接传入Blob对象,第三个参数指定文件名
    fd.append('data', videoBlob, 'test.webm');
    $.ajax({
        type: 'POST',
        url: '/cam',
        data: fd,
        cache: false,
        contentType: false,
        processData: false
    }).done(function(data) {
        console.log('上传成功');
    }).fail(function(err) {
        console.error('上传失败', err);
    });
});

后端修改:配置Multer保存文件

配置Multer的存储规则,指定视频保存的目录和文件名,确保上传的文件能被正确保存。

修改后的Node.js代码:

const express = require('express');
const router = express.Router();
const multer = require('multer');
const fs = require('fs');

// 配置Multer存储参数
const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        // 确保uploads目录存在,不存在则创建
        const uploadDir = './uploads';
        if (!fs.existsSync(uploadDir)) {
            fs.mkdirSync(uploadDir);
        }
        cb(null, uploadDir);
    },
    filename: function (req, file, cb) {
        // 生成唯一文件名,避免重复
        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
        const ext = file.originalname.split('.').pop();
        cb(null, `video-${uniqueSuffix}.${ext}`);
    }
});

const upload = multer({ storage: storage });

router.post('/cam', upload.single("data"), (req, res) => {
    // req.file包含上传文件的完整信息
    console.log('文件信息:', req.file);
    res.json({ 
        status: 'success', 
        message: '视频上传完成',
        savePath: req.file.path 
    });
});

module.exports = router;
验证结果

修改完成后,后端req.file会输出类似如下的文件信息,视频文件将自动保存到./uploads目录下:

{
  fieldname: 'data',
  originalname: 'test.webm',
  encoding: '7bit',
  mimetype: 'video/webm',
  destination: './uploads',
  filename: 'video-1700000000000-123456789.webm',
  path: 'uploads/video-1700000000000-123456789.webm',
  size: 896542 // 文件字节大小
}

内容的提问来源于stack exchange,提问作者Cihan Sulu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 21:45:31