Skip to content

Video thumbnail generation logs an error on every successful run (ffmpeg writes to stderr; ffmpeg 8 adds an image2 -update warning) #14944

Description

@phknot

Bug description

Generating a Control Panel video thumbnail writes a Log::error() entry on every successful run, even though the thumbnail is produced correctly. Any app routing error-level logs to an aggregator (Sentry, Bugsnag, Papertrail, …) gets a spurious error for each first-time video thumbnail.

Two things combine:

  1. Console\Processes\Process::logErrorOutput() logs at error level whenever the process wrote anything to stderr, regardless of exit code. ffmpeg (like git, composer, …) writes its banner and per-frame progress to stderr on success, so hasErrorOutput() is always true after a successful Ffmpeg::extractThumbnail(). Note Ffmpeg never calls throwOnFailure() — it treats a non-zero exit as "no thumbnail" via file_exists() — yet a zero-exit run is still logged as an error.

  2. Console\Processes\Ffmpeg::buildCommand() builds … -vframes 1 <output>.jpg with no -loglevel/-hide_banner and no -update. On ffmpeg 8 the image2 muxer additionally emits:

    [image2 @ …] The specified filename '…thumb_….jpg' does not contain an image sequence pattern or a pattern is invalid.
    [image2 @ …] Use a pattern such as %03d for an image sequence or use the -update option (with -frames:v 1 if needed) to write a single image.
    

    This is non-fatal (exit 0, file written), but it adds to the stderr that (1) then logs at error level.

How to reproduce

  1. Install ffmpeg (any version reproduces the stderr-on-success logging; ffmpeg 8 adds the extra image2 warning).
  2. Upload a video asset to a container with video_thumbnails enabled.
  3. View it in the CP so the thumbnail is generated (/cp/thumbnails/…).
  4. Observe an error-level log entry Process Class: Ffmpeg / Command: … / Error: … containing the ffmpeg banner (and, on ffmpeg 8, the image2 warning) — despite the thumbnail rendering fine.

Command-level repro on ffmpeg 8.x:

$ ffmpeg -y -ss 00:00:00 -i input.mov -vframes 1 out.jpg; echo "exit=$?"
  … <banner + progress on stderr> …
  [image2 @ …] The specified filename 'out.jpg' does not contain an image sequence pattern…
  [image2 @ …] Use … the -update option …
  exit=0                      # succeeds; out.jpg is written

$ ffmpeg -hide_banner -loglevel error -y -ss 00:00:00 -i input.mov -frames:v 1 -update 1 out.jpg; echo "exit=$?"
  exit=0                      # succeeds; out.jpg written; stderr EMPTY

Environment

  • Statamic 6.23.0 (unchanged on 6.x HEAD)
  • PHP 8.4
  • ffmpeg 8.0.1 (Alpine) for the image2 warning; the stderr-on-success logging occurs on any ffmpeg version

Suggested fix

Primary (targeted, low risk) — quiet the command and make single-image output explicit in Ffmpeg::buildCommand():

 return collect([
     escapeshellarg($ffmpegBinary),
+    '-hide_banner',
+    '-loglevel error',
     '-y',
     '-ss',
     escapeshellarg($this->startTimestamp),
     '-i',
     escapeshellarg($path),
-    '-vframes 1',
+    '-frames:v 1',
+    '-update 1',
     escapeshellarg($output),
 ])->join(' ');

With -loglevel error, a successful run produces no stderr → no error log, while a genuine failure still prints at error level and is still logged. -update 1 is ffmpeg's documented opt-in for writing a single image to a fixed filename — it silences the image2 warning and keeps the command correct if a future ffmpeg promotes that warning to a hard error.

Secondary (deeper root cause, optional)Process::logErrorOutput() arguably shouldn't log at error when the process exited 0; gating on $process->getExitCode() > 0 (or logging stderr-on-success at debug/warning) would prevent this class of false error for every process wrapper. Flagging separately since it also affects Composer/Please/etc. and may warrant its own discussion.

Happy to open a PR for the Ffmpeg::buildCommand change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions