Node.js捕获WebSocket MP4视频流保存失败求助:文件无法打开
问题分析
直接把WebSocket收到的原始Buffer写入.webm文件无效,核心原因是WebSocket传输的大概率是未封装的裸视频帧(比如H264/VP8),而非标准WebM容器格式的数据流。WebM需要特定的文件头、元数据和帧时序标记,直接拼接帧数据会破坏文件结构,导致FFmpeg无法识别。
解决方案
1. 先确认流的编码格式
先判断WebSocket返回的视频编码类型,可通过打印Buffer前几个字节识别:
- VP8帧起始特征:
0x9D 0x01 0x2A - H264帧起始码:
0x00 0x00 0x00 0x01或0x00 0x00 0x01
2. 用FFmpeg实时封装成标准WebM
不要直接写Buffer到文件,而是通过管道把WebSocket流传给FFmpeg,让它负责容器封装:
const WebSocket = require('ws'); const { spawn } = require('child_process'); const fs = require('fs'); const ws = new WebSocket('wss://stoa-wsez-e01.ezvds.net/ezs/60/ezugi_5_hd/websocketstream2'); const outputPath = `video_${Date.now()}.webm`; // 启动FFmpeg,将裸帧封装为WebM const ffmpeg = spawn('ffmpeg', [ '-f', 'h264', // 替换为实际编码格式,比如vp8 '-i', '-', // 从标准输入读取流 '-c:v', 'copy', // 直接复制编码,避免重新编码 outputPath ]); ws.on('open', () => { ws.send(JSON.stringify({ eventType: "PLAY", stream: "ezugi_5_hd", requestId: 0 })); }); ws.on('message', (data) => { // 将收到的帧数据写入FFmpeg输入 ffmpeg.stdin.write(data); }); ws.on('close', () => { // 关闭FFmpeg输入,触发文件写入完成 ffmpeg.stdin.end(); ffmpeg.on('exit', () => { // 执行截图并删除原视频 spawn('ffmpeg', [ '-i', outputPath, '-vframes', '1', '-ss', '00:00:01', `${outputPath}.png` ], { stdio: 'inherit' }).on('exit', () => { fs.unlinkSync(outputPath); }); }); }); ws.on('error', (err) => { console.error('WebSocket错误:', err); ffmpeg.kill(); });
注意:如果是H264编码,FFmpeg编译时需要开启WebM兼容H264的选项,若遇到兼容问题,可将输出编码改为VP8(把
-c:v copy改成-c:v vp8)。
3. 处理带分隔符的帧数据
如果WebSocket返回的帧前带有长度标识(比如4字节大端长度),需要先解析出完整帧再传给FFmpeg:
let buffer = Buffer.alloc(0); ws.on('message', (data) => { buffer = Buffer.concat([buffer, data]); // 按4字节长度标识拆分帧 while (buffer.length >= 4) { const frameLength = buffer.readUInt32BE(0); if (buffer.length >= 4 + frameLength) { const frame = buffer.slice(4, 4 + frameLength); ffmpeg.stdin.write(frame); buffer = buffer.slice(4 + frameLength); } else { break; } } });
4. 验证文件有效性
若仍有问题,用ffprobe检查文件结构:
ffprobe video_xxx.webm
如果仍提示Invalid data found when processing input,说明输入格式和FFmpeg的-f参数不匹配,需调整-f的值(比如H264用-f h264,VP8用-f vp8)。
内容的提问来源于stack exchange,提问作者Aleksandr Rogonov
相关产品推荐
相关产品推荐

