15

I want to convert a youtube url into an mp3 file. Currently, I download the mp4 using node's ytdl module, like so:

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

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

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

Once the download is complete, I convert the mp4 into mp3 using the fluent-ffmpeg module, like so:

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

I don't want to have to save the entire mp4 before starting the mp3 conversion. How do I pipe the mp4 into proc so it carries out the conversion as it receives the mp4 chunks?

tldr
  • 11,924
  • 15
  • 75
  • 120
  • 3
    you can also ytdl(url,{filter: 'audioonly'}) then it will give you audio file with buffer data and you can save it as mp3 version. – Kiwi Rupela Dec 31 '18 at 11:59

2 Answers2

13

Instead of passing the location of mp4 file, pass in the ytdl stream as the source, like so:

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'
        )
tldr
  • 11,924
  • 15
  • 75
  • 120
  • If I understand correctly, this still downloads entire mp4 but instead of saving and converting, it converts while downloading/streaming. If original mp4 file is 80MB and resulting mp3 is 6MB, it downloads 80MB, right? – Dread Boy May 01 '15 at 16:18
  • the mp4 is sent to you via a stream, youtube I doubt will let you request just the sepreate mp3 stream.. you have to dl the whole thing in other works – Michael Crook May 08 '15 at 00:20
  • is there any way to send that response directly to the client without downloading it, like piping the readable stream to res – Aniket Kariya May 19 '20 at 14:38
0

This is a relatively old question, but may help someone in the future - I stumbled upon it myself when looking for a similar solution to download a youtube vid as mp3 without needing to save the file on the server. I basically settled on piping the conversion directly to response and is working as I had hoped.

Originally answered this question in a different thread: 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');
    });
};
ejuhjav
  • 2,660
  • 2
  • 21
  • 32