Skip to content
Docs
Open Promoeyes
videos

videos

Video primitives — `video` as a UI item, one idea per scene.

Read the rig's notes
A `<video>` inside `<ui>` / `<ui3d>` is an item like any other. It goes
wherever an `image(...)` can go — device glass, a chrome window, a floating
ui3d panel — and adds the two things an image does not need:

  A MASK. `clip="inherit"` (the default) reads the SHAPE OF THE PARENT.
  A square parent crops square, a rounded card crops to that card's own
  radius, an avatar crops to a disc. The same authored line —

    video(src="video:product-loop" w="fill" h="fill" fit=cover)

  — is a rectangle in one parent and a circle in the next, with nothing
  about the shape written on the video itself.

  A CLOCK. THE CLIP DOES NOT PLAY, IT IS SAMPLED. Scene time is the only
  clock; `start` / `end` / `loop` / `speed` / `freeze` are a mapping from
  scene seconds to source seconds, evaluated fresh every frame. That is
  what makes a scrub, a re-render and a headless capture agree on the same
  frame.

ATTRIBUTES
  src|href|url  an asset NAME, never a path: `video:product-loop` for the
                shared library, `media:aurora-sky` for a clip that lives in
                this promo's own folder. The endpoint owns the directory
                and the extension.
  w / h         the layout box in mm. Give one axis and `aspect` (default:
                the clip's own) resolves the other.
  fit           cover (default) | contain | fill — how the clip meets a box
                of a different aspect. A UV transform, not a redraw.
  clip          inherit (default) | square | round | circle | none
  r / radius    an explicit corner radius, in mm. Beats `clip="inherit"`.
  start / end   the trim window in the SOURCE, in seconds.
  loop          true (default) — wrap scene time at the window length.
  speed         source seconds per scene second. 1 by default.
  freeze        hold the frame at `start` — a poster still, no decode churn.
  color         the placeholder fill shown until the first decoded frame.
  opacity       animatable, like every other item.

THE SHAPE TABLE (what `clip="inherit"` resolves to)
  card           -> its own r (default 8)     container -> its radius (14)
  glass-window   -> r 12                      window-frame -> r 12 / 10
  panel          -> 18                        video-card -> 16
  avatar, stat-ring -> a CIRCLE
  row/column/grid/stack/group/box -> PASS THROUGH to the nearest drawn
                   ancestor (scaffolding never resets the shape to square)
  the <ui> stage root -> square
  anything else  -> square
  KNOWN LIMIT: a `card path="M…"` silhouette is not followed; the mask
  falls back to that card's `r`.

SCENES
  01 glass      a clip filling real phone glass — square, then r=6
  02 chrome     the crop follows a rounded card with nothing authored;
                the same video again with clip="none"
  03 shapes     ONE clip, four parents, one frame — the whole feature
  04 fit        cover vs contain vs fill on a mismatched aspect
  05 time       trim, speed, freeze — one source, four points in one second
  06 wall       macbook + ipad + iphone + a floating ui3d panel
  07 scroll     an ancestor's overflow clip INTERSECTING the video's mask
  08 reference  every attribute, called out on one board

Scenes 03/04/05/08 are full-stage <ui3d> boards: the default 1920x1080
stage mapped 1:1 into world space, camera at 960 540 <dist>, so every
coordinate below is a stage pixel with the origin at the top-left.

Preview: /packages/runtime/index.html?project=promos/primitives/videos/videos.promo
Topic
uis
Scenes
8
Kind
reference rig
//
    Video primitives — `video` as a UI item, one idea per scene.

    A `<video>` inside `<ui>` / `<ui3d>` is an item like any other. It goes
    wherever an `image(...)` can go — device glass, a chrome window, a floating
    ui3d panel — and adds the two things an image does not need:

      A MASK. `clip="inherit"` (the default) reads the SHAPE OF THE PARENT.
      A square parent crops square, a rounded card crops to that card's own
      radius, an avatar crops to a disc. The same authored line —

        video(src="video:product-loop" w="fill" h="fill" fit=cover)

      — is a rectangle in one parent and a circle in the next, with nothing
      about the shape written on the video itself.

      A CLOCK. THE CLIP DOES NOT PLAY, IT IS SAMPLED. Scene time is the only
      clock; `start` / `end` / `loop` / `speed` / `freeze` are a mapping from
      scene seconds to source seconds, evaluated fresh every frame. That is
      what makes a scrub, a re-render and a headless capture agree on the same
      frame.

    ATTRIBUTES
      src|href|url  an asset NAME, never a path: `video:product-loop` for the
                    shared library, `media:aurora-sky` for a clip that lives in
                    this promo's own folder. The endpoint owns the directory
                    and the extension.
      w / h         the layout box in mm. Give one axis and `aspect` (default:
                    the clip's own) resolves the other.
      fit           cover (default) | contain | fill — how the clip meets a box
                    of a different aspect. A UV transform, not a redraw.
      clip          inherit (default) | square | round | circle | none
      r / radius    an explicit corner radius, in mm. Beats `clip="inherit"`.
      start / end   the trim window in the SOURCE, in seconds.
      loop          true (default) — wrap scene time at the window length.
      speed         source seconds per scene second. 1 by default.
      freeze        hold the frame at `start` — a poster still, no decode churn.
      color         the placeholder fill shown until the first decoded frame.
      opacity       animatable, like every other item.

    THE SHAPE TABLE (what `clip="inherit"` resolves to)
      card           -> its own r (default 8)     container -> its radius (14)
      glass-window   -> r 12                      window-frame -> r 12 / 10
      panel          -> 18                        video-card -> 16
      avatar, stat-ring -> a CIRCLE
      row/column/grid/stack/group/box -> PASS THROUGH to the nearest drawn
                       ancestor (scaffolding never resets the shape to square)
      the <ui> stage root -> square
      anything else  -> square
      KNOWN LIMIT: a `card path="M…"` silhouette is not followed; the mask
      falls back to that card's `r`.

    SCENES
      01 glass      a clip filling real phone glass — square, then r=6
      02 chrome     the crop follows a rounded card with nothing authored;
                    the same video again with clip="none"
      03 shapes     ONE clip, four parents, one frame — the whole feature
      04 fit        cover vs contain vs fill on a mismatched aspect
      05 time       trim, speed, freeze — one source, four points in one second
      06 wall       macbook + ipad + iphone + a floating ui3d panel
      07 scroll     an ancestor's overflow clip INTERSECTING the video's mask
      08 reference  every attribute, called out on one board

    Scenes 03/04/05/08 are full-stage <ui3d> boards: the default 1920x1080
    stage mapped 1:1 into world space, camera at 960 540 <dist>, so every
    coordinate below is a stage pixel with the origin at the top-left.

    Preview: /packages/runtime/index.html?project=promos/primitives/videos/videos.promo
promo#videos

  // =======================================================================
  // SCENE 01 · GLASS — a clip filling real phone glass
  // The video is authored twice and cross-faded: the first is square (the