an.adapters#
Renderer adapters — facades over backends (the stage, Manim, Remotion, whiteboard).
The Renderer Protocol and registry live in _base. The core’s own optional
backends are imported here so they self-register on package import. The stage
(an.stage, the cut-out renderer) sits behind the import firewall, so it is
named by MODULE and imported the first time the registry is asked anything
(an#247). Backends with missing
system deps still register but their render() raises a clear error;
can_render(shot) continues to work for routing decisions.
Functions
|
Register a renderer in the default registry. |
|
Look up a renderer by name in the default registry. |
Names of all renderers registered in the default registry. |
|
|
Name the module whose import registers renderer |
Classes
|
Backend renderer interface. |
|
Name-keyed registry of renderers. |
|
Everything a renderer needs that isn't on the Shot itself. |
|
Outcome of a single shot render. |
|
Manim Community Edition, through |
Remotion-based renderer (skeleton). |
|
Whiteboard-style renderer (stub). |
- class an.adapters.ManimRenderer(*, render_check=None, source_resolver=None)[source]#
Bases:
objectManim Community Edition, through
manimkit: an opaque-source shot renderer.Implements
RendererandClockOwningRenderer. Seams:render_check(defaultmanimkit.render_check(), imported on first use) andsource_resolver(default: the project’ssourcesstore,store_source_resolver()). The shot cache keys a shot through the REGISTERED instance’s resolver; a subclass registers its own keyer (register_shot_keyer(name, manim_shot_inputs, renderer_type=Sub)).- measure_duration(shot, ctx, *, render=True, force=False)[source]#
Manim’s length of this shot’s scene, from the
measurementsstore, or rendered now (and stored) when there is none — or whenforce.- Return type:
DurationMeasurement|None
- probe_frames(shot, ctx, times)[source]#
The film’s frames of
shotat each oftimes, from its STORED picture (an#347).Manim owns its clock and renders a whole scene at once, so
an probenever runs it: the picture a render stored is conformed exactly asrender()conforms it, and the frames showing attimesare read out. With no stored picture it refuses, naming the render that stores one.
- class an.adapters.RenderContext(mall, work_dir, fps=30, resolution=(1920, 1080), strict_assets=False, supersample=1, pix_fmt=None, step_hz=None, style_pack=None, default_easing=None, frame_samples=None, capture=None, extra=<factory>)[source]#
Bases:
objectEverything a renderer needs that isn’t on the Shot itself.
mallcarries the project’s stores so the renderer can resolve assets by reference.work_diris a scratch space; the renderer must clean up after itself or treat it as ephemeral.- capture: str | None#
"screenshot"(a Playwright element screenshot per instant) or"canvas"(the runtime reads its own canvas in-page, in batches).Noneis the renderer’s module default, read at call time —"canvas"since an#192, after the equivalence gate held on the whole corpus on both lanes. The two paths write frames whose DECODED pixels are equal, so this is a throughput knob and never a picture knob; aRenderContextfield forsupersample’s reason, and recorded in per-shot provenance.- Type:
How frames leave the browser
- default_easing: Any#
the curve of every authored tween that names none.
None= the built-in"ease_in_out", and a compiled document byte-identical to before the field existed; set, it changes keyframes, so the contract hash moves with it — as it should.- Type:
The scene’s
meta.default_easing(an#166)
- fps: int | float#
Frames per second of the delivered video. May be non-integer — a camera’s 29.97 — and the capture loop and the mux honour it exactly. The COMPILER aligns its frame-sampled curves (gaze saccades, co-articulation, descriptor plays, face curves) to the nearest integer grid instead, because the compiled document’s
meta.fpsis an integer; tweens and every other keyframe are exact at any rate.
- frame_samples: tuple[tuple[float, ...], ...] | None#
Per output frame, the scene instants to render and average into it —
Noneis one instant ati / fps, the path every render took before this field existed, byte for byte. Several instants per frame are an open shutter (motion blur); instants off thei / fpsgrid are capture jitter. Built byan.frame_clock.FrameClock, which is also what the impact harness writes into its ground truth, so the render and the record of when each frame was taken come from one object.A
RenderContextfield forsupersample’s reason: it changes how frames are CAPTURED, not what the scene is, so it must not move the compiled document. Its length must equal the render’s frame count.
- pix_fmt: str | None#
The delivered encode’s pixel format, or
Nonefor the module default. The one first-order quality lever in the encoder: 4:2:0 -> 4:4:4 cuts the edge-band error 11.35 -> 3.79, where mathematically lossless 4:2:0 only reaches 10.15. Losslessness buys 8%; dropping chroma subsampling buys 66%.Nonerather than the literal, so the bench’spix_fmtlever — which rebinds the module default — still reaches an unset render. The default stays 4:2:0 for a PRODUCT reason and not an encoder one: High 4:4:4 Predictive is refused by many hardware decoders, browsers and platforms.
- step_hz: float | None#
Scene-level stepped-timing policy for authored tweens (an#89); a shot’s own
step_hzoverrides it.None= smooth. Reaches the compiled document’smeta.step_hz(only when set) and per-shot provenance.The one deliberate exception to the rule two fields up (“a field on the compiled scene document moves
scene_contract_sha256”): unlikesupersample, this knob CHANGES the compiled document — the resampled keyframes are the contract — so the hash moves whenever it is set no matter where the knob lives, and a document that carries its own timing policy is the honest one. Omit-when-unset keeps the unset case free.
- strict_assets: bool#
Refuse to draw a stand-in for a declared asset that the stores do not supply. Off by default so an asset-less project still renders; on for anything that measures pixels, where a stand-in is a different picture that looks like a successful render (an#33).
- style_pack: StylePack | None#
The
StylePackthis render is drawn under, already resolved from the scene’smeta.style_pack(an#112). Resolved ONCE per render rather than per shot: a pack is art direction for a project, and a scene whose shots disagreed about it would be two scenes.
- supersample: int#
Render at this many times the declared resolution and resolve back with an exact block mean. 1 means off, and off is free — Chromium’s own PNG bytes reach disk untouched.
A
RenderContextfield, and that placement is load-bearing rather than convenient. Simulated against a real committed ledger row: as arender_kwargsentry it becomes aCOMMON_ENV_PATHSkey and **all 96 metrics are refused**; as a field on the compiled scene document it movesscene_contract_sha256and every scene becomes incomparable; here, onlyruntime_sha256moves, which is deliberately not a comparability key — so 30 render-side entries still compare. It needs noSCHEMA_VERSIONmigration, and it MUST reach per-shot provenance, because a row that does not record it cannot be read back later.
- class an.adapters.RenderResult(mp4_path, duration, frame_manifest=<factory>, log='', provenance=<factory>)[source]#
Bases:
objectOutcome of a single shot render.
- class an.adapters.Renderer(*args, **kwargs)[source]#
Bases:
ProtocolBackend renderer interface.
Implementations should be cheap to construct and stateless across renders; state belongs in the
RenderContextor the project mall.- render(shot, ctx)[source]#
Render a single shot to mp4. Idempotent given identical inputs.
- Return type:
- supported_renderers: tuple[str, ...]#
The
Shot.renderervalues this backend claims. It is the ONE place an adapter names them:can_renderderives from it rather than comparing to its own literal, so an adapter cannot advertise one renderer and accept another. an#106 renamed this fromsupported_styles; the rename is a break for an out-of-tree adapter becauseRendereris@runtime_checkableand 3.12 checks data members, soisinstance(old_adapter, Renderer)is now False.
- class an.adapters.RendererRegistry(*, entry_point_group=None)[source]#
Bases:
objectName-keyed registry of renderers.
A module-level instance is exposed via
register_renderer/get_renderer/list_renderers; callers needing isolation (tests, multi-tenant servers) can construct their own.Backends outside the core register LAZILY (an#247): a renderer that lives behind the import firewall – the stage, a genre’s, a third-party engine – is named here by the MODULE that registers it (
register_lazy(), or thean.renderersentry point group), and that module is imported the first time the registry is asked anything. So importing the core loads no backend, and every lookup still finds it.- find_for(shot)[source]#
Return the first registered renderer that
can_render(shot).Nonewhen none can; aRendererLoadErrorwhen none can AND a backend failed to import, since that backend may have been the one.
- an.adapters.get_renderer(name)[source]#
Look up a renderer by name in the default registry.
- Return type:
- an.adapters.register_lazy_renderer(name, module)[source]#
Name the module whose import registers renderer
name(default registry).- Return type:
- an.adapters.register_renderer(renderer)[source]#
Register a renderer in the default registry.
- Return type:
Modules
The cut-out backend's old package: the stage moved to |
|
ManimRenderer — a whole-shot renderer for opaque Manim scene files (an#279). |
|
RemotionRenderer — invoke |
|
WhiteboardRenderer — stub for hand-drawn / chalkboard-style animation. |