an.verify.media#
Media verification helpers — audio + frame quality checks for rendered mp4s.
Phase 8 Tier 2. These complement the existing IR-only LayoutLintVerifier
by inspecting actual mp4 output: silence detection (catches cutoff dialogue),
audio level (catches missing audio), and per-frame perceptual diff via SSIM
(catches “all frames are identical” or “scene drifted between frames”).
Designed to depend only on ffmpeg / ffprobe and numpy (Pillow when
loading frames). No scikit-image, no opencv.
Functions
|
Return dict with mean_db and max_db of the media's audio stream. |
|
Return |
|
Extract frames from |
|
A global-moment structural-similarity score between two single-channel images. |
|
SSIM between two image files (any format Pillow can read). |
|
Return the transcribed speech in |
Classes
|
A contiguous run of near-silence inside an audio stream. |
- class an.verify.media.SilenceSpan(start, end)[source]#
Bases:
objectA contiguous run of near-silence inside an audio stream.
- an.verify.media.audio_volume(media_path)[source]#
Return dict with mean_db and max_db of the media’s audio stream.
- an.verify.media.detect_silence(media_path, *, noise_db=-30.0, min_duration_s=0.3)[source]#
Return
SilenceSpan``s in the audio of ``media_pathvia ffmpeg.Wraps
ffmpeg -af silencedetect=...and parses the stderr “silence_start” / “silence_end” lines. Useful for catching dialogue that got cut off (silence at the start/end of a shot when speech was expected).- Return type:
- an.verify.media.extract_frames(media_path, out_dir, *, fps=4.0, pattern='frame_%04d.png')[source]#
Extract frames from
media_pathatfpstoout_dir.
- an.verify.media.ssim(a, b)[source]#
A global-moment structural-similarity score between two single-channel images.
Not Wang et al.’s SSIM, despite what this docstring said for a long time: that estimator is computed over sliding local windows, and this one uses one global mean, variance and covariance per image. The formula is the same; the reduction is not, and the difference is the whole behaviour. Global moments are blind to a small local change — a total eye-blink scores 0.9989 here — because the flat fill that is most of a cutout frame drags the mean to 1.0.
That blindness is fine for what this function is used for: catching a frozen render, where every pixel is identical or none is. It is not fine as a quality metric, which is why
an.bench.metrics.ssim_map()exists beside it rather than replacing it —MediaQualityVerifier’s frozen-render threshold was tuned against this reduction, and that verifier is in the default orchestrate chain.Inputs are float arrays in [0, 1]. Returns a float in roughly
[-1, 1]; 1 means identical.- Return type:
>>> import numpy as np >>> x = np.zeros((8, 8), dtype=np.float32) >>> ssim(x, x) 1.0