Skip to content

Instantly share code, notes, and snippets.

@ericBG
Created September 7, 2015 22:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericBG/159debbcdb606647afb8 to your computer and use it in GitHub Desktop.
Save ericBG/159debbcdb606647afb8 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web;
namespace ConsoleYoutubeDownloader
{
public class Downloader
{
private readonly string _ytPath;
private readonly string _folderPath;
public Downloader(string folderPath, string ytPath)
{
_folderPath = folderPath;
_ytPath = GetYoutubeURI(ytPath);
}
public async Task Download(Action<string> progressAction)
{
var apiRequest = WebRequest.Create($"http://youtubeinmp3.com/fetch/?format=text&video={_ytPath}");
Task<WebResponse> apiResponseTask = apiRequest.GetResponseAsync();
progressAction($"API requested for {_ytPath}");
string[] apiDetails;
using (var apiResponse = await apiResponseTask)
{
using (StreamReader sr = new StreamReader(apiResponse.GetResponseStream()))
{
var apiDetailsTask = sr.ReadToEndAsync();
progressAction($"Downloading API response for {_ytPath}");
apiDetails = (await apiDetailsTask).Split('\n');
}
}
if (apiDetails.Length != 3) throw new InvalidDataException("YoutubeInMP3 response invalid.");
var songRequest = WebRequest.Create(apiDetails[2]);
Task<WebResponse> songResponseTask = apiRequest.GetResponseAsync();
progressAction($"Song requested for {_ytPath}");
using (var songResponse = (await songResponseTask).GetResponseStream())
{
string fileName = Path.ChangeExtension(string.Join("", apiDetails[0].Skip(7).Except(Path.GetInvalidFileNameChars())), ".mp3");
Console.WriteLine(Path.Combine(_folderPath, fileName));
using (FileStream songStream = File.Create(Path.Combine(_folderPath, fileName)))
{
byte[] buffer = new byte[32*1024];
int read = songResponse.Read(buffer, 0, buffer.Length);
while (read > 0)
{
songStream.Write(buffer, 0, read);
read = songResponse.Read(buffer, 0, buffer.Length);
}
}
}
}
public static string GetYoutubeURI(string path)
{
Uri ytUri = new Uri(path);
if (ytUri.Host == "youtu.be")
return $"http://youtube.com/watch?v={ytUri.AbsolutePath.TrimStart('\\')}";
if (ytUri.Host.Contains("youtube.com"))
return $"http://youtube.com/watch?v={HttpUtility.ParseQueryString(ytUri.Query)["v"]}";
throw new ArgumentException("Not a valid Youtube URI.");
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleYoutubeDownloader
{
class Program
{
private static string _folderPath = "";
static void Main(string[] args)
{
List<string> toDownload = new List<string>();
if (args.Length > 0 && Directory.Exists(args[0]))
{
_folderPath = args[0];
if (args.Length > 1) toDownload.AddRange(args.Skip(1));
}
else
{
Console.WriteLine("Enter folder path where you would like output .mp3 files to be saved:");
for (;;)
{
string folderTemp = Console.ReadLine();
if (!Directory.Exists(folderTemp ?? ""))
{
Console.WriteLine("Not a valid folder path, please enter another one.");
continue;
}
_folderPath = folderTemp;
break;
}
}
List<Task> tasks = new List<Task>();
if (toDownload.Any())
tasks.AddRange(
toDownload.Select(
ytPath =>
new Downloader(_folderPath, ytPath).Download(Console.WriteLine)
.ContinueWith(t => Console.WriteLine("Completed download."))));
if (tasks.Any()) Task.WaitAll(tasks.ToArray());
for (;;)
{
Console.WriteLine("Enter any youtube videos you would like downloaded:");
tasks.Add(
new Downloader(_folderPath, Console.ReadLine()).Download(Console.WriteLine)
.ContinueWith(t => Console.WriteLine("Completed download.")));
if (tasks.Any()) Task.WaitAll(tasks.ToArray());
foreach (Task t in tasks.ToArray()) if (t.IsCompleted) tasks.Remove(t);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment