an.engines.frame_stage#
frame_stage_renderer(engine): any seekable engine becomes a Renderer.
The core owns everything around the engine, once, for every engine:
the knobs, validated before anything launches – ffmpeg present, the supersample factor (
an.media.supersample.check_factor()), the pixel format (an.media.mp4.check_pix_fmt()), the engine’s own knobs (Engine.check), and the frame clock (an.media.shutter.check_frame_samples());the clock:
frame_count = max(1, round(duration * fps)), frameiati / fpsunlessRenderContext.frame_samples(built byan.frame_clock.FrameClock) says otherwise;the shot’s workspace –
<work_dir>/shot_<id>/with a clearedframes/;the capture loop (
an.engines.capture): supersampling and the shutter resolved in the frame stage;the sink: the frames muxed to the shot mp4 with the pinned argv, the shot’s dialogue laid under it (
an.media.mp4.mux_shot());provenance: the core’s facts plus the session’s own (
provenance()).
The engine only loads the shot and draws instants (an.engines.protocol).
A STATE-driven session is adapted here: the core evaluates its timeline with
an.timing.timeline.evaluate_timeline() (in the session’s space when it
has one) and hands each state to render.
Errors the core raises (FrameStageError,
MediaError, UnseekableEngineError)
are re-raised as the renderer’s own error type at its boundary, message
intact, so a cut-out render still fails with CutoutRenderError.
>>> from contextlib import contextmanager
>>> class Card:
... name = "card"
... @contextmanager
... def open(self, job):
... yield self
... def frame(self, t): return b""
... def state(self, t): return {}
>>> r = frame_stage_renderer(Card(), renderers=("card", "title"))
>>> r.name, r.supported_renderers
('card', ('card', 'title'))
Module Attributes
A shot's scratch directory under |
Functions
|
Turn |
|
Refuse an object that is not an engine, saying what is missing. |
|
|
Classes
|
A |
|
A state-driven session seen as a time-driven one: the core evaluates |
- class an.engines.frame_stage.FrameStageRenderer(engine, name='', supported_renderers=(), error=<class 'an.engines.capture.FrameStageError'>, capture_options=<factory>)[source]#
Bases:
objectA
Rendererthat drives anEngineframe by frame.Build it with
frame_stage_renderer(). Stateless across renders, so one instance serves every shot of a parallel render: eachrenderopens its own session.- capture_options: dict[str, Any]#
Capture-loop tunables passed through to
an.engines.capture.capture_frames()(batch,workers,max_inflight,batch_pixels); unset = its defaults.
- error#
The exception type raised at the boundary for every core error.
alias of
FrameStageError
- probe_frames(shot, ctx, times)[source]#
The film’s frames of
shotshowing at each oftimes(seconds), as PNG bytes.an probe(an#347): the sessionrender()opens (the same engine, state-driven adapter, supersample and frame clock) and the samecapture_frames(), asked only for the frames needed — so a probe frame IS the film’s frame, without the rest of the shot or the mux. Each instant is snapped to the frame showing then (floor(t * fps), clamped to the shot).
- an.engines.frame_stage.SHOT_WORKSPACE_PATTERN: str = 'shot_{shot_id}'#
A shot’s scratch directory under
RenderContext.work_dir. Kept from the stage renderer it came from, so the paths a render leaves behind (and that the bench and film assembly read) do not move.
- class an.engines.frame_stage.StateDrivenAdapter(session)[source]#
Bases:
objectA state-driven session seen as a time-driven one: the core evaluates
at(t).frame(t)isrender(evaluate_timeline(timeline, t, space=space))andstate(t)is the evaluated state, so the capture loop and the conformance tests treat both drive modes alike. The session’s other members (resolve,provenance, …) are reached through attribute access.Batched (an#286):
frames(requests)evaluates every instant here and hands the session the STATES, through its optionalrender_states(states)(one round trip per batch, the member a JS-bridged view engine implements), elserenderper state. A session’s ownframesis never forwarded: it would take times and bypassstate.Adapted by drive mode (an#286):
project(point, t)andbounds(t)reach the session asproject(point, state)andbounds(state)(the state-driven signature, previz’sproject(point, {state, ...})), and exist only when the session has them, sodescribe()still reads capabilities from real members.
- an.engines.frame_stage.frame_stage_renderer(engine, *, name=None, renderers=None, error=<class 'an.engines.capture.FrameStageError'>, capture_options=None)[source]#
Turn
engineinto aRenderer: the core’s clock, capture loop, resolves and sinks.namedefaults to the engine’s;renderers– theShot.renderervalues claimed – default to(name,).erroris the typed exception the renderer raises at its boundary for every core error.- Return type: