annie.pages.videoclock¶
Frame-accurate control of one HTML5 <video> element (UI, browser-gated).
The Event-annotation task drives a single ui.video from Python: play/pause, seek to a
time or a frame, step frame-by-frame, and jump ±5 s. HTML5 video exposes only a time
cursor (currentTime in seconds), not a frame cursor, so every frame operation converts
through the video’s fps:
frame -> currentTime = frame / fps + half_frame_nudge time -> frame = round(currentTime * fps)
Documented limitation. Because seeking is time-based, the landed frame is
round(currentTime * fps). On constant-fps media — which Annie’s convert pipeline
produces (see annie.media.convert) — this is exact. On a variable-fps source it can
be off by one frame. That is the accepted trade-off for smooth playback with audio, which
a torchcodec frame-by-frame decoder cannot give; an exact confirm is a possible later
refinement, deliberately out of scope here.
This module is a thin bridge: each function returns the JavaScript that acts on the element,
run via nicegui.ui.run_javascript(). It holds no state — the task owns the model. It
is exercised in the browser, not unit-tested, like the other ui.video paths.
Functions¶
|
Return the stable DOM id given to the task's video element for a client. |
|
Start playback of the video element. |
|
Pause the video element. |
|
Toggle play/pause on the video element. |
|
Seek the video to an absolute time in seconds (clamped at zero). |
|
Seek the video to a specific frame via its time, with a half-frame nudge. |
|
Pause and move the cursor by |
|
Jump the cursor by |
|
Read the video's current time in seconds from the browser. |
|
Move the timeline playhead line to a horizontal fraction without a full re-render. |
|
Move the pan scrollbar's thumb without rebuilding it (so a drag is not interrupted). |
|
Resize the amber capture band without a full re-render, while a start is armed. |
Module Contents¶
- annie.pages.videoclock.element_id(client_id: str) str[source]¶
Return the stable DOM id given to the task’s video element for a client.
- Parameters:
client_id – The NiceGUI client id (
context.client.id).- Returns:
A DOM id unique to that client’s Event-annotation video.
- annie.pages.videoclock.toggle(element_id_: str) None[source]¶
Toggle play/pause on the video element.
- annie.pages.videoclock.seek_seconds(element_id_: str, seconds: float) None[source]¶
Seek the video to an absolute time in seconds (clamped at zero).
- Parameters:
element_id – The video element’s DOM id.
seconds – The target time; negative values clamp to the start.
- annie.pages.videoclock.seek_frame(element_id_: str, frame: int, fps: float) None[source]¶
Seek the video to a specific frame via its time, with a half-frame nudge.
- Parameters:
element_id – The video element’s DOM id.
frame – The target frame index (clamped at zero).
fps – Frames per second; a non-positive fps seeks to the start.
- annie.pages.videoclock.step_frames(element_id_: str, delta: int, fps: float) None[source]¶
Pause and move the cursor by
deltaframes (positive forward, negative back).- Parameters:
element_id – The video element’s DOM id.
delta – Number of frames to move; sign gives the direction.
fps – Frames per second; a non-positive fps is a no-op.
- annie.pages.videoclock.nudge_seconds(element_id_: str, delta: float) None[source]¶
Jump the cursor by
deltaseconds (the ±5 s buttons), clamped at the start.- Parameters:
element_id – The video element’s DOM id.
delta – Seconds to move; sign gives the direction.
- annie.pages.videoclock.current_time(element_id_: str) collections.abc.Awaitable[float][source]¶
Read the video’s current time in seconds from the browser.
Used when
I/Ocapture the playhead: the caller awaits this, converts to a frame, and writes the event boundary. Returns0.0if the element is gone.- Parameters:
element_id – The video element’s DOM id.
- Returns:
An awaitable resolving to the current time in seconds.
- annie.pages.videoclock.set_playhead_x(timeline_id: str, x_fraction: float | None) None[source]¶
Move the timeline playhead line to a horizontal fraction without a full re-render.
The playhead is a single SVG line inside the timeline element; the poll updates only its position so playback stays cheap (no server round-trip re-draw of the event boxes).
- Parameters:
timeline_id – DOM id of the timeline’s SVG element.
x_fraction – Playhead position as a fraction
[0, 1]of the visible window, orNonewhen the playhead is outside it — the line is then hidden, never pinned to an edge.
- annie.pages.videoclock.set_scrollbar(scroll_id: str, left: float, width: float) None[source]¶
Move the pan scrollbar’s thumb without rebuilding it (so a drag is not interrupted).
- Parameters:
scroll_id – DOM id of the scrollbar track.
left – The thumb’s left edge as a fraction of the track.
width – The thumb’s width as a fraction of the track.
- annie.pages.videoclock.set_pending_band(timeline_id: str, start_fraction: float, end_fraction: float) None[source]¶
Resize the amber capture band without a full re-render, while a start is armed.
Mirrors
set_playhead_x(): the band is one.annie-pendingrect, and the poll updates only itsx/widthfrom two[0, 1]fractions so it grows with the playhead cheaply. Fractions are ordered and clamped, so a playhead left of the start still yields a valid (leftward) band.- Parameters:
timeline_id – DOM id of the timeline’s SVG element.
start_fraction – The band’s start edge as a fraction of the timeline width.
end_fraction – The band’s end edge (the live playhead) as a fraction of the width.