an.engines#
Engines: seekable things the core drives frame by frame, and the renderer that drives them.
Core (ADR 0001 decision 12; core study §2.7). No engine is core: the core holds
the PROTOCOL and the frame stage, and an engine – the 2D stage runtime, a
previz view behind a page, a burns crop over a still – lives in its own
package and registers the renderer frame_stage_renderer() builds from it.
an.engines.protocol–Engine(a factory that opens a session per shot), the time-driven and state-driven session protocols, the declared live tier, anddescribe(), which reads a session’s tier, drive mode and features off the members it implements (never off a flag).an.engines.capture– the capture loop, sequential or batched, with the frame stage’s resolves (supersample, shutter).an.engines.frame_stage–frame_stage_renderer(): an engine in, aRendererout, using the core’s frame clock, capture loop, resolves and MP4 sink (an.media).
>>> from contextlib import contextmanager
>>> class Blank:
... name = "blank"
... @contextmanager
... def open(self, job):
... yield self
... def frame(self, t): return b""
... def state(self, t): return {}
>>> describe(Blank()).drive, frame_stage_renderer(Blank()).name
('time', 'blank')
Functions
|
Write one PNG per request into |
|
The tier, drive mode and features a session (or a session class) offers. |
|
|
|
Turn |
|
Refuse an object that is not an engine, saying what is missing. |
|
The session's drive mode, or a refusal that says what to add. |
|
Requests as plain dicts, the shape a page or a subprocess takes. |
|
|
Classes
|
A stateless factory of loaded, seekable sessions -- one per shot render. |
|
What a session can do, read off its members. |
|
What the frame stage asks of an engine for one shot. |
|
One output frame's instants, in the order they must be captured. |
|
A |
|
The live tier: apply, settle, capture in real time. |
|
A session the core hands states to. |
|
A state-driven session seen as a time-driven one: the core evaluates |
|
A session that evaluates the compiled channels itself. |
Exceptions
The frame stage could not produce a frame directory it can vouch for. |
|
A session that the frame stage cannot drive; the message says what to add. |
- class an.engines.Engine(*args, **kwargs)[source]#
Bases:
ProtocolA stateless factory of loaded, seekable sessions – one per shot render.
- class an.engines.EngineProfile(tier, drive, features)[source]#
Bases:
objectWhat a session can do, read off its members.
- class an.engines.FrameJob(shot, ctx, workspace, frames_dir, total_frames, supersample, frame_samples=None)[source]#
Bases:
objectWhat the frame stage asks of an engine for one shot.
Built by the core, before
Engine.open(): every knob here is already validated, so an engine never re-derives the frame count or the factor.- frame_samples: tuple[tuple[float, ...], ...] | None#
Per frame, the instants to capture and average, or
Nonefor one instant ati / fps.
- requests()[source]#
Every frame’s request, frame
iati / fpsunless a clock says otherwise.- Return type:
>>> from types import SimpleNamespace >>> job = FrameJob(None, SimpleNamespace(fps=4, resolution=(2, 2)), Path("."), ... Path("."), total_frames=3, supersample=1) >>> [r.times for r in job.requests()] [(0.0,), (0.25,), (0.5,)]
- property size: tuple[int, int]#
what every resolved frame must be.
- Type:
The DECLARED (width, height)
- class an.engines.FrameRequest(frame, times)[source]#
Bases:
objectOne output frame’s instants, in the order they must be captured.
One instant unless a frame clock opened the shutter (
RenderContext.frame_samples).
- exception an.engines.FrameStageError[source]#
Bases:
RuntimeErrorThe frame stage could not produce a frame directory it can vouch for.
A renderer built by
frame_stage_renderer(..., error=...)re-raises it as its own typed error at its boundary.
- class an.engines.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#
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).
- class an.engines.LiveEngine(*args, **kwargs)[source]#
Bases:
ProtocolThe live tier: apply, settle, capture in real time. Declared, not built.
Its recorder resamples to a constant rate (
walkthru’s worked example);frame_stage_rendererdoes not drive it, and never falls back to it.
- class an.engines.StateDriven(*args, **kwargs)[source]#
Bases:
ProtocolA session the core hands states to.
- class an.engines.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.
- class an.engines.TimeDriven(*args, **kwargs)[source]#
Bases:
ProtocolA session that evaluates the compiled channels itself.
- exception an.engines.UnseekableEngineError[source]#
Bases:
TypeErrorA session that the frame stage cannot drive; the message says what to add.
- an.engines.capture_frames(session, requests, frames_dir, *, factor=1, size=None, batch=None, workers=None, max_inflight=None, batch_pixels=None)[source]#
Write one PNG per request into
frames_dir, resolved to the declared size.sessionis time-driven (frame(t)), optionally batched (frames(requests)), optionally with its ownresolve. A state-driven session is adapted by the frame stage before it reaches here.size, when known, sets the pixel budget and is passed to the resolve.Nonefor any tunable reads the module default at call time.- Return type:
- an.engines.describe(session)[source]#
The tier, drive mode and features a session (or a session class) offers.
- Return type:
- an.engines.drive_mode(session)[source]#
"time","state", orNonefor a session the frame stage cannot drive.A session with both
frameandrenderis time-driven: it evaluates its own document, and the core does not second-guess it.
- an.engines.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:
- an.engines.requests_as_dicts(requests)[source]#
Requests as plain dicts, the shape a page or a subprocess takes.
- an.engines.require_engine(engine)[source]#
Refuse an object that is not an engine, saying what is missing.
- Return type:
>>> require_engine(object()) Traceback (most recent call last): ... TypeError: an Engine needs `name` and `open(job)`; object lacks: name, open
- an.engines.require_seekable(session)[source]#
The session’s drive mode, or a refusal that says what to add.
- Return type:
>>> require_seekable(object()) Traceback (most recent call last): ... an.engines.protocol.UnseekableEngineError: this engine session cannot be captured: it has no frame(t) (time-driven), and no render(state) with a timeline (state-driven). Add frame(t) and state(t) if the engine evaluates the timeline itself, or timeline and render(state) if the core should evaluate it.
- an.engines.shot_workspace(work_dir, shot_id)[source]#
<work_dir>/shot_<id>: the one per-shot scratch directory.- Return type:
Modules
The capture loop: drive a session through every frame, resolve, write -- for ANY engine. |
|
Conformance of a TIME-driven engine against the timing kernel's golden vectors. |
|
|
|
The |