Version 1.0.1
This commit is contained in:
parent
7dfa5bdf5d
commit
dadd15f7bc
|
@ -8,6 +8,8 @@ using YoutubeExplode.Videos;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using YoutubeExplode.Playlists;
|
||||||
|
using YoutubeExplode.Channels;
|
||||||
|
|
||||||
namespace Tesses.YouTubeDownloader.Server
|
namespace Tesses.YouTubeDownloader.Server
|
||||||
{
|
{
|
||||||
|
@ -94,22 +96,149 @@ namespace Tesses.YouTubeDownloader.Server
|
||||||
);
|
);
|
||||||
return asAscii;
|
return asAscii;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task GetAsync(ServerContext ctx)
|
public override async Task GetAsync(ServerContext ctx)
|
||||||
{
|
{
|
||||||
string path=ctx.UrlAndQuery;
|
string path=ctx.UrlAndQuery;
|
||||||
if(path.StartsWith("/File/"))
|
/*if(path.StartsWith("/File/NotConverted/"))
|
||||||
{
|
{
|
||||||
using(var s = await baseCtl.OpenReadAsyncWithLength( WebUtility.UrlDecode(path.Substring(6))))
|
// redirect to new
|
||||||
|
// /File/NotConverted/xxxxxxxxxxx.mp4
|
||||||
|
string idmp4=WebUtility.UrlDecode(path.Substring(19));
|
||||||
|
if(idmp4.Length == 15)
|
||||||
|
{
|
||||||
|
string id=Path.GetFileNameWithoutExtension(idmp4);
|
||||||
|
string path2 = $"Info/{id}.json";
|
||||||
|
|
||||||
|
if(!await baseCtl.FileExistsAsync(path2))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
} var data= await baseCtl.ReadAllTextAsync(path2);
|
||||||
|
var data2=JsonConvert.DeserializeObject<SavedVideo>(data);
|
||||||
|
var loc= await BestStreams.GetPathResolution(baseCtl,data2,Resolution.PreMuxed);
|
||||||
|
|
||||||
|
if(!await baseCtl.FileExistsAsync(loc))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using(var s = await baseCtl.OpenReadAsyncWithLength(loc))
|
||||||
|
{
|
||||||
|
await ctx.SendStreamAsync(s,HeyRed.Mime.MimeTypesMap.GetMimeType(loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(path.StartsWith("/File/Converted/"))
|
||||||
|
{
|
||||||
|
// redirect to new
|
||||||
|
// /File/NotConverted/xxxxxxxxxxx.mp4
|
||||||
|
string idmp4=WebUtility.UrlDecode(path.Substring(16));
|
||||||
|
if(idmp4.Length == 15)
|
||||||
|
{
|
||||||
|
string id=Path.GetFileNameWithoutExtension(idmp4);
|
||||||
|
string path2 = $"Info/{id}.json";
|
||||||
|
|
||||||
|
if(!await baseCtl.FileExistsAsync(path2))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
} var data= await baseCtl.ReadAllTextAsync(path2);
|
||||||
|
var data2=JsonConvert.DeserializeObject<SavedVideo>(data);
|
||||||
|
var loc= await BestStreams.GetPathResolution(baseCtl,data2,Resolution.Mux);
|
||||||
|
|
||||||
|
if(!await baseCtl.FileExistsAsync(loc))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using(var s = await baseCtl.OpenReadAsyncWithLength(loc))
|
||||||
|
{
|
||||||
|
await ctx.SendStreamAsync(s,HeyRed.Mime.MimeTypesMap.GetMimeType(loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(path.StartsWith("/File/Audio/"))
|
||||||
|
{
|
||||||
|
// redirect to new
|
||||||
|
// /File/NotConverted/xxxxxxxxxxx.mp4
|
||||||
|
string idmp4=WebUtility.UrlDecode(path.Substring(12));
|
||||||
|
if(idmp4.Length == 15)
|
||||||
|
{
|
||||||
|
string id=Path.GetFileNameWithoutExtension(idmp4);
|
||||||
|
string path2 = $"Info/{id}.json";
|
||||||
|
|
||||||
|
if(!await baseCtl.FileExistsAsync(path2))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
} var data= await baseCtl.ReadAllTextAsync(path2);
|
||||||
|
var data2=JsonConvert.DeserializeObject<SavedVideo>(data);
|
||||||
|
var loc= await BestStreams.GetPathResolution(baseCtl,data2,Resolution.AudioOnly);
|
||||||
|
|
||||||
|
if(!await baseCtl.FileExistsAsync(loc))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using(var s = await baseCtl.OpenReadAsyncWithLength(loc))
|
||||||
|
{
|
||||||
|
await ctx.SendStreamAsync(s,HeyRed.Mime.MimeTypesMap.GetMimeType(loc));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(path.StartsWith("/File/Info/"))
|
||||||
|
{
|
||||||
|
string idjson=WebUtility.UrlDecode(path.Substring(11));
|
||||||
|
string path2 = $"Info/{idjson}";
|
||||||
|
if(!await baseCtl.FileExistsAsync(path2))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var data= await baseCtl.ReadAllTextAsync(path2);
|
||||||
|
var data2=JsonConvert.DeserializeObject<SavedVideo>(data);
|
||||||
|
await ctx.SendJsonAsync(data2.ToLegacy());
|
||||||
|
}
|
||||||
|
else*/ if(path.StartsWith("/File/"))
|
||||||
|
{
|
||||||
|
string file=WebUtility.UrlDecode(path.Substring(6));
|
||||||
|
if(!await baseCtl.FileExistsAsync(file))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using(var s = await baseCtl.OpenReadAsyncWithLength(file))
|
||||||
{
|
{
|
||||||
await ctx.SendStreamAsync(s);
|
await ctx.SendStreamAsync(s);
|
||||||
}
|
}
|
||||||
}else if(path.StartsWith("/GetFiles/"))
|
}/*else if(path.StartsWith("/File-v2/"))
|
||||||
|
{
|
||||||
|
string file=WebUtility.UrlDecode(path.Substring(9));
|
||||||
|
if(!await baseCtl.FileExistsAsync(file))
|
||||||
|
{
|
||||||
|
await NotFoundServer.ServerNull.GetAsync(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using(var s = await baseCtl.OpenReadAsyncWithLength(file))
|
||||||
|
{
|
||||||
|
await ctx.SendStreamAsync(s);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
else if(path.StartsWith("/GetFiles/"))
|
||||||
{
|
{
|
||||||
await ctx.SendJsonAsync(baseCtl.EnumerateFiles( WebUtility.UrlDecode(path.Substring(10))).ToList());
|
await ctx.SendJsonAsync(baseCtl.EnumerateFiles( WebUtility.UrlDecode(path.Substring(10))).ToList());
|
||||||
}else if(path.StartsWith("/GetDirectories/"))
|
}else if(path.StartsWith("/GetDirectories/"))
|
||||||
{
|
{
|
||||||
await ctx.SendJsonAsync(baseCtl.EnumerateDirectories( WebUtility.UrlDecode(path.Substring(16))).ToList());
|
await ctx.SendJsonAsync(baseCtl.EnumerateDirectories( WebUtility.UrlDecode(path.Substring(16))).ToList());
|
||||||
}else if(path.StartsWith("/FileExists/"))
|
}else if(path.StartsWith("/FileExists-v2/"))
|
||||||
|
{
|
||||||
|
await ctx.SendTextAsync(baseCtl.FileExists(WebUtility.UrlDecode(path.Substring(15))) ? "true" : "false","text/plain");
|
||||||
|
}
|
||||||
|
else if(path.StartsWith("/FileExists/"))
|
||||||
{
|
{
|
||||||
await ctx.SendTextAsync(baseCtl.FileExists(WebUtility.UrlDecode(path.Substring(12))) ? "true" : "false","text/plain");
|
await ctx.SendTextAsync(baseCtl.FileExists(WebUtility.UrlDecode(path.Substring(12))) ? "true" : "false","text/plain");
|
||||||
}else if(path.StartsWith("/DirectoryExists/"))
|
}else if(path.StartsWith("/DirectoryExists/"))
|
||||||
|
@ -132,7 +261,7 @@ namespace Tesses.YouTubeDownloader.Server
|
||||||
{
|
{
|
||||||
|
|
||||||
//Console.WriteLine("F is not null");
|
//Console.WriteLine("F is not null");
|
||||||
string filename = Path.GetFileName(path0);
|
string filename = $"{v.Title}-{Path.GetFileName(path0)}";
|
||||||
string header=GetVideoContentDisposition(filename).ToString();
|
string header=GetVideoContentDisposition(filename).ToString();
|
||||||
ctx.ResponseHeaders.Add("Content-Disposition",header);
|
ctx.ResponseHeaders.Add("Content-Disposition",header);
|
||||||
using(var strm = await baseCtl.OpenReadAsync(path0))
|
using(var strm = await baseCtl.OpenReadAsync(path0))
|
||||||
|
@ -172,7 +301,7 @@ namespace Tesses.YouTubeDownloader.Server
|
||||||
{
|
{
|
||||||
|
|
||||||
//Console.WriteLine("F is not null");
|
//Console.WriteLine("F is not null");
|
||||||
string filename = Path.GetFileName(path0);
|
string filename = $"{v.Title}-{Path.GetFileName(path0)}";
|
||||||
string header=GetVideoContentDisposition(filename).ToString();
|
string header=GetVideoContentDisposition(filename).ToString();
|
||||||
ctx.ResponseHeaders.Add("Content-Disposition",header);
|
ctx.ResponseHeaders.Add("Content-Disposition",header);
|
||||||
using(var strm = await baseCtl.OpenReadAsync(path0))
|
using(var strm = await baseCtl.OpenReadAsync(path0))
|
||||||
|
@ -197,6 +326,10 @@ namespace Tesses.YouTubeDownloader.Server
|
||||||
{
|
{
|
||||||
this.Downloader=downloader;
|
this.Downloader=downloader;
|
||||||
Add("/AddItem",AddItem);
|
Add("/AddItem",AddItem);
|
||||||
|
Add("/AddChannel",AddChannel);
|
||||||
|
Add("/AddUser",AddUser);
|
||||||
|
Add("/AddPlaylist",AddPlaylist);
|
||||||
|
Add("/AddVideo",AddVideo);
|
||||||
Add("/Progress",ProgressFunc);
|
Add("/Progress",ProgressFunc);
|
||||||
Add("/QueueList",QueueList);
|
Add("/QueueList",QueueList);
|
||||||
}
|
}
|
||||||
|
@ -208,7 +341,7 @@ namespace Tesses.YouTubeDownloader.Server
|
||||||
{
|
{
|
||||||
await ctx.SendJsonAsync(Downloader.GetProgress());
|
await ctx.SendJsonAsync(Downloader.GetProgress());
|
||||||
}
|
}
|
||||||
public async Task AddItem(ServerContext ctx)
|
public async Task AddVideo(ServerContext ctx)
|
||||||
{
|
{
|
||||||
string id;
|
string id;
|
||||||
if(ctx.QueryParams.TryGetFirst("v",out id))
|
if(ctx.QueryParams.TryGetFirst("v",out id))
|
||||||
|
@ -225,7 +358,103 @@ namespace Tesses.YouTubeDownloader.Server
|
||||||
VideoId? id1=VideoId.TryParse(id);
|
VideoId? id1=VideoId.TryParse(id);
|
||||||
if(id1.HasValue)
|
if(id1.HasValue)
|
||||||
{
|
{
|
||||||
await Downloader.AddItemAsync(id1,resolution);
|
await Downloader.AddVideoAsync(id1.Value,resolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await ctx.SendTextAsync(
|
||||||
|
$"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
public async Task AddItem(ServerContext ctx)
|
||||||
|
{
|
||||||
|
string id;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("v",out id))
|
||||||
|
{
|
||||||
|
Resolution resolution=Resolution.PreMuxed;
|
||||||
|
string res;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("res",out res))
|
||||||
|
{
|
||||||
|
if(!Enum.TryParse<Resolution>(res,out resolution))
|
||||||
|
{
|
||||||
|
resolution=Resolution.PreMuxed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Downloader.AddItemAsync(id,resolution);
|
||||||
|
|
||||||
|
}
|
||||||
|
await ctx.SendTextAsync(
|
||||||
|
$"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
public async Task AddUser(ServerContext ctx)
|
||||||
|
{
|
||||||
|
string id;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("v",out id))
|
||||||
|
{
|
||||||
|
Resolution resolution=Resolution.PreMuxed;
|
||||||
|
string res;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("res",out res))
|
||||||
|
{
|
||||||
|
if(!Enum.TryParse<Resolution>(res,out resolution))
|
||||||
|
{
|
||||||
|
resolution=Resolution.PreMuxed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UserName? id1=UserName.TryParse(id);
|
||||||
|
if(id1.HasValue)
|
||||||
|
{
|
||||||
|
await Downloader.AddUserAsync(id1.Value,resolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await ctx.SendTextAsync(
|
||||||
|
$"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddChannel(ServerContext ctx)
|
||||||
|
{
|
||||||
|
string id;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("v",out id))
|
||||||
|
{
|
||||||
|
Resolution resolution=Resolution.PreMuxed;
|
||||||
|
string res;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("res",out res))
|
||||||
|
{
|
||||||
|
if(!Enum.TryParse<Resolution>(res,out resolution))
|
||||||
|
{
|
||||||
|
resolution=Resolution.PreMuxed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChannelId? id1=ChannelId.TryParse(id);
|
||||||
|
if(id1.HasValue)
|
||||||
|
{
|
||||||
|
await Downloader.AddChannelAsync(id1.Value,resolution);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await ctx.SendTextAsync(
|
||||||
|
$"<html><head><titleYou Will Be Redirected in 5 Sec</title><meta http-equiv=\"Refresh\" content=\"5; url='../../'\" /></head><body><h1>You Will Be Redirected in 5 Sec</h1></body></html>\n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddPlaylist(ServerContext ctx)
|
||||||
|
{
|
||||||
|
string id;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("v",out id))
|
||||||
|
{
|
||||||
|
Resolution resolution=Resolution.PreMuxed;
|
||||||
|
string res;
|
||||||
|
if(ctx.QueryParams.TryGetFirst("res",out res))
|
||||||
|
{
|
||||||
|
if(!Enum.TryParse<Resolution>(res,out resolution))
|
||||||
|
{
|
||||||
|
resolution=Resolution.PreMuxed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PlaylistId? id1=PlaylistId.TryParse(id);
|
||||||
|
if(id1.HasValue)
|
||||||
|
{
|
||||||
|
await Downloader.AddPlaylistAsync(id1.Value,resolution);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await ctx.SendTextAsync(
|
await ctx.SendTextAsync(
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
<PackageId>Tesses.YouTubeDownloader.Server</PackageId>
|
<PackageId>Tesses.YouTubeDownloader.Server</PackageId>
|
||||||
<Author>Mike Nolan</Author>
|
<Author>Mike Nolan</Author>
|
||||||
<Company>Tesses</Company>
|
<Company>Tesses</Company>
|
||||||
<Version>1.0.0.0</Version>
|
<Version>1.0.1.0</Version>
|
||||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
<AssemblyVersion>1.0.1.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.0</FileVersion>
|
<FileVersion>1.0.1.0</FileVersion>
|
||||||
<Description>Adds WebServer to TYTD</Description>
|
<Description>Adds WebServer to TYTD</Description>
|
||||||
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
|
|
|
@ -241,6 +241,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
audioInfo.AudioCodec=asi.AudioCodec;
|
audioInfo.AudioCodec=asi.AudioCodec;
|
||||||
AudioInfo = audioInfo;
|
AudioInfo = audioInfo;
|
||||||
}
|
}
|
||||||
|
_si=info;
|
||||||
//vsi.VideoCodec
|
//vsi.VideoCodec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
var (Video, Resolution) = Dequeue(out hasAny);
|
var (Video, Resolution) = Dequeue(out hasAny);
|
||||||
if (hasAny)
|
if (hasAny)
|
||||||
{
|
{
|
||||||
await DownloadVideoAsync(Video, Resolution, token);
|
await DownloadVideoAsync(Video, Resolution, token,new Progress<double>(ReportProgress),true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -75,21 +75,41 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private async Task DownloadVideoAsync(SavedVideo video, Resolution resolution, CancellationToken token)
|
public async Task DownloadNoQueue(SavedVideo info,Resolution resolution=Resolution.Mux,CancellationToken token=default(CancellationToken),IProgress<double> progress=null)
|
||||||
|
{
|
||||||
|
|
||||||
|
await DownloadVideoAsync(info,resolution,token,progress,false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<SavedVideo> GetSavedVideoAsync(VideoId id)
|
||||||
|
{
|
||||||
|
VideoMediaContext context=new VideoMediaContext(id,Resolution.PreMuxed);
|
||||||
|
List<(SavedVideo Video,Resolution)> s=new List<(SavedVideo Video, Resolution)>();
|
||||||
|
await context.FillQueue(this,s);
|
||||||
|
if(s.Count> 0)
|
||||||
|
{
|
||||||
|
return s.First().Video;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async Task DownloadVideoAsync(SavedVideo video, Resolution resolution, CancellationToken token=default(CancellationToken),IProgress<double> progress=null,bool report=true)
|
||||||
{
|
{
|
||||||
switch (resolution)
|
switch (resolution)
|
||||||
{
|
{
|
||||||
case Resolution.Mux:
|
case Resolution.Mux:
|
||||||
await DownloadVideoMuxedAsync(video,token);
|
await DownloadVideoMuxedAsync(video,token,progress,report);
|
||||||
break;
|
break;
|
||||||
case Resolution.PreMuxed:
|
case Resolution.PreMuxed:
|
||||||
await DownloadPreMuxedVideoAsync(video, token);
|
await DownloadPreMuxedVideoAsync(video, token,progress,report);
|
||||||
break;
|
break;
|
||||||
case Resolution.AudioOnly:
|
case Resolution.AudioOnly:
|
||||||
await DownloadAudioOnlyAsync(video,token);
|
await DownloadAudioOnlyAsync(video,token,progress,report);
|
||||||
break;
|
break;
|
||||||
case Resolution.VideoOnly:
|
case Resolution.VideoOnly:
|
||||||
await DownloadVideoOnlyAsync(video,token);
|
await DownloadVideoOnlyAsync(video,token,progress,report);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,15 +369,15 @@ namespace Tesses.YouTubeDownloader
|
||||||
Directory.Delete("TYTD_TEMP",true);
|
Directory.Delete("TYTD_TEMP",true);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
private async Task DownloadVideoMuxedAsync(SavedVideo video,CancellationToken token)
|
private async Task DownloadVideoMuxedAsync(SavedVideo video,CancellationToken token,IProgress<double> progress,bool report=true)
|
||||||
{
|
{
|
||||||
bool isValid=true;
|
bool isValid=true;
|
||||||
isValid=await DownloadVideoOnlyAsync(video,token);
|
isValid=await DownloadVideoOnlyAsync(video,token,progress,report);
|
||||||
if(token.IsCancellationRequested || !isValid)
|
if(token.IsCancellationRequested || !isValid)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isValid = await DownloadAudioOnlyAsync(video,token);
|
isValid = await DownloadAudioOnlyAsync(video,token,progress,report);
|
||||||
if(token.IsCancellationRequested || !isValid)
|
if(token.IsCancellationRequested || !isValid)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -367,6 +387,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(report)
|
||||||
ReportStartVideo(video,Resolution.Mux,0);
|
ReportStartVideo(video,Resolution.Mux,0);
|
||||||
string complete = $"Muxed/{video.Id}.mkv";
|
string complete = $"Muxed/{video.Id}.mkv";
|
||||||
string incomplete = $"Muxed/{video.Id}incomplete.mkv";
|
string incomplete = $"Muxed/{video.Id}incomplete.mkv";
|
||||||
|
@ -376,12 +397,12 @@ namespace Tesses.YouTubeDownloader
|
||||||
if(await Continue(complete))
|
if(await Continue(complete))
|
||||||
{
|
{
|
||||||
|
|
||||||
if(await MuxVideosAsync(video,complete_vidonly,complete_audonly,incomplete,new Progress<double>(ReportProgress),token))
|
if(await MuxVideosAsync(video,complete_vidonly,complete_audonly,incomplete,progress,token))
|
||||||
{
|
{
|
||||||
RenameFile(incomplete,complete);
|
RenameFile(incomplete,complete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(report)
|
||||||
ReportEndVideo(video,Resolution.Mux);
|
ReportEndVideo(video,Resolution.Mux);
|
||||||
}
|
}
|
||||||
private void DeleteIfExists(string path)
|
private void DeleteIfExists(string path)
|
||||||
|
@ -391,10 +412,12 @@ namespace Tesses.YouTubeDownloader
|
||||||
File.Delete(path);
|
File.Delete(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<bool> DownloadVideoOnlyAsync(SavedVideo video,CancellationToken token)
|
public async Task<bool> DownloadVideoOnlyAsync(SavedVideo video,CancellationToken token,IProgress<double> progress,bool report=true)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool ret=false;
|
bool ret=false;
|
||||||
var streams = await BestStreamInfo.GetBestStreams(this, video.Id, token, false);
|
var streams = await BestStreamInfo.GetBestStreams(this, video.Id, token, false);
|
||||||
|
if(!can_download) return false;
|
||||||
if(streams != null)
|
if(streams != null)
|
||||||
{
|
{
|
||||||
await MoveLegacyStreams(video,streams);
|
await MoveLegacyStreams(video,streams);
|
||||||
|
@ -412,16 +435,18 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(report)
|
||||||
ReportStartVideo(video, Resolution.VideoOnly,streams.VideoOnlyStreamInfo.Size.Bytes);
|
ReportStartVideo(video, Resolution.VideoOnly,streams.VideoOnlyStreamInfo.Size.Bytes);
|
||||||
long len=await GetLengthAsync(incomplete);
|
long len=await GetLengthAsync(incomplete);
|
||||||
|
|
||||||
using(var dest = await OpenOrCreateAsync(incomplete))
|
using(var dest = await OpenOrCreateAsync(incomplete))
|
||||||
{
|
{
|
||||||
ret=await CopyStreamAsync(strm,dest,len,streams.VideoOnlyStreamInfo.Size.Bytes,4096,new Progress<double>(ReportProgress),token);
|
ret=await CopyStreamAsync(strm,dest,len,streams.VideoOnlyStreamInfo.Size.Bytes,4096,progress,token);
|
||||||
}
|
}
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
RenameFile(incomplete,complete);
|
RenameFile(incomplete,complete);
|
||||||
|
if(report)
|
||||||
ReportEndVideo(video, Resolution.VideoOnly);
|
ReportEndVideo(video, Resolution.VideoOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,10 +507,12 @@ namespace Tesses.YouTubeDownloader
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<bool> DownloadAudioOnlyAsync(SavedVideo video,CancellationToken token)
|
private async Task<bool> DownloadAudioOnlyAsync(SavedVideo video,CancellationToken token,IProgress<double> progress,bool report=true)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool ret=false;
|
bool ret=false;
|
||||||
var streams = await BestStreamInfo.GetBestStreams(this, video.Id, token, false);
|
var streams = await BestStreamInfo.GetBestStreams(this, video.Id, token, false);
|
||||||
|
if(!can_download) return false;
|
||||||
if(streams != null)
|
if(streams != null)
|
||||||
{
|
{
|
||||||
string complete = $"AudioOnly/{video.Id}.{streams.AudioOnlyStreamInfo.Container}";
|
string complete = $"AudioOnly/{video.Id}.{streams.AudioOnlyStreamInfo.Container}";
|
||||||
|
@ -504,16 +531,18 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if(report)
|
||||||
ReportStartVideo(video, Resolution.AudioOnly,streams.AudioOnlyStreamInfo.Size.Bytes);
|
ReportStartVideo(video, Resolution.AudioOnly,streams.AudioOnlyStreamInfo.Size.Bytes);
|
||||||
long len=await GetLengthAsync(incomplete);
|
long len=await GetLengthAsync(incomplete);
|
||||||
|
|
||||||
using(var dest = await OpenOrCreateAsync(incomplete))
|
using(var dest = await OpenOrCreateAsync(incomplete))
|
||||||
{
|
{
|
||||||
ret=await CopyStreamAsync(strm,dest,len,streams.AudioOnlyStreamInfo.Size.Bytes,4096,new Progress<double>(ReportProgress),token);
|
ret=await CopyStreamAsync(strm,dest,len,streams.AudioOnlyStreamInfo.Size.Bytes,4096,progress,token);
|
||||||
}
|
}
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
RenameFile(incomplete,complete);
|
RenameFile(incomplete,complete);
|
||||||
|
if(report)
|
||||||
ReportEndVideo(video, Resolution.AudioOnly);
|
ReportEndVideo(video, Resolution.AudioOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,9 +556,10 @@ namespace Tesses.YouTubeDownloader
|
||||||
//We know its resolution
|
//We know its resolution
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
private async Task DownloadPreMuxedVideoAsync(SavedVideo video, CancellationToken token)
|
private async Task DownloadPreMuxedVideoAsync(SavedVideo video, CancellationToken token,IProgress<double> progress,bool report=true)
|
||||||
{
|
{
|
||||||
var streams = await BestStreamInfo.GetBestStreams(this, video.Id, token, false);
|
var streams = await BestStreamInfo.GetBestStreams(this, video.Id, token, false);
|
||||||
|
if(!can_download) return;
|
||||||
if(streams != null)
|
if(streams != null)
|
||||||
{
|
{
|
||||||
await MoveLegacyStreams(video,streams);
|
await MoveLegacyStreams(video,streams);
|
||||||
|
@ -549,17 +579,19 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if(report)
|
||||||
ReportStartVideo(video,Resolution.PreMuxed,streams.MuxedStreamInfo.Size.Bytes);
|
ReportStartVideo(video,Resolution.PreMuxed,streams.MuxedStreamInfo.Size.Bytes);
|
||||||
long len=await GetLengthAsync(incomplete);
|
long len=await GetLengthAsync(incomplete);
|
||||||
bool ret;
|
bool ret;
|
||||||
using(var dest = await OpenOrCreateAsync(incomplete))
|
using(var dest = await OpenOrCreateAsync(incomplete))
|
||||||
{
|
{
|
||||||
ret=await CopyStreamAsync(strm,dest,len,streams.MuxedStreamInfo.Size.Bytes,4096,new Progress<double>(ReportProgress),token);
|
ret=await CopyStreamAsync(strm,dest,len,streams.MuxedStreamInfo.Size.Bytes,4096,progress,token);
|
||||||
}
|
}
|
||||||
//We know its resolution
|
//We know its resolution
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
RenameFile(incomplete,complete);
|
RenameFile(incomplete,complete);
|
||||||
|
if(report)
|
||||||
ReportEndVideo(video, Resolution.PreMuxed);
|
ReportEndVideo(video, Resolution.PreMuxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
{
|
{
|
||||||
public abstract partial class TYTDStorage : TYTDBase, IWritable, IDownloader
|
public abstract partial class TYTDStorage : TYTDBase, IWritable, IDownloader
|
||||||
{
|
{
|
||||||
|
private static readonly HttpClient _default = new HttpClient();
|
||||||
public abstract Task<Stream> CreateAsync(string path);
|
public abstract Task<Stream> CreateAsync(string path);
|
||||||
|
|
||||||
public abstract void CreateDirectory(string path);
|
public abstract void CreateDirectory(string path);
|
||||||
|
@ -28,7 +29,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
public TYTDStorage()
|
public TYTDStorage()
|
||||||
{
|
{
|
||||||
HttpClient=new HttpClient();
|
HttpClient=_default;
|
||||||
YoutubeClient=new YoutubeClient(HttpClient);
|
YoutubeClient=new YoutubeClient(HttpClient);
|
||||||
ExtensionContext=null;
|
ExtensionContext=null;
|
||||||
}
|
}
|
||||||
|
@ -40,6 +41,8 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool can_download=true;
|
||||||
|
public bool CanDownload {get {return can_download;} set {can_download=value;}}
|
||||||
|
|
||||||
public abstract void MoveDirectory(string src,string dest);
|
public abstract void MoveDirectory(string src,string dest);
|
||||||
public abstract void DeleteFile(string file);
|
public abstract void DeleteFile(string file);
|
||||||
|
@ -92,6 +95,7 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
public async Task DownloadThumbnails(VideoId id)
|
public async Task DownloadThumbnails(VideoId id)
|
||||||
{
|
{
|
||||||
|
if(!can_download) return;
|
||||||
string Id=id.Value;
|
string Id=id.Value;
|
||||||
string[] res=new string[] {"default.jpg","sddefault.jpg","mqdefault.jpg","hqdefault.jpg","maxresdefault.jpg"};
|
string[] res=new string[] {"default.jpg","sddefault.jpg","mqdefault.jpg","hqdefault.jpg","maxresdefault.jpg"};
|
||||||
CreateDirectoryIfNotExist($"Thumbnails/{Id}");
|
CreateDirectoryIfNotExist($"Thumbnails/{Id}");
|
||||||
|
@ -109,14 +113,18 @@ namespace Tesses.YouTubeDownloader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void StartLoop(CancellationToken token = default(CancellationToken))
|
public void CreateDirectories()
|
||||||
{
|
{
|
||||||
CreateDirectoryIfNotExist("VideoOnly");
|
CreateDirectoryIfNotExist("VideoOnly");
|
||||||
CreateDirectoryIfNotExist("AudioOnly");
|
CreateDirectoryIfNotExist("AudioOnly");
|
||||||
CreateDirectoryIfNotExist("Muxed");
|
CreateDirectoryIfNotExist("Muxed");
|
||||||
CreateDirectoryIfNotExist("PreMuxed");
|
CreateDirectoryIfNotExist("PreMuxed");
|
||||||
CreateDirectoryIfNotExist("Info");
|
CreateDirectoryIfNotExist("Info");
|
||||||
CreateDirectoryIfNotExist("Thumbnails");
|
CreateDirectoryIfNotExist("Thumbnails");
|
||||||
|
}
|
||||||
|
public void StartLoop(CancellationToken token = default(CancellationToken))
|
||||||
|
{
|
||||||
|
CreateDirectories();
|
||||||
Thread thread0=new Thread(()=>{
|
Thread thread0=new Thread(()=>{
|
||||||
DownloadLoop(token).Wait();
|
DownloadLoop(token).Wait();
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
<PackageId>Tesses.YouTubeDownloader</PackageId>
|
<PackageId>Tesses.YouTubeDownloader</PackageId>
|
||||||
<Author>Mike Nolan</Author>
|
<Author>Mike Nolan</Author>
|
||||||
<Company>Tesses</Company>
|
<Company>Tesses</Company>
|
||||||
<Version>1.0.0.0</Version>
|
<Version>1.0.1.0</Version>
|
||||||
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
<AssemblyVersion>1.0.1.0</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.0</FileVersion>
|
<FileVersion>1.0.1.0</FileVersion>
|
||||||
<Description>A YouTube Downloader</Description>
|
<Description>A YouTube Downloader</Description>
|
||||||
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
<PackageLicenseExpression>LGPL-3.0-only</PackageLicenseExpression>
|
||||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||||
|
|
Loading…
Reference in New Issue