我一直在构建一个youtube视频转换应用程序,该应用程序使用youtube-dl流式传输youtube视频并将其保存,直到我尝试流式传输一个小时以上的视频之前,一切工作正常。当任务完成的时间介于50%-100%之间或40-80秒之间时,就是重新运行整个代码块,导致同时发生多个流。因此,在等待管道完成时,永远不会发送响应。添加next(); 流功能外部允许转换完成,而不会中断代码块或重新运行它,但是在尝试发送响应时导致以下错误:
throw new Error('Can\'t set headers after they are sent.');
这是有问题的Node.js代码块:
app.post('/convert/', function (req, res, next){ var url = 'http://www.youtube.com/'+req.body.url; var quality = req.body.quality; var socketId = req.body.socketId; stream = youtubedl(url, ['-f ' + quality], // // Additional options can be given for calling `child_process.execFile()`. { cwd: __dirname }); stream.on('info', function(info) { console.log('Download started'); console.log('filename: ' + info._filename); console.log('size: ' + info.size); console.log('format: ' + info.format); var fileName = info._filename; var videoId = info.id; var videoTitle = info.title; videoTitle = videoTitle.replace(/[^a-zA-Z0-9\s]/g, ''); console.log(videoTitle); var mp4 = 'downloads/'+videoTitle+'-'+info.format_id+'.mp4'; fs.writeFile(mp4, "file", function(err) { if(err) { return console.log(err); } console.log("The file was saved!"); var stat = fs.statSync(mp4); var str = progress({ length: info.size, time: 100 }); str.on('progress', function(progress) { io.to(global.socketid).emit('progressVideo',{progress: progress.percentage}); console.log(info.size); console.log(progress.transferred); console.log(progress.percentage); console.log(progress.remaining); }); var pipe = stream.pipe(str).pipe(fs.createWriteStream(mp4)); pipe.on('finish', function () { console.log("stream finished."); res.json(videoTitle+'-'+info.format_id+'.mp4'); }); }); }); // next(); });
由某些Angular代码调用。
// Sends youtube link to backend $scope.getVideo = function(youtubeLink, resolution){ var cleanedLink = youtubeLink.substring(24); var url = {url: cleanedLink, quality: resolution}; $http.post('/convert/', url).success(function (response){ // Do some stuff }); }
对于为什么为什么要运行一次又一次又一次的运行感到困惑,我慢慢删除了越来越多的代码,直到剩下这个简单的测试为止。
app.post('/convert/', function (req, res, next){ console.log('hello!'); });
这是由ng-click事件调用的,在等待一分钟左右后,控制台还打印了两个然后是三个hello!
语句。我完全不知道为什么会这样。如果有人能为我阐明这一点,将不胜感激。
因此,在走到最基本的发布路线并注销了一些文本但未返回响应之后,我得出结论,问题出在节点上。我决定记录一下console.log语句之间的时间长度,结果是每2分钟一次。有了这个,我能够发现如果未将响应发送回客户端,则该节点的默认超时为2分钟。
我可以使用以下代码将响应设置为永不超时:
res.connection.setTimeout(0);
希望这对需要长时间保持连接以进行文件转换/传输等的其他人有所帮助...