Skip to content

Live Viewer

LiveViewer starts the server immediately and streams push_state calls to connected browser tabs over WebSocket as a simulation runs. See Live Streaming for a worked example.

simview.live.LiveViewer

LiveViewer(
    scene: SimulationScene,
    host: str = "127.0.0.1",
    preferred_port: int = 5420,
    open_browser: bool = False,
    queue_size: int = _SEND_QUEUE_MAXSIZE,
)

Streams a running simulation to an already-open browser tab over WebSocket, instead of the usual save-then-view flow.

scene should already have its complete model (terrain, bodies, ...) -- states are pushed incrementally afterwards via push_state, using the same validation/encoding as SimulationScene.add_state. Because push_state appends to scene.states exactly like add_state would, the scene can still be save()d normally once streaming is done.

Broadcasting happens on a dedicated sender thread fed by a bounded queue, so the simulation loop calling push_state is never blocked by a slow or hung browser tab -- see _enqueue for the backpressure policy.

dropped_frames property

dropped_frames: int

How many frames were skipped on the wire because the viewer could not keep up. Purely a live-streaming statistic: dropped frames are still recorded in scene.states and in the server's catch-up buffer.

mark_episode

mark_episode(
    label: str | None = None, start_index: int | None = None
)

Mark the start of an episode at the current point in the stream.

The episodic counterpart to push_state: call it on each reset, before pushing that episode's first frame. Connected viewers update their playback bar immediately; a viewer that connects later picks the boundaries up from /model. Returns the created SimViewEpisode.

Like push_state, this never blocks the caller on the network.

push_state

push_state(time, body_states, scalar_values=None) -> None

Append one frame and hand it to the sender thread for broadcast.

Runs on the caller's thread, but never blocks on the network: it delegates to scene.add_state for the same validation/encoding SimulationScene normally does (the frame also lands in self.scene.states, so scene.save() still works after streaming), records the frame for catch-up, and returns as soon as the frame is queued. Safe to call before any client has connected -- the frame is simply buffered for the next connection's catch-up message.

stop

stop() -> None

Flush queued frames, then signal the server to exit and wait for it.

Idempotent -- safe to call multiple times (e.g. once explicitly and once more via exit).