No audio in above 360p video downloaded from ytdl-core express?

Viewed 1864

I have made an api which is downloading videos from the link of youtube link but I'm not enable to download the video with its audio above 360p format. It is downloading only video and there is no audio.
Is there any solution to this ?

3 Answers

Typically 1080p or better video does not have audio encoded with it. The audio must be downloaded separately and merged via an appropriate encoding library. ffmpeg is the most widely used tool, with many Node.js modules available. Use the format objects returned from ytdl.getInfo to download specific streams to combine to fit your needs. Look at https://github.com/fent/node-ytdl-core/blob/master/example/ffmpeg.js for an example on doing this.

You can specific the video quality

const video = ytdl('http://www.youtube.com/watch?v=e_RsG3HPpA0',{quality: 18});
video.on('progress', function(info) {
  console.log('Download progress')
})
video.on('end', function(info) {
  console.log('Download finish')
})

video.pipe(fs.createWriteStream('video.mp4'));

Please check the option of quality value by this link

If you are using ytdl-core then the problem is with the itags and the availability of the itag you need.There are 3 itags only that support both video and audio and rest itags only support either audio or just video. For video and audio in ytdl-core you need to specifically check if the URl supports 720p or 1080p or not. I created two functions that can help you alot. what you can do is that simple send an xmlhttprequest from index.html and wait for link response so that you or your user can download from that link. "fup90" means false url provided and inc90 denotes incorrect URL so that you can handle the error if the URL is not a youtube URL. The code is shown below and note that you send an xmlhttpreqest using post method and with data in json string in this format var data = {downloadType:"audio"/"video",quality:"required itag",url:"youtube video url"}.

const ytdl = require('ytdl-core');
const express = require('express');
const parser = require('body-parser');
const app = express();

app.use(parser.text());
app.use(express.static(__dirname + "\\static"));

// video formats 18 - 360p and  22 - 720p
// audio

async function getAudioData(videoURL) {

    let videoid = await ytdl.getURLVideoID(videoURL);
    let info = await ytdl.getInfo(videoid);
    // let format = ytdl.chooseFormat(info.formats, { quality: '134' }); for video
    // var format = ytdl.filterFormats(info.formats, 'videoandaudio');

    let format = ytdl.filterFormats(info.formats, 'audioonly');
    let required_url = 0;
    format.forEach(element => {
        if (element.mimeType == `audio/mp4; codecs="mp4a.40.2"`) {
            required_url = element.url;
        }
    });

    return required_url;
}

async function getVideoData(videoURL, qualityCode) {
    try {
        let videoid = ytdl.getURLVideoID(videoURL);

        let info = await ytdl.getInfo(videoid);
        var ifExists = true;
        if (qualityCode == 22) {
            info.formats.forEach(element => {
                if (element.itag == 22) {
                    qualityCode = 22;
                } else {
                    qualityCode = 18;
                    ifExists = false;
                }
            });
        }
        let format = ytdl.chooseFormat(info.formats, { quality: qualityCode });
        var answers = {
            url: format.url,
            exists: ifExists
        }
    } catch (e) {
        var answers = {
            url: "fup90",
            exists: false
        }
    }
    return answers;
}


app.get("/", (req, res) => {
    res.sendFile(__dirname + "\\index.html");
});

app.post("/getdownload", async(req, res) => {
    let data = JSON.parse(req.body);
    if (data.downloadType === "video") {
        var answer = await getVideoData(data.url, data.quality);
        if (answer.url === "fup90") {
            res.send("inc90");
        } else {
            res.send(answer.exists ? answer.url : "xformat");
        }
    } else if (data.downloadType === "audio") {
        var audioLink = await getAudioData(data.url);
        res.send(audioLink);
    } else {
        res.send("error from server");
    }
});


app.listen(8000, () => {
    console.log("server started at http://localhost:8000");
});

Related