From eef41d41721cab17c1fc1b359ea9c4b775f93d53 Mon Sep 17 00:00:00 2001 From: Cameron Cordes Date: Thu, 7 May 2026 17:20:05 -0400 Subject: [PATCH] thumbnails: align video ffmpeg args with the image path so non-yuvj420p sources work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bare 'ffmpeg -ss 3 -i in -vframes 1 -f image2 out' command failed on sources whose decoded pix_fmt isn't yuvj420p (e.g. older Samsung phone videos in yuv420p). With no -vf filter chain, the decoded frame goes straight to the mjpeg encoder, which rejects it with 'Non full-range YUV is non-standard' and exits non-zero. generate_image_thumbnail_ffmpeg already handles the same class of source for HEIC/RAW by adding -vf scale=200:-1 -c:v mjpeg — the filter chain lets ffmpeg auto-insert the pix_fmt converter the encoder needs. Adopt the same args here. Side benefit: video thumbnails are now 200px wide on disk, matching image thumbnails (previously full-resolution). Pre-existing .unsupported sentinels for videos that hit this failure will need to be deleted manually to retry — they're under $THUMBNAILS//.../*.unsupported. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/video/actors.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/video/actors.rs b/src/video/actors.rs index 7722a5d..cfe2aa7 100644 --- a/src/video/actors.rs +++ b/src/video/actors.rs @@ -108,15 +108,27 @@ pub async fn create_playlist(video_path: &str, playlist_file: &str) -> Result std::io::Result<()> { + // -vf scale + -c:v mjpeg mirrors `generate_image_thumbnail_ffmpeg`. The + // filter chain matters as much as the scale does: without it, ffmpeg + // hands the decoded frame straight to the mjpeg encoder, which rejects + // any non-yuvj420p source ("Non full-range YUV is non-standard"). The + // filter chain lets ffmpeg auto-insert the pix_fmt converter the + // encoder needs, which is how the image-thumbnail path already handles + // the same class of source. let output = Command::new("ffmpeg") + .arg("-y") .arg("-ss") .arg("3") .arg("-i") .arg(path) .arg("-vframes") .arg("1") + .arg("-vf") + .arg("scale=200:-1") .arg("-f") .arg("image2") + .arg("-c:v") + .arg("mjpeg") .arg(destination) .output()?;