Jakemmarsh
Jakemmarsh

Reputation: 4661

FFmpeg converting from video to audio missing duration

I'm attempting to load YouTube videos via their direct video URL (retrieved using ytdl-core). I load them using the request library. I then pipe the result to a stream, which is used as the input to ffmpeg (via fluent-ffmpeg). The code looks something like this:

var getAudioStream = function(req, res) {
    var requestUrl = 'http://youtube.com/watch?v=' + req.params.videoId;
    var audioStream = new PassThrough();
    var videoUrl;

    ytdl.getInfo(requestUrl, { downloadURL: true }, function(err, info) {
      res.setHeader('Content-Type', 'audio/x-wav');
      res.setHeader('Accept-Ranges', 'bytes');
      videoUrl = info.formats ? info.formats[0].url : '';
      request(videoUrl).pipe(audioStream);

      ffmpeg()
        .input(audioStream)
        .outputOptions('-map_metadata 0')
        .format('wav')
        .pipe(res);
    });
  };

This actually works just fine, and the frontend successfully receives just the audio in WAV format and is playable. However, the audio is missing any information about its size or duration (and all other metadata). This also makes it unseekable.

I'm assuming this is lost somewhere during the ffmpeg stage, because if I load the video directly via the URL passed to request it loads and plays fine, and has a set duration/is seekable. Any ideas?

Upvotes: 1

Views: 1096

Answers (1)

Brad
Brad

Reputation: 163272

It isn't possible to know the output size nor duration until it is finished. FFmpeg cannot know this information ahead of time in most cases. Even if it could, the way you are executing FFmpeg it prevents you from accessing the extra information.

Besides, to support seeking you need to support range requests. This isn't possible either, short of encoding the file up to the byte requested and streaming from there on.

Basically, this isn't possible by the nature of what you're doing.

Upvotes: 1

Related Questions