Skip to content

tams-keyframe-generator — visual index

A store you can only play is a store you have to watch. This produces a picture per second of every recorded video flow, so material can be looked at — browsed, scanned, and found — instead of scrubbed through in real time.

TAMS — components tams-recorder tams-player tams-flow-manager tams-flow-visualiser tams-serverREST APIMySQL meta · S3 alloc register fetch delete reqs browse MySQL — metadata MinIO / S3 — media objects metadata in MySQL · media blobs in object storage via signed URLs · retention by flow-manager

  • Produces: a derived TAMS flow of JPEG keyframes, one per second of media time
  • Default size: 240 × 120, configurable
  • Addressed by: a companion JSON frame-index flow

Discover. On startup it registers a webhook on the TAMS server for flow and segment creation, and reconciles existing flows by polling. New segments arrive by webhook; a periodic reconcile pass backfills anything missed. As with the transcode watcher, that redundancy is deliberate — webhook delivery is best-effort, and the poll turns a missed event into a delay rather than a permanent gap in the index.

Queue. Each observed source segment becomes a de-duplicated job, so the same segment seen twice is not processed twice.

Process. A pool of workers downloads the source segment, decodes it, picks the decoded frame at each whole-second point inside that segment’s time range, encodes each as a JPEG at the configured size, packs them into a single object with a frame index, and registers a keyframe segment covering the same time range as the source.

Keyframes land on a global integer-second grid in media time, not wall-clock time.

This matters more than it sounds. A segment boundary is an arbitrary place in the material — it falls where the recorder happened to close a segment. If the one-second cadence were counted from the start of each segment, the grid would shift at every boundary, and two adjacent segments would disagree about where a second begins. Anchoring to a global grid means the nth keyframe of a flow is always the same moment of that flow, regardless of how the material happened to be segmented, and regardless of when the generator got round to processing it.

One derived segment per source segment, covering the same time range. The keyframe flow therefore has the same shape as the material it describes: ask for a time range and you get the pictures for exactly that range, with no mapping step and nothing to go out of sync when the source is trimmed by retention.

Connection and authentication follow the usual TAMS client pattern — basic auth, a bearer token, or OAuth2 client credentials.

Beyond that the useful knobs are the keyframe width, height and quality, the interval in media seconds, and include/exclude flow filters for restricting which flows get an index at all. The webhook receiver needs a publicly reachable callback URL and takes a shared-secret header, so the TAMS server can prove it is the one calling.

Sizes are the one place to be careful: width must be a multiple of 16 and height a multiple of 8.