Skip to content

Commit

Permalink
Fix VOD download trimming and quality selection (#936)
Browse files Browse the repository at this point in the history
* fix streamOffsetSeconds calculation

* handle source quality streams

* check GroupId, add tests

* use `contains` instead of `equals`

Co-authored-by: Scrub <[email protected]>

---------

Co-authored-by: Scrub <[email protected]>
  • Loading branch information
vaindil and ScrubN authored Jan 6, 2024
1 parent f166581 commit d10fdeb
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 4 deletions.
24 changes: 24 additions & 0 deletions TwitchDownloaderCore.Tests/M3U8ExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,30 @@ public static void CorrectlyFindsStreamOfQualityFromOldM3U8Response(string quali
Assert.Equal(expectedPath, selectedQuality.Path);
}

[Theory]
[InlineData("1080", "1080p60")]
[InlineData("1080p", "1080p60")]
[InlineData("1080p60", "1080p60")]
[InlineData("720p60", "720p60")]
[InlineData("foo", "1080p60")]
public static void CorrectlyFindsStreamOfQualityFromM3U8ResponseWithoutFramerate(string qualityString, string expectedPath)
{
var m3u8 = new M3U8(new M3U8.Metadata(), new[]
{
new M3U8.Stream(
new M3U8.Stream.ExtMediaInfo(M3U8.Stream.ExtMediaInfo.MediaType.Video, "chunked", "Source", true, true),
new M3U8.Stream.ExtStreamInfo(0, 1, "avc1.4D401F,mp4a.40.2", (1920, 1080), "chunked", 0),
"1080p60"),
new M3U8.Stream(
new M3U8.Stream.ExtMediaInfo(M3U8.Stream.ExtMediaInfo.MediaType.Video, "720p60", "720p60", true, true),
new M3U8.Stream.ExtStreamInfo(0, 1, "avc1.4D401F,mp4a.40.2", (1280, 720), "720p60", 58.644M),
"720p60"),
});

var selectedQuality = m3u8.GetStreamOfQuality(qualityString);
Assert.Equal(expectedPath, selectedQuality.Path);
}

[Theory]
[InlineData("480p60", "1080p60")]
[InlineData("852x480p60", "1080p60")]
Expand Down
17 changes: 14 additions & 3 deletions TwitchDownloaderCore/Extensions/M3U8Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static M3U8.Stream GetStreamOfQuality(this M3U8 m3u8, string qualityStrin

if (qualityString is null)
{
return streams.MaxBy(x => x.StreamInfo.Resolution.Width * x.StreamInfo.Resolution.Height * x.StreamInfo.Framerate);
return m3u8.BestQualityStream();
}

if (qualityString.Contains("audio", StringComparison.OrdinalIgnoreCase) &&
Expand All @@ -57,7 +57,7 @@ public static M3U8.Stream GetStreamOfQuality(this M3U8 m3u8, string qualityStrin
var qualityStringMatch = UserQualityStringRegex.Match(qualityString);
if (!qualityStringMatch.Success)
{
return streams.MaxBy(x => x.StreamInfo.Resolution.Width * x.StreamInfo.Resolution.Height * x.StreamInfo.Framerate);
return m3u8.BestQualityStream();
}

var desiredWidth = qualityStringMatch.Groups["Width"];
Expand All @@ -74,7 +74,7 @@ public static M3U8.Stream GetStreamOfQuality(this M3U8 m3u8, string qualityStrin
{
1 => filteredStreams[0],
2 when !desiredFramerate.Success => filteredStreams.First(x => Math.Abs(x.StreamInfo.Framerate - 30) <= 2),
_ => streams.MaxBy(x => x.StreamInfo.Resolution.Width * x.StreamInfo.Resolution.Height * x.StreamInfo.Framerate)
_ => m3u8.BestQualityStream()
};
}

Expand Down Expand Up @@ -118,5 +118,16 @@ public static string GetResolutionFramerateString(this M3U8.Stream stream)

return $"{frameHeight}p{frameRate}";
}

/// <summary>
/// Returns the best quality stream from the provided M3U8.
/// </summary>
public static M3U8.Stream BestQualityStream(this M3U8 m3u8)
{
var source = Array.Find(
m3u8.Streams, x => x.MediaInfo.Name.Contains("source", StringComparison.OrdinalIgnoreCase) ||
x.MediaInfo.GroupId.Equals("chunked", StringComparison.OrdinalIgnoreCase));
return source ?? m3u8.Streams.MaxBy(x => x.StreamInfo.Resolution.Width * x.StreamInfo.Resolution.Height * x.StreamInfo.Framerate);
}
}
}
2 changes: 1 addition & 1 deletion TwitchDownloaderCore/VideoDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public async Task DownloadAsync(CancellationToken cancellationToken)
.Take(videoListCrop.Start.Value)
.Sum(x => x.PartInfo.Duration);

startOffsetSeconds -= downloadOptions.CropBeginningTime;
startOffsetSeconds = downloadOptions.CropBeginningTime - startOffsetSeconds;
double seekDuration = Math.Round(downloadOptions.CropEndingTime - downloadOptions.CropBeginningTime);

string metadataPath = Path.Combine(downloadFolder, "metadata.txt");
Expand Down

0 comments on commit d10fdeb

Please sign in to comment.