首页 > 解决方案 > 将ffmpeg缩略图输出管道传输到另一个程序

问题描述

我正在尝试从实时视频流(h.264)中捕获帧并将生成的 JPG 图像通过管道传输到 Node JS 脚本,而不是将这些单独的帧直接保存到 .jpg 文件中。

作为测试,我创建了以下 Node JS 脚本,以简单地捕获传入的管道数据,然后将其转储到文件中:

// pipe.js - test pipe output
var fs = require('fs');
var data = '';

process.stdin.resume();
process.stdin.setEncoding('utf8');

var filename = process.argv[2];

process.stdin.on('data', (chunk) => {
        console.log('Received data chunk via pipe.');
        data += chunk;
});

process.stdin.on('end', () => {
        console.log('Data ended.');
        fs.writeFile(filename, data, err => {
                if (err) {
                        console.log('Error writing file: error #', err);
                }
        });
        console.log('Saved file.');
});

console.log('Started...  Filename = ' + filename);

这是我使用的 ffmpeg 命令:

ffmpeg -vcodec h264_mmal -i "rtsp://[stream url]" -vframes 1 -f image2pipe - | node pipe.js test.jpg

这生成了以下输出,并且还生成了一个 175kB 的文件,其中包含垃圾(无论如何都无法作为 jpg 文件读取)。仅供参考,使用 ffmpeg 直接导出为 jpg 文件,生成的文件大小约为 25kB。

...
Press [q] to stop, [?] for help
[h264_mmal @ 0x130d3f0] Changing output format.
Input stream #0:0 frame changed from size:1280x720 fmt:yuvj420p to size:1280x720 fmt:yuv420p
[swscaler @ 0x1450ca0] deprecated pixel format used, make sure you did set range correctly
Received data chunk via pipe.
Received data chunk via pipe.
frame=    1 fps=0.0 q=7.7 Lsize=      94kB time=00:00:00.40 bitrate=1929.0kbits/s speed=1.18x
video:94kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
Received data chunk via pipe.
Data ended.
Saved file.

您可以看到 Node JS 脚本正在接收管道数据(根据上面的“通过管道接收数据”消息。但是,它似乎没有输出有效的 JPG 文件。我找不到具体要求的方法ffmpeg 输出 JPG 格式,因为 JPG 没有 -vcodec 选项。我尝试使用 -vcodec png 并输出到 .png 文件,但生成的文件大小约为 2MB,并且无法作为 png 文件读取。

这是使用 utf8 编码引起的问题,还是我做错了什么?

感谢您的任何建议。

更新:好的,我可以正确发送单个 jpg 图像。问题在于 Node JS 捕获流数据的方式。这是一个工作脚本:

// pipe.js - capture piped binary input and write to file
var fs = require('fs');
var filename = process.argv[2];

console.log("Opening " + filename + " for binary writing...");

var wstream = fs.createWriteStream(filename);

process.stdin.on('readable', () => {
        var chunk = '';
        while ((chunk = process.stdin.read()) !== null) {
                wstream.write(chunk);   // Write the binary data to file
                console.log("Writing chunk to file...");
        }
});

process.stdin.on('end', () => {
        // Close the file
        wstream.end();
});

但是,现在的问题是:当将 ffmpeg 的输出通过管道传输到该脚本时,我如何判断一个 JPG 文件何时结束,而另一个 JPG 文件何时开始?

ffmpeg 命令:

 ffmpeg -vcodec h264_mmal -i "[my rtsp stream]" -r 1 -q:v 2 -f singlejpeg - | node pipe.js test_output.jpg

只要脚本运行,test_output.jpg 文件就会继续增长。相反,我如何知道一个 jpg 的数据何时完成而另一个 jpg 的数据何时开始?据此 jpeg 文件总是以 FF D8 FF 开头并以 FF D9 结尾,所以我想我可以检查这个结束签名并在那时开始一个新文件......还有其他建议吗?

标签: node.jsffmpegpipejpeg

解决方案


推荐阅读