Node.js:如何将YouTube视频转换为MP4再转换为MP3

15

我想将一个YouTube网址转换为mp3文件。目前,我使用Node的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块时执行转换?


3
你也可以使用 ytdl(url, {filter: 'audioonly'}),这样会给你一个带有缓冲数据的音频文件,你可以将其保存为 mp3 版本。 - Kiwi Rupela
2个回答

13

不要传递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,对吗? - Dread Boy
MP4文件通过流的方式发送给您,我怀疑YouTube不会让您仅请求单独的MP3流。换句话说,您必须下载整个文件。 - Michael Crook
有没有办法将该响应直接发送给客户端而不下载它,例如将可读流传输到res? - Aniket Kariya

0

这是一个比较老的问题,但可能会在未来帮助到某些人 - 当我寻找类似的解决方案以下载YouTube视频为MP3而无需将文件保存在服务器上时,我自己偶然发现了它。 我基本上选择将转换直接传输到响应中,并且正如我所希望的那样工作。

最初在另一个线程中回答了这个问题:通过Node.js进行FFmpeg MP3流媒体

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');
    });
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接