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

如何在Express(Node.js)中处理Blob并保存前端上传的录屏视频文件

解决方案

问题根因

  • Express默认未开启二进制请求体解析,默认req.body为空
  • 原有代码每次readable事件触发时都新建写入流,会覆盖之前写入的内容,仅能保存最后一段二进制数据
  • 未监听请求结束事件,也未给前端返回响应,会触发请求超时
  • MediaRecorder输出格式与存储后缀不匹配的话,会导致保存的文件无法正常播放

修复后实现代码

前端优化(可选,提升兼容性)

// 优先匹配H264编码的MP4格式,兼容性更好
const supportedMime = MediaRecorder.isTypeSupported('video/mp4; codecs=h264') 
  ? 'video/mp4; codecs=h264' 
  : 'video/webm';

// 原有MediaRecorder初始化时传入指定格式
// const recorder = new MediaRecorder(stream, { mimeType: supportedMime })

// 原有录制逻辑...

const blob = new Blob(chunks, { type: supportedMime });
const savedVideo = document.getElementById("savedVideo");
chunks = [];

const videoURL = window.URL.createObjectURL(blob);
savedVideo.src = videoURL;

// 停止所有轨道
stream.getTracks().forEach(track => track.stop());

// 上传Blob
const response = await fetch('http://localhost:3001/upload', {
  method: 'POST',
  headers: {
    'Content-Type': supportedMime,
  },
  body: blob
});
const uploadResult = await response.json();
console.log(uploadResult);

服务端代码

常规小文件场景直接用express.raw解析:

const express = require("express");
const cors = require('cors');
const fs = require('fs');
const path = require('path');

const app = express();
const port = 3001;

app.use(cors({
  origin: 'http://localhost:3000'
}));

// 开启二进制请求体解析,大小限制可根据实际需求调整
app.use(express.raw({ 
  type: ['video/*'], 
  limit: '200mb' 
}));

app.post("/upload", (req, res) => {
  // 直接获取解析后的完整二进制Buffer
  const videoBuffer = req.body;
  // 生成唯一文件名避免覆盖,后缀和前端录制格式保持一致
  const savePath = path.join(__dirname, `record_${Date.now()}.mp4`);

  fs.writeFile(savePath, videoBuffer, (err) => {
    if (err) {
      console.error('视频保存失败:', err);
      return res.status(500).json({
        success: false,
        message: '保存失败'
      });
    }
    res.json({
      success: true,
      message: '保存成功',
      path: savePath
    });
  });
});

app.listen(port, () => {
  console.log(`服务启动成功:http://localhost:${port}`);
});

大文件场景优化方案(长时间录屏)

如果录制的视频文件过大,用内存缓存完整Buffer会占用过高资源,可直接用流管道写入:

app.post("/upload", (req, res) => {
  const savePath = path.join(__dirname, `record_${Date.now()}.mp4`);
  const writeStream = fs.createWriteStream(savePath);

  // 直接将请求流导入写入流
  req.pipe(writeStream);

  writeStream.on('finish', () => {
    res.json({
      success: true,
      message: '保存成功',
      path: savePath
    });
  });

  writeStream.on('error', (err) => {
    console.error('写入失败:', err);
    res.status(500).json({
      success: false,
      message: '保存失败'
    });
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:36:02