Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/Ytdlp.NET/Parsing/RegexPatterns.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace ManuHub.Ytdlp.NET;
using System.Text.Json.Serialization;

namespace ManuHub.Ytdlp.NET;

internal static class RegexPatterns
{
Expand Down Expand Up @@ -34,4 +36,4 @@ internal static class RegexPatterns
// Generic fallback for any unknown post-processor
public const string PostProcessorGeneric =
@"\[(?<processor>Merger|ModifyChapters|SplitChapters|ExtractAudio|VideoRemuxer|VideoConvertor|Metadata|EmbedSubtitle|EmbedThumbnail|SubtitlesConvertor|ThumbnailsConvertor|FixupStretched|FixupM4a|FixupM3u8|FixupTimestamp|FixupDuration|MoveFiles|ffmpeg|ConvertSubs|SponsorBlock)\]\s*(?<action>.+)";
}
}
17 changes: 17 additions & 0 deletions src/Ytdlp.NET/Parsing/YtdlpJsonContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.Text.Json.Serialization;

namespace ManuHub.Ytdlp.NET;

/// <summary>
/// Defines the source-generated JSON serialization context for <see cref="Ytdlp"/>.
/// </summary>
/// <remarks>
/// This class enables high-performance, reflection-free JSON serialization/deserialization.
/// It is essential for:
/// <list type="bullet">
/// <item>Reducing CPU overhead and memory allocations during metadata probing.</item>
/// <item>Supporting Native AOT compilation by providing compile-time type metadata.</item>
/// </list>
/// </remarks>
[JsonSerializable(typeof(Metadata))]
public partial class YtdlpJsonContext : JsonSerializerContext { }
44 changes: 23 additions & 21 deletions src/Ytdlp.NET/Ytdlp.Probe.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public sealed partial class Ytdlp
{
PropertyNameCaseInsensitive = true,
NumberHandling = JsonNumberHandling.AllowReadingFromString,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
TypeInfoResolver = YtdlpJsonContext.Default
};

#endregion
Expand Down Expand Up @@ -147,7 +148,7 @@ public async Task<List<string>> GetAdobePassListAsync(CancellationToken ct = def

try
{
return JsonSerializer.Deserialize<Metadata>(json, JsonOptions);
return JsonSerializer.Deserialize(json, YtdlpJsonContext.Default.Metadata);
}
catch (Exception ex)
{
Expand Down Expand Up @@ -187,7 +188,7 @@ public async Task<List<string>> GetAdobePassListAsync(CancellationToken ct = def

try
{
return JsonSerializer.Deserialize<Metadata>(json, JsonOptions);
return JsonSerializer.Deserialize(json, YtdlpJsonContext.Default.Metadata);
}
catch (Exception ex)
{
Expand All @@ -209,24 +210,6 @@ public async Task<List<string>> GetAdobePassListAsync(CancellationToken ct = def
public async Task<string?> GetDeepMetadataRawAsync(string url, CancellationToken ct = default, bool tuneProcess = true)
=> await GetMetadataInternalAsync(url, flat: false, ct, tuneProcess);

private async Task<string?> GetMetadataInternalAsync(string url, bool flat, CancellationToken ct, bool tuneProcess)
{
if (string.IsNullOrWhiteSpace(url))
throw new ArgumentException("URL cannot be empty.", nameof(url));

var arguments =
"--dump-single-json " +
"--simulate " +
"--skip-download " +
(flat ? "--flat-playlist " : "") +
"--lazy-playlist " +
"--quiet " +
"--no-warnings " +
$"{Quote(url)}";

return await RunProbeAsync(arguments, ct, tuneProcess);
}

/// <summary>
/// Retrieves a list of all available stream formats for a given URL.
/// </summary>
Expand Down Expand Up @@ -477,6 +460,25 @@ public async Task<List<SubtitleTrack>> GetSubtitlesAsync(string url, Cancellatio
}
}


private async Task<string?> GetMetadataInternalAsync(string url, bool flat, CancellationToken ct, bool tuneProcess)
{
if (string.IsNullOrWhiteSpace(url))
throw new ArgumentException("URL cannot be empty.", nameof(url));

var arguments =
"--dump-single-json " +
"--simulate " +
"--skip-download " +
(flat ? "--flat-playlist " : "") +
"--lazy-playlist " +
"--quiet " +
"--no-warnings " +
$"{Quote(url)}";

return await RunProbeAsync(arguments, ct, tuneProcess);
}

private List<Format> ParseFormats(string result)
{
var formats = new List<Format>();
Expand Down
Loading