Skip to content

Commit

Permalink
Improve clip downloader quality detection (#1144)
Browse files Browse the repository at this point in the history
* Support "best"/"source" and "worst" quality keywords in clip downloader

* Make clip quality selection more robust

* Cleanup imports
  • Loading branch information
ScrubN authored Jul 11, 2024
1 parent 18cb855 commit f02d323
Showing 1 changed file with 59 additions and 7 deletions.
66 changes: 59 additions & 7 deletions TwitchDownloaderCore/ClipDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,24 +126,76 @@ private async Task<string> GetDownloadUrl()
throw new NullReferenceException("Clip has no video qualities, deleted possibly?");
}

string downloadUrl = "";
var downloadUrl = GetDownloadUrlForQuality(clip, downloadOptions.Quality);

foreach (var quality in clip.videoQualities)
return downloadUrl + "?sig=" + clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(clip.playbackAccessToken.value);
}

private static string GetDownloadUrlForQuality(ClipToken clip, string qualityString)
{
Debug.Assert(clip.videoQualities.OrderBy(x => x, new ClipQualityComparer()).SequenceEqual(clip.videoQualities));

if (TryGetKeywordQuality(clip, qualityString, out var downloadUrl))
{
return downloadUrl;
}

if (qualityString.Contains('p'))
{
foreach (var quality in clip.videoQualities)
{
var framerate = (int)Math.Round(quality.frameRate);
var framerateString = qualityString.EndsWith('p') && framerate == 30
? ""
: framerate.ToString("F0");

if ($"{quality.quality}p{framerateString}" == qualityString)
{
return quality.sourceURL;
}
}
}
else
{
if (quality.quality + "p" + (Math.Round(quality.frameRate) == 30 ? "" : Math.Round(quality.frameRate).ToString("F0")) == downloadOptions.Quality)
var quality = clip.videoQualities.FirstOrDefault(quality => quality.quality == qualityString);
if (quality is not null)
{
downloadUrl = quality.sourceURL;
return quality.sourceURL;
}
}

if (downloadUrl == "")
return BestQuality(clip).sourceURL;
}

private static bool TryGetKeywordQuality(ClipToken clip, string qualityString, out string downloadUrl)
{
if (string.IsNullOrWhiteSpace(qualityString))
{
downloadUrl = clip.videoQualities.First().sourceURL;
downloadUrl = BestQuality(clip).sourceURL;
return true;
}

return downloadUrl + "?sig=" + clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(clip.playbackAccessToken.value);
if (qualityString.Contains("best", StringComparison.OrdinalIgnoreCase)
|| qualityString.Contains("source", StringComparison.OrdinalIgnoreCase))
{
downloadUrl = BestQuality(clip).sourceURL;
return true;
}

if (qualityString.Contains("worst", StringComparison.OrdinalIgnoreCase))
{
downloadUrl = WorstQuality(clip).sourceURL;
return true;
}

downloadUrl = null;
return false;
}

private static VideoQuality BestQuality(ClipToken clip) => clip.videoQualities.First();

private static VideoQuality WorstQuality(ClipToken clip) => clip.videoQualities.Last();

private static async Task DownloadFileTaskAsync(string url, FileStream fs, int throttleKib, IProgress<StreamCopyProgress> progress, CancellationToken cancellationToken)
{
var request = new HttpRequestMessage(HttpMethod.Get, url);
Expand Down

0 comments on commit f02d323

Please sign in to comment.