【问题标题】:node.js : how to pipe - youtube to mp4 to mp3node.js:如何管道 - youtube 到 mp4 到 mp3
【发布时间】:2013-08-12 16:03:31
【问题描述】:

我想将 youtube 网址转换为 mp3 文件。目前,我使用节点的 ytdl 模块下载 mp4,如下所示:

fs = require 'fs'
ytdl = require 'ytdl'

url = 'http://www.youtube.com/watch?v=v8bOTvg-iaU'
mp4 = './video.mp4'

ytdl(url).pipe(fs.createWriteStream(mp4))

下载完成后,我使用 fluent-ffmpeg 模块将 mp4 转换为 mp3,如下所示:

ffmpeg = require 'fluent-ffmpeg'

mp4 = './video.mp4'
mp3 = './audio.mp3'

proc = new ffmpeg({source:mp4})
proc.setFfmpegPath('/Applications/ffmpeg')
proc.saveToFile(mp3, (stdout, stderr)->
            return console.log stderr if err?
            return console.log 'done'
        )

我不想在开始 mp3 转换之前保存整个 mp4。如何将 mp4 通过管道传输到 proc 中,以便它在收到 mp4 块时执行转换?

【问题讨论】:

  • 你也可以 ytdl(url,{filter: 'audioonly'}) 然后它会给你带有缓冲数据的音频文件,你可以将它保存为 mp3 版本。

标签: node.js stream pipe


【解决方案1】:

不传递 mp4 文件的位置,而是传递 ytdl 流作为源,如下所示:

stream = ytdl(url)

proc = new ffmpeg({source:stream})
proc.setFfmpegPath('/Applications/ffmpeg')
proc.saveToFile(mp3, (stdout, stderr)->
            return console.log stderr if err?
            return console.log 'done'
        )

【讨论】:

  • 如果我理解正确,这仍然会下载整个 mp4,但不是保存和转换,而是在下载/流式传输时转换。如果原始 mp4 文件是 80MB,而生成的 mp3 文件是 6MB,那么它会下载 80MB,对吧?
  • mp4 是通过流发送给你的,我怀疑 youtube 会让你只请求单独的 mp3 流.. 你必须在其他作品中 dl 整个事情
  • 有没有办法直接将响应发送到客户端而不下载它,比如将可读流通过管道传输到 res
【解决方案2】:

这是一个相对较老的问题,但将来可能会对某人有所帮助 - 在寻找类似的解决方案以将 youtube vid 下载为 mp3 而无需将文件保存在服务器上时,我自己偶然发现了这个问题。我基本上决定将转换直接传递给响应,并且按我希望的那样工作。

最初在另一个帖子中回答了这个问题:ffmpeg mp3 streaming via node js

module.exports.toMp3 = function(req, res, next){
    var id = req.params.id; // extra param from front end
    var title = req.params.title; // extra param from front end
    var url = 'https://www.youtube.com/watch?v=' + id;
    var stream = youtubedl(url); //include youtbedl ... var youtubedl = require('ytdl');

    //set response headers
    res.setHeader('Content-disposition', 'attachment; filename=' + title + '.mp3');
    res.setHeader('Content-type', 'audio/mpeg');

    //set stream for conversion
    var proc = new ffmpeg({source: stream});

    //currently have ffmpeg stored directly on the server, and ffmpegLocation is the path to its location... perhaps not ideal, but what I'm currently settled on. And then sending the output directly to the response.
    proc.setFfmpegPath(ffmpegLocation);
    proc.withAudioCodec('libmp3lame')
        .toFormat('mp3')
        .output(res)
        .run();
    proc.on('end', function() {
        console.log('finished');
    });
};

【讨论】:

    【解决方案3】:

    这对我不起作用。如果我设置了本地 .mp4 文件但使用流没有,则下面的代码有效。

    var ytUrl = 'http://www.youtube.com/watch?v=' + data.videoId;
            var stream = youtubedl(ytUrl, {
                quality: 'highest'
            });
            var saveLocation = './mp3/' + data.videoId + '.mp3';
    
            var proc = new ffmpeg({
                source: './mp3/test.mp4' //using 'stream' does not work
            })
                .withAudioCodec('libmp3lame')
                .toFormat('mp3')
                .saveToFile(saveLocation, function(stdout, stderr) {
                    console.log('file has been converted succesfully');
                });
    

    【讨论】:

    • @Tim: 上面代码块中流的用途是什么
    猜你喜欢
    • 2022-01-02
    • 2014-02-20
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-10-19
    • 2019-04-03
    • 2016-06-12
    • 1970-01-01
    相关资源
    最近更新 更多