ViewerSession

Qualified name: algan.viewer.session.ViewerSession

class ViewerSession(scene, video_settings=None)[source]

Bases: object

A Scene, rendered on demand for a browser to page through.

Methods

attributes

children

close

Stop the worker and wait for it to actually leave the Scene alone.

frame

The PNG for a frame, rendering it first if it is not cached.

frame_of

The frame index a timestamp lands on, clamped to the video.

pixel

The fragment list behind one pixel of one frame.

prefetch

Ask the worker to render around index without waiting for it.

resolution_options

The picker's rows: a name to post back, and a label to show.

roots

set_resolution

Re-render everything at another of the offered resolutions.

state

Everything the page needs to lay itself out.

time_of

The timestamp a frame index lands on.

close(timeout=30.0)[source]

Stop the worker and wait for it to actually leave the Scene alone.

Waiting is the point. A render materializes the Scene’s timeline at the frames it is drawing and restores it when it finishes; a worker still running after the viewer is gone would leave the Scene materialized under whoever authors next, which shows up as shape mismatches in code nowhere near here.

frame(index, timeout=120.0)[source]

The PNG for a frame, rendering it first if it is not cached.

frame_of(seconds)[source]

The frame index a timestamp lands on, clamped to the video.

pixel(frame, x, y, wait=3.0)[source]

The fragment list behind one pixel of one frame.

Computed on a thread of its own and reported back over however many requests it takes, rather than by holding one request open until it is done. That is not a style preference: the first inspection of a session compiles a Taichi kernel variant for the capture-armed render path, which was measured at 12 s with an idle worker and 67 s with one still rendering, and a browser asked to wait that long for a single response gives up and reports it to the page as TypeError: Failed to fetch – discarding an answer that was on its way.

So this waits wait seconds, which is long enough that a warm inspection (~2 s) still answers in one round trip, and otherwise returns {"pending": True} for the page to poll on. Results are cached by (frame, x, y), so the poll that finally lands costs nothing and re-inspecting a pixel is free.

prefetch(index)[source]

Ask the worker to render around index without waiting for it.

resolution_options()[source]

The picker’s rows: a name to post back, and a label to show.

Labelled (height, width), which is the order asked for – note it is the reverse of VideoSettings.resolution, which is (width, height).

set_resolution(name)[source]

Re-render everything at another of the offered resolutions.

Returns the new state, or None if there is no such option.

Takes the Scene lock, so it waits out the batch in flight rather than swapping the size under a render that has already read it. Everything cached is then wrong by definition and goes: the frames, and the pixel inspections whose coordinates were in the old frame’s grid.

state()[source]

Everything the page needs to lay itself out.

time_of(index)[source]

The timestamp a frame index lands on.