fix: built-in downloader prefers separate streams over 360p muxed (v1.0.0.16)
All checks were successful
Publish Release / release (push) Successful in 24s

When YouTube offered a muxed stream, it was always taken, but muxed streams
are 360p only. Use muxed only when the separate video+audio streams are
missing or not better.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Martin
2026-10-05 21:39:49 -04:00
parent 43e002fcdd
commit d6280f3ce8
3 changed files with 27 additions and 22 deletions

View File

@@ -3,8 +3,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<RootNamespace>Jellyfin.Plugin.CinemaTrailers4Jellyfins</RootNamespace> <RootNamespace>Jellyfin.Plugin.CinemaTrailers4Jellyfins</RootNamespace>
<AssemblyVersion>1.0.0.15</AssemblyVersion> <AssemblyVersion>1.0.0.16</AssemblyVersion>
<FileVersion>1.0.0.15</FileVersion> <FileVersion>1.0.0.16</FileVersion>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<GenerateDocumentationFile>false</GenerateDocumentationFile> <GenerateDocumentationFile>false</GenerateDocumentationFile>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>

View File

@@ -90,31 +90,37 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
.GetManifestAsync($"https://www.youtube.com/watch?v={key}", ct) .GetManifestAsync($"https://www.youtube.com/watch?v={key}", ct)
.ConfigureAwait(false); .ConfigureAwait(false);
// Muxed streams include audio+video in one file. YouTube rarely serves them // Best video-only stream at or below the height limit. MP4 (H.264) is preferred for
// anymore, but use one when it exists since it needs no merge. // client compatibility; any container is the fallback.
var videoStreams = manifest.GetVideoOnlyStreams().ToList();
var audioStreams = manifest.GetAudioOnlyStreams().ToList();
var mp4Video = videoStreams.Where(s => s.Container == Container.Mp4).ToList();
var video = videoStreams.Count > 0
? PickByHeight(mp4Video.Count > 0 ? mp4Video : videoStreams, preferredHeight)
: null;
// Muxed streams (audio+video in one file) need no merge, but YouTube only serves
// them at 360p. Use one only when the separate streams can't do better.
var muxedStreams = manifest.GetMuxedStreams().ToList(); var muxedStreams = manifest.GetMuxedStreams().ToList();
if (muxedStreams.Count > 0) if (muxedStreams.Count > 0)
{ {
var muxed = PickByHeight(muxedStreams, preferredHeight); var muxed = PickByHeight(muxedStreams, preferredHeight);
if (video == null || audioStreams.Count == 0
|| muxed.VideoQuality.MaxHeight >= video.VideoQuality.MaxHeight)
{
_logger.LogInformation( _logger.LogInformation(
"|CinemaTrailers4Jellyfins| Downloading {Key} at {Quality} (muxed) to {Path}", "|CinemaTrailers4Jellyfins| Downloading {Key} at {Quality} (muxed) to {Path}",
key, muxed.VideoQuality.Label, outputPath); key, muxed.VideoQuality.Label, outputPath);
await youtube.Videos.Streams.DownloadAsync(muxed, outputPath, cancellationToken: ct).ConfigureAwait(false); await youtube.Videos.Streams.DownloadAsync(muxed, outputPath, cancellationToken: ct).ConfigureAwait(false);
return true; return true;
} }
}
// Otherwise download the best video-only and audio-only streams and merge them. if (video == null || audioStreams.Count == 0)
// MP4 (H.264/AAC) is preferred for client compatibility; any container is the fallback.
var videoStreams = manifest.GetVideoOnlyStreams().ToList();
var audioStreams = manifest.GetAudioOnlyStreams().ToList();
if (videoStreams.Count == 0 || audioStreams.Count == 0)
{ {
_logger.LogWarning("|CinemaTrailers4Jellyfins| No usable video/audio streams for {Key}.", key); _logger.LogWarning("|CinemaTrailers4Jellyfins| No usable video/audio streams for {Key}.", key);
return false; return false;
} }
var mp4Video = videoStreams.Where(s => s.Container == Container.Mp4).ToList();
var video = PickByHeight(mp4Video.Count > 0 ? mp4Video : videoStreams, preferredHeight);
var mp4Audio = audioStreams.Where(s => s.Container == Container.Mp4).ToList(); var mp4Audio = audioStreams.Where(s => s.Container == Container.Mp4).ToList();
var audio = (mp4Audio.Count > 0 ? mp4Audio : audioStreams).GetWithHighestBitrate(); var audio = (mp4Audio.Count > 0 ? mp4Audio : audioStreams).GetWithHighestBitrate();

View File

@@ -1,5 +1,5 @@
--- ---
version: 1.0.0.15 version: 1.0.0.16
name: CinemaTrailers4Jellyfins name: CinemaTrailers4Jellyfins
guid: b581493e-1046-40ed-b6dc-cb8027624984 guid: b581493e-1046-40ed-b6dc-cb8027624984
description: > description: >
@@ -12,10 +12,9 @@ category: General
owner: 514mart owner: 514mart
targetAbi: 10.11.0.0 targetAbi: 10.11.0.0
changelog: changelog:
- Trailer Languages now also checks the original language of the movie or - The built-in downloader no longer picks YouTube's 360p combined file
show. Before, only the trailer's own language tag was checked, and when separate video and audio streams give a better picture. This
TMDB often tags subtitled foreign trailers as English, so Korean, mostly showed up when yt-dlp failed and the built-in downloader took over
Chinese or Japanese trailers got through
dotnetProjects: dotnetProjects:
- name: Jellyfin.Plugin.CinemaTrailers4Jellyfins - name: Jellyfin.Plugin.CinemaTrailers4Jellyfins