Skip to content

feat(time-offset): add Time Offset block for live PTS shifting#555

Merged
srperens merged 1 commit intomainfrom
feat/time-offset-block
May 8, 2026
Merged

feat(time-offset): add Time Offset block for live PTS shifting#555
srperens merged 1 commit intomainfrom
feat/time-offset-block

Conversation

@srperens
Copy link
Copy Markdown
Collaborator

@srperens srperens commented May 8, 2026

Summary

  • New builtin.time_offset block: a single identity element whose src pad has a GStreamer pad-offset applied. Media-agnostic (Generic in/out pads), so the same block works on audio or video branches.
  • offset_ms (Float, signed) is live-updatable. A small interceptor in update_element_property catches it before the default property-set path and applies pad.set_offset() directly, then triggers pipeline.recalculate_latency() so downstream sinks resync.

Why

Two use cases drove this:

  • Lipsync — drop a Time Offset block between an input and a mixer to align audio against video (or vice versa).
  • Per-branch latency shaping — give different output branches different latency budgets (e.g. WHEP PGM gets full pipeline latency, WHEP multiview is shifted to play out earlier relative to PGM).

Design notes

  • Positive offset_ms shifts buffers later (delay), negative shifts them earlier (advance). Negative is accepted in the API, but with live sources only positive is physically meaningful — the pipeline cannot emit data ahead of the source. Documented in the property description.
  • The interceptor is keyed on (prop_name == "offset_ms", element_id ends_with ":offset_identity"). Coupling to the block's PropertyMapping and element naming is documented at the function site.
  • The block reuses the existing exposed-property infrastructure for persistence, WebSocket events, properties-panel UI, etc. — no new API endpoints, no new event variants.

Test plan

  • cargo test --lib time_offset — 6 unit tests covering definition shape, live apply (positive, negative, non-matching element, non-matching property), and initial offset on build
  • cargo test --test openapi_test — snapshot unchanged (no new API types)
  • cargo test --test pipeline_lifecycle_test — leak regression still passes
  • cargo check and clippy pre-commit hooks clean
  • Manual: create flow with Time Offset between input and mixer, verify lipsync drag in properties panel updates pipeline live without restart

🤖 Generated with Claude Code

Generic media-agnostic block that shifts buffer running_time via
gst_pad_set_offset. Use cases: lipsync between audio/video inputs to a
mixer, and per-branch latency shaping (e.g. PGM vs multiview WHEP outputs).

The `offset_ms` exposed property is live-updatable. A new interceptor in
update_element_property catches it before the default property-set path
and applies the offset directly to the identity src pad, then triggers
recalculate_latency() so downstream sinks resync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@srperens srperens merged commit bc8a2af into main May 8, 2026
7 checks passed
@srperens srperens deleted the feat/time-offset-block branch May 8, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant