feat: yt-dlp prefers H.264, falls back to built-in, no pipe hang (v1.0.0.13)
Some checks failed
Publish Release / release (push) Failing after 8s

- Format string prefers avc1 video + m4a audio, then any codec. The RTX 2070
  host can hardware-transcode H.264 but not AV1.
- Pass Jellyfin's ffmpeg via --ffmpeg-location instead of relying on PATH.
- If yt-dlp fails, retry with the built-in YoutubeExplode downloader.
- Read stdout/stderr while yt-dlp runs (and add --no-progress); before,
  stdout was never read, so a full pipe buffer could block yt-dlp forever.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Martin
2026-10-05 18:01:33 -04:00
parent 6002ce7b46
commit 4145e1f1dd
3 changed files with 24 additions and 15 deletions

View File

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

View File

@@ -63,8 +63,10 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
if (!string.IsNullOrWhiteSpace(ytDlpPath) && File.Exists(ytDlpPath))
{
return await DownloadWithYtDlpAsync(youtubeKey, outputPath, preferredHeight, ytDlpPath, ct)
.ConfigureAwait(false);
if (await DownloadWithYtDlpAsync(youtubeKey, outputPath, preferredHeight, ytDlpPath, ct).ConfigureAwait(false))
return true;
_logger.LogWarning("|CinemaTrailers4Jellyfins| yt-dlp failed for {Key}; falling back to the built-in downloader.", youtubeKey);
}
return await DownloadWithYoutubeExplodeAsync(youtubeKey, outputPath, preferredHeight, ct)
@@ -224,13 +226,16 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
{
try
{
// Format selects the best video at or below preferredHeight merged with the best audio.
// --merge-output-format mp4 ensures the output is always an mp4.
// Format selects the best video at or below preferredHeight merged with the best audio,
// preferring H.264 + AAC (plays or hardware-transcodes on every client; VP9/AV1 often
// need a CPU transcode). --merge-output-format mp4 ensures the output is always an mp4.
var args = string.Join(" ",
$"-f \"bestvideo[height<={preferredHeight}]+bestaudio/best[height<={preferredHeight}]\"",
$"-f \"bestvideo[height<={preferredHeight}][vcodec^=avc1]+bestaudio[ext=m4a]/bestvideo[height<={preferredHeight}]+bestaudio/best[height<={preferredHeight}]\"",
"--merge-output-format mp4",
"--no-playlist",
"--no-warnings",
"--no-progress",
$"--ffmpeg-location \"{FfmpegLocator.Path}\"",
$"-o \"{outputPath}\"",
$"\"https://www.youtube.com/watch?v={key}\"");
@@ -252,11 +257,15 @@ namespace Jellyfin.Plugin.CinemaTrailers4Jellyfins.Services
};
process.Start();
// Drain both pipes while yt-dlp runs so a full buffer can never block it.
var stdoutTask = process.StandardOutput.ReadToEndAsync(ct);
var stderrTask = process.StandardError.ReadToEndAsync(ct);
await process.WaitForExitAsync(ct).ConfigureAwait(false);
await stdoutTask.ConfigureAwait(false);
var stderr = await stderrTask.ConfigureAwait(false);
if (process.ExitCode != 0)
{
var stderr = await process.StandardError.ReadToEndAsync(ct).ConfigureAwait(false);
_logger.LogError("|CinemaTrailers4Jellyfins| yt-dlp exited with code {Code} for {Key}: {Error}",
process.ExitCode, key, stderr);
return false;

View File

@@ -1,5 +1,5 @@
---
version: 1.0.0.12
version: 1.0.0.13
name: CinemaTrailers4Jellyfins
guid: b581493e-1046-40ed-b6dc-cb8027624984
description: >
@@ -12,12 +12,12 @@ category: General
owner: 514mart
targetAbi: 10.11.0.0
changelog:
- Anime trailers now only play before anime. Western animation (Pixar,
Disney, ...) is no longer blocked and follows the normal genre filter
again. A trailer counts as anime when TMDB tags it "anime" or "based on
manga", or it is animation in Japanese, Chinese or Korean; it is marked
with a ct4j-anime tag in its NFO at download time. Your anime is
recognised by the "Anime" genre or the same TMDB keywords
- yt-dlp now prefers H.264 + AAC (plays or hardware-transcodes on every
client; VP9/AV1 often needed a CPU transcode) and uses Jellyfin's own
ffmpeg for the merge
- If yt-dlp fails, the built-in downloader is tried instead
- Fix a possible hang: yt-dlp's output is now read while it runs, so a
full output buffer can no longer block it
dotnetProjects:
- name: Jellyfin.Plugin.CinemaTrailers4Jellyfins