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

Node.js视频流传输时同步发送JSON数据的实现方案问询

在Express视频流接口中同步发送坐标JSON数据(无需新增接口)

问题背景

我现在有个Express接口能流式传输本地MP4视频,想在不新增任何接口的前提下,同时向前端发送x、y坐标的JSON数据。目前的代码如下:

const express = require("express")
const fs = require("fs")
const app = express()

app.get("/video", (req, res) => {
  const path = "video.mp4";
  const stat = fs.statSync(path);
  const fileSize = stat.size;
  const head = {
    'Content-Length': fileSize,
    'Content-Type': 'video/mp4'
  }
  res.writeHead(200, head);
  fs.createReadStream(path).pipe(res);
});

app.listen(3000, function () {
  console.log('App is running on port 3000')
})

解决方案:使用Multipart混合响应

要在同一个接口里同时传输视频流和JSON数据,你可以利用HTTP的multipart/mixed响应类型——把视频内容和坐标数据拆分成独立的"部分",用一个自定义分隔符分隔,前端就能分别解析这两部分内容了。

下面是修改后的完整代码:

const express = require("express");
const fs = require("fs");
const app = express();

app.get("/video", (req, res) => {
  const videoPath = "video.mp4";
  const videoStat = fs.statSync(videoPath);
  const videoSize = videoStat.size;
  
  // 生成一个唯一的分隔符,避免和内容里的字符串冲突
  const boundary = `video-coord-separator-${Date.now()}`;

  // 设置响应头为multipart/mixed,指定分隔符
  res.writeHead(200, {
    "Content-Type": `multipart/mixed; boundary=${boundary}`,
    "Transfer-Encoding": "chunked" // 启用分块传输,适配流式内容
  });

  // 先发送坐标JSON部分
  res.write(`\r\n--${boundary}\r\n`);
  res.write('Content-Type: application/json\r\n\r\n');
  // 这里替换成你的实际坐标数据,如果是实时的可以改成动态生成
  const coordData = JSON.stringify({ x: 150, y: 300 });
  res.write(coordData);

  // 再发送视频流部分
  res.write(`\r\n--${boundary}\r\n`);
  res.write(`Content-Type: video/mp4\r\nContent-Length: ${videoSize}\r\n\r\n`);
  
  const videoStream = fs.createReadStream(videoPath);
  videoStream.on("end", () => {
    // 所有内容发送完毕后,加上结束标记
    res.write(`\r\n--${boundary}--\r\n`);
    res.end();
  });
  
  // 把视频流管道到响应,注意不要自动结束响应
  videoStream.pipe(res, { end: false });
});

app.listen(3000, () => {
  console.log('App is running on port 3000');
});

前端怎么解析这个响应?

前端需要手动拆分multipart响应的各个部分,这里用fetch举个例子:

async function loadVideoAndCoords() {
  const response = await fetch('/video');
  const contentType = response.headers.get('Content-Type');
  const boundary = contentType.split('boundary=')[1];
  const body = await response.text();
  
  // 按分隔符拆分各个部分
  const parts = body.split(`\r\n--${boundary}`).filter(part => part.trim() !== '');
  
  // 提取坐标JSON
  const coordPart = parts.find(part => part.includes('application/json'));
  const coords = JSON.parse(coordPart.split('\r\n\r\n')[1]);
  console.log('收到坐标:', coords);
  
  // 提取视频内容并渲染
  const videoPart = parts.find(part => part.includes('video/mp4'));
  const videoBlob = new Blob([videoPart.split('\r\n\r\n')[1]], { type: 'video/mp4' });
  const videoElement = document.querySelector('video');
  videoElement.src = URL.createObjectURL(videoBlob);
}

loadVideoAndCoords();

额外提示

  • 如果你的坐标数据是实时动态更新的(比如随着视频播放持续发送新坐标),可以把坐标拆成多个小的multipart部分,在视频流传输过程中随时发送,前端监听响应流的chunk就能实时获取新数据。
  • 分隔符一定要唯一,用随机字符串加时间戳的方式能有效避免和内容冲突。
  • 启用Transfer-Encoding: chunked很重要,因为我们没法提前知道整个响应的总大小(尤其是动态发送坐标的情况)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 10:22:43