ffmpeg的使用教程,ffmpegnode实现流式处理
ffmpeg的使用教程,ffmpegnode实现流式处理ffmpeg 虽然提供了流式输出功能,但并不适用于所有场景,我简单测试了一下发现:C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)ffmpeg -s 0 -i input.mp4 -t 10 -f mpegts - | tee output.ts 提示:使用 - 时,ffmpeg 会尽量遵循管道通讯约束,将命令处理后的视频流输出到标准输出流;将命令运行的过程信息输出到标准错误流。流式处理最大的好处是不用等整个视频命令处理完就可以先拿到一部分数据,这在一些性能敏感场景,比如web视频服务、直播流等能够提高响应速度。在node实现中,本质上是使用 spawn 接口调用 ffmpeg 命令,借助父子进程间的管道通讯机制,将 ffmpeg 命令的标准输出流输出到目标视频文件中,实现保存效果,完整示例:co
1. 流式处理简介先来看个示例:
ffmpeg -s 0 -i input.mp4 -t 10 output.mp4
这段命令将截取输入视频 input.mp4 从0秒开始到第10秒之间的片段,并保存的 output.mp4 文件。命令可以分为三个部分:
ffmpeg 接受三种类型的输出:
- 文件位置
- 网络位置,用于实现网络推流
- - ,以标准输出流方式输出命令结果
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
借助 - 特性,我们可以以管道风格调用ffmpeg命令,例如:
ffmpeg -s 0 -i input.mp4 -t 10 -f mpegts - | tee output.ts
提示:使用 - 时,ffmpeg 会尽量遵循管道通讯约束,将命令处理后的视频流输出到标准输出流;将命令运行的过程信息输出到标准错误流。
2. 在node中使用流式处理最大的好处是不用等整个视频命令处理完就可以先拿到一部分数据,这在一些性能敏感场景,比如web视频服务、直播流等能够提高响应速度。在node实现中,本质上是使用 spawn 接口调用 ffmpeg 命令,借助父子进程间的管道通讯机制,将 ffmpeg 命令的标准输出流输出到目标视频文件中,实现保存效果,完整示例:
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
function transform(sourceFile outputStream start duration) {
const params = [`-ss` start `-i` sourceFile `-t` duration '-f' 'mpegts' '-'];
return new Promise((r j) => {
const cp = spawn('ffmpeg' params);
// ffmpeg 标准输出流
cp.stdout.pipe(outputStream);
// 将 ffmpeg 执行的过程日志输出到程序的标准输出流,通常为console
cp.stderr.pipe(process.stdout);
cp.on('error' (err) => {
j(err);
});
cp.on('close' (code) => {
console.log(`ffmpeg process close all stdio with code ${code}`);
r(code);
});
cp.on('exit' (code) => {
console.log(`ffmpeg process exited with code ${code}`);
});
});
}
async function run() {
const inputFile = path.join(__dirname 'test.mp4');
const output = fs.createWriteStream(path.join(__dirname 'output.mp4'));
await transform(inputFile output 0 100);
}
run();
运行效果:
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
ffmpeg 虽然提供了流式输出功能,但并不适用于所有场景,我简单测试了一下发现:
- 当输出封装格式为 mp4 时会报错 muxer does not support non seekable output ,这个异常是因为 mp4 不是顺序写的,在写不同类型的box时需要多次执行seek操作将数据插入适当位置,因此 mp4 格式要求输出流是 seekable 的,那用 stdout 自然就抓瞎了。
- 当输出封装格式为 hls 时会警告 Cannot use rename on non file protocol this may lead to races and temporary partial files ,这是因为hls需要输出多个文件,包括 m3u8 和一堆 ts ,默认情况下 ts 分片会按照分片序列命名,这个时候如果用标准输出流这种没法重命名的流,自然也是抓瞎。