我想要做的是使用 ffmpeg 制作视频的缩略图。视频数据在 HTTP 请求中接收,然后通过管道传输到 ffmpeg。问题是,一旦 ffmpeg 子进程退出,我就无法将响应发回。

这是代码:

var http = require('http'),
sys = require('sys'),
child = require('child_process')
http.createServer(function (req, res) {
    im = child.spawn('ffmpeg',['-i','-','-vcodec','mjpeg','-ss','00:00:03','-vframes','1','-s','100x80','./thumb/thumbnail.jpg']);
    im.on('exit', function (code, signal) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('{"success":true}\n');
     });
    req.connection.pipe(im.stdin);
}).listen(5678, "127.0.0.1");

问题是调用:
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('{"success":true}\n');

什么都不做,客户端永远不会收到响应。

最佳答案

经过两天的调试和谷歌搜索,我似乎找到了问题所在。
node.js 中有两个相关的开放错误负责:

  • https://github.com/joyent/node/issues/777
  • https://github.com/joyent/node/issues/782

  • 我将尝试描述我认为“管道”方法的问题所在:

    请求流无法在 ffmpeg.stdin 上调用 end(可能是错误 #777),这会导致管道损坏错误,但由于错误 #782,node.js 无法处理该错误,同时请求流保持暂停 - 这会阻止发送的任何响应。

    黑客/解决方法是在 ffmpeg 退出后恢复请求流。

    这是固定的代码示例:
    var http = require('http'),
    sys = require('sys'),
    child = require('child_process')
    http.createServer(function (req, res) {
    im = child.spawn('ffmpeg',['-i','-','-vcodec','mjpeg','-ss','00:00:03','-vframes','1','-s','100x80','./thumb/thumbnail.jpg']);
        im.on('exit', function (code, signal) {
            req.resume();
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end('{"success":true}\n');
         });
      req.connection.pipe(im.stdin);
    }).listen(5678, "127.0.0.1");
    

    请记住,这是一个黑客/解决方法,一旦他们对这些错误采取措施,可能会导致 future 的 node.js 版本出现问题

    10-07 19:15
    查看更多