Skip to content

Instantly share code, notes, and snippets.

@twfarland
Last active March 17, 2023 23:44
Show Gist options
  • Save twfarland/857da418a195f7fbeb5438e252cc0bb6 to your computer and use it in GitHub Desktop.
Save twfarland/857da418a195f7fbeb5438e252cc0bb6 to your computer and use it in GitHub Desktop.
Downloads youtube videos and converts them to mp3 via streaming. ChatpGPT 4 wrote most of this (with minor babysitting from me).
using NAudio.Wave;
using NAudio.Lame;
using YoutubeExplode;
using YoutubeExplode.Videos.Streams;
namespace YoutubeDownloader
{
class Program
{
static async Task Main(string[] args)
{
// Check for the correct number of command-line arguments
if (args.Length != 2)
{
Console.WriteLine("Usage: YoutubeDownloader <url_list_file> <output_dir>");
return;
}
// Parse the command-line arguments
var urlListFile = args[0];
var outputDir = args[1];
// Read the list of URLs from the specified file
var urls = File.ReadAllLines(urlListFile).Distinct();
// Create the output directory if it doesn't exist
Directory.CreateDirectory(outputDir);
var youtube = new YoutubeClient();
// Define a function to download and convert a single video
async Task DownloadVideoAsync(string url)
{
try
{
Console.WriteLine($"Getting stream for {url}...");
// Get the video information and stream URL
var video = await youtube.Videos.GetAsync(url);
var outputPath = Path.Combine(outputDir, $"{video.Title}.mp3");
Console.WriteLine("Got stream for " + video.Title + " (" + video.Id + ")");
if (File.Exists(outputPath))
{
Console.WriteLine($"Skipping {video.Title} - file already exists");
return;
}
var streamInfoSet = await youtube.Videos.Streams.GetManifestAsync(video.Id);
var streamInfo = streamInfoSet.GetAudioOnlyStreams().GetWithHighestBitrate();
var streamUrl = streamInfo.Url;
Console.WriteLine($"Downloading {video.Title}...");
// Download the audio stream and convert it to MP3
var inputStream = new MediaFoundationReader(streamUrl);
var outputStream = new LameMP3FileWriter(outputPath, inputStream.WaveFormat, LAMEPreset.STANDARD);
await inputStream.CopyToAsync(outputStream);
Console.WriteLine($"Saved {video.Title} as mp3");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to download {url}: {ex.Message}");
Console.WriteLine(ex.StackTrace);
Console.WriteLine(ex.InnerException);
}
}
// Download the videos with the specified degree of parallelism
var tasks = urls
.Select(url =>
DownloadVideoAsync(url))
.AsParallel()
.WithDegreeOfParallelism(
Environment.ProcessorCount);
await Task.WhenAll(tasks);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment