Creating a Discord bot to save YouTube audio locally

Hey everyone, I’m working on a Discord bot that plays music from a local folder. I’m trying to add a feature where it can download songs from YouTube and save them locally. But I’m running into a problem.

When I use the download command, it starts the process and creates a file in the directory. However, the file always ends up empty (0 bytes) and the download never completes. Here is a simplified version of my code:

const ytdl = require('ytdl-core');
const fs = require('fs');

client.on('messageCreate', async (message) => {
  if (message.content.startsWith('!getmusic')) {
    const url = message.content.split(' ')[1];
    const info = await ytdl.getInfo(url);
    const title = info.videoDetails.title.replace(/[^\w\s]/gi, '');
    const outputPath = `./music/${title}.mp3`;

    const stream = ytdl(url, { filter: 'audioonly' });
    const file = fs.createWriteStream(outputPath);
    stream.pipe(file);

    file.on('finish', () => {
      message.reply('Download complete!');
    });
  }
});

I’m not sure what I’m doing wrong. Any ideas on how to fix this? Thanks!

hey, try combining ytdl-core with ffmpeg for audio. use fluent-ffmpeg:

const ffmpeg = require(‘fluent-ffmpeg’);
ffmpeg(stream)
.audioBitrate(128)
.save(outputPath)
.on(‘end’, () => message.reply(‘done!’));

this worked for me, hope it helps!

I encountered a similar issue when developing a YouTube downloader. One thing that often gets overlooked is the content disposition of the stream. YouTube sometimes sends audio in a fragmented format, which can cause issues with direct piping.

Try using the ‘audioFormat’ option to specify a desired format:

const stream = ytdl(url, { 
  filter: 'audioonly', 
  quality: 'highestaudio',
  format: 'mp3'
});

Also, consider implementing a progress indicator. This can help you track if the download is actually progressing or stalling:

let downloadedBytes = 0;
stream.on('data', (chunk) => {
  downloadedBytes += chunk.length;
  console.log(`Downloaded: ${downloadedBytes} bytes`);
});

If these modifications don’t resolve the issue, you might want to explore alternative libraries like fluent-ffmpeg in combination with ytdl-core for more reliable audio extraction.

I’ve faced a similar issue when working with ytdl-core. The problem might be that the download is terminating prematurely. Here’s what worked for me:

Add error handling to catch any issues during the download process, use the ‘end’ event on the stream instead of relying solely on the ‘finish’ event of the file, and ensure you have the latest version of ytdl-core installed.

Try modifying your code like this:

stream.pipe(file);

stream.on('error', (err) => {
  console.error('Download error:', err);
  message.reply('Error during download. Please try again.');
});

stream.on('end', () => {
  file.close();
  message.reply('Download complete!');
});

This approach helped me resolve the empty file issue. Also, make sure you have sufficient disk space and proper write permissions for the output directory. If the problem persists, you might want to consider using a different library like youtube-dl-exec for more robust downloading capabilities.