muvid.visualize.ffmpeg¶
Low-level ffmpeg/ffprobe primitives shared across muvid.visualize.
Thin, dependency-free wrappers around the ffmpeg/ffprobe binaries that
muvid.visualize assumes on the PATH: running a command with a readable
error, probing duration and streams, checking that an optional filter was
compiled in, decoding raw PCM for an analysis pass, and measuring loudness
(EBU R128) for two-pass normalization.
Nothing here knows about music or a destination platform — it is the shared
substrate under muvid.visualize.canvas, muvid.visualize.visuals,
muvid.visualize.reactive, and muvid.visualize.video.
Module Attributes
Env var bounding a single ffmpeg invocation's wall-clock (seconds). |
|
Loudness targets, in the units EBU R128 / ffmpeg |
|
little-endian 32-bit float, which is exactly |
Functions
|
Decode |
|
Whether this ffmpeg build has the |
|
Analyse |
|
Duration of |
|
Return |
|
Raise a helpful |
|
Raise unless this ffmpeg build has the |
|
Run |
Classes
|
An EBU R128 loudness target, plus the measurement of a specific track. |
Exceptions
An ffmpeg/ffprobe invocation failed, or a needed tool/filter is absent. |
- muvid.visualize.ffmpeg.DEFAULT_LOUDNESS_I = -14.0¶
Loudness targets, in the units EBU R128 / ffmpeg
loudnormuses. The defaults match what YouTube normalizes playback to, so a track mastered here is neither turned down nor left quiet relative to the rest of a playlist.
- muvid.visualize.ffmpeg.FFMPEG_TIMEOUT_ENV_VAR = 'MUVID_FFMPEG_TIMEOUT_S'¶
Env var bounding a single ffmpeg invocation’s wall-clock (seconds). Unset = no timeout (the historical behaviour). A long-running host (the reelee MCP connector renders synchronously over HTTP) sets this so an oversized or adversarial input can’t pin a worker indefinitely — a belt-and-braces bound on top of the caller’s own input-duration cap.
- exception muvid.visualize.ffmpeg.FfmpegError[source]¶
Bases:
RuntimeErrorAn ffmpeg/ffprobe invocation failed, or a needed tool/filter is absent.
- class muvid.visualize.ffmpeg.Loudness(integrated=-14.0, true_peak=-1.0, lra=11.0, measured=None)[source]¶
Bases:
objectAn EBU R128 loudness target, plus the measurement of a specific track.
measuredis theloudnormanalysis pass output (Noneuntilmeasure_loudness()has run). Carrying both letsfilter_spec()emit the accurate two-pass filter when a measurement exists and fall back to the (less accurate) single-pass form when it does not.
- muvid.visualize.ffmpeg.PCM_SAMPLE_FORMAT = 'f32le'¶
little-endian 32-bit float, which is exactly
numpy.float32’s memory layout, so an analysis pass can read the bytes straight into an array with no conversion step.- Type:
Sample format the raw-PCM decode emits
- muvid.visualize.ffmpeg.decode_pcm(audio, *, sample_rate, channels=1)[source]¶
Decode
audioto rawPCM_SAMPLE_FORMATsamples on stdout.Analysis passes (loudness envelopes, onset detection) want samples, not a container. This is the single place muvid turns a media file into raw PCM, so
$MUVID_FFMPEG_TIMEOUT_Sbounds that decode like every other one.- Parameters:
- Return type:
- Returns:
The raw PCM bytes — empty when ffmpeg could not decode
audio. Returning empty rather than raising lets a caller treat “no usable audio” as “no effect” (seemuvid.visualize.reactive.flash_filter()).
- muvid.visualize.ffmpeg.has_filter(name)[source]¶
Whether this ffmpeg build has the
namefilter compiled in.- Return type:
- muvid.visualize.ffmpeg.measure_loudness(audio, target=None)[source]¶
Analyse
audio(loudnorm pass 1) and returntargetwith the result.Two-pass
loudnormis the only accurate way to hit a loudness target: pass 1 measures the program loudness, pass 2 applies a linear gain from that measurement. Single-pass loudnorm is a dynamic normalizer and will both miss the target and squash the dynamics of music.
- muvid.visualize.ffmpeg.media_duration(media)[source]¶
Duration of
mediain seconds.Falls back to the longest stream duration when the container has none.
- Raises:
FfmpegError – The duration could not be determined.
- Return type:
- muvid.visualize.ffmpeg.probe(media)[source]¶
Return
ffprobe’sformat+streamsJSON formedia.- Return type:
- muvid.visualize.ffmpeg.require_ffmpeg(*tools)[source]¶
Raise a helpful
FfmpegErrorif any oftoolsis not on PATH.- Parameters:
*tools (
str) – Binaries to require (defaults toffmpegandffprobe).- Raises:
FfmpegError – With per-platform install instructions.
- Return type:
- muvid.visualize.ffmpeg.require_filter(name, *, needed_for)[source]¶
Raise unless this ffmpeg build has the
namefilter.Filters like
drawtext(libfreetype) andshowcqt(libfftw/avfilter extras) are build-time options, so a working ffmpeg is not enough — the specific filter has to be there.- Raises:
FfmpegError – Naming the filter, the feature that needs it, and the fix.
- Return type:
- muvid.visualize.ffmpeg.run_ffmpeg(args, *, overwrite=True)[source]¶
Run
ffmpegwithargs, raising a readable error on failure.- Parameters:
- Return type:
- Returns:
The completed process.
- Raises:
FfmpegError – ffmpeg exited non-zero; the message carries the tail of stderr and the full command, which is what you actually need to debug a filtergraph.