Skip to content
Docs
Open Promoeyes
youtube-devices

youtube-devices

YouTube on four screens — paused, then played, one device at a time.

Read the rig's notes
Four devices stand side by side at TRUE PHYSICAL SIZE (iphone 71×154 mm of
glass, ipad 197×262, macbook 346×223, a 480×300 chrome window), each running
the same YouTube-style page on the same clip. Every player starts PAUSED
behind a play button; the cursor clicks them one at a time while the camera
frames each device at fill=90; by the last beat all four are playing.

HOW "PAUSED" IS BUILT — there is no play/pause state in this format, and
there does not need to be. `video` is SAMPLED at scene time, so the paused
frame is simply a still sitting on top of a clip that has been running all
along:

  video(src="video:city-station" …)          <- always running underneath
  image(href="media:poster-phone" …)         <- the paused frame, on top
    opacity  1 until the click, 0 after

The poster is the frame the live clip is ACTUALLY at when the click lands
(`T mod duration`, extracted with ffmpeg), so the cut from still to motion
has nothing to cut — it is the same frame. Using an `image` rather than a
second `video(freeze=true)` also keeps this to FOUR decoders, not eight.

Click times, and therefore the poster frames (clip is 4.667 s long):
  phone   4.2 s -> 4.200 s     laptop  12.4 s -> 3.066 s
  tablet  8.0 s -> 3.333 s     web     17.4 s -> 3.399 s

Preview: /packages/runtime/index.html?project=promos/new/youtube-devices/youtube-devices.promo
Topic
uis
Scenes
1
Kind
reference rig
//
    YouTube on four screens — paused, then played, one device at a time.

    Four devices stand side by side at TRUE PHYSICAL SIZE (iphone 71×154 mm of
    glass, ipad 197×262, macbook 346×223, a 480×300 chrome window), each running
    the same YouTube-style page on the same clip. Every player starts PAUSED
    behind a play button; the cursor clicks them one at a time while the camera
    frames each device at fill=90; by the last beat all four are playing.

    HOW "PAUSED" IS BUILT — there is no play/pause state in this format, and
    there does not need to be. `video` is SAMPLED at scene time, so the paused
    frame is simply a still sitting on top of a clip that has been running all
    along:

      video(src="video:city-station" …)          <- always running underneath
      image(href="media:poster-phone" …)         <- the paused frame, on top
        opacity  1 until the click, 0 after

    The poster is the frame the live clip is ACTUALLY at when the click lands
    (`T mod duration`, extracted with ffmpeg), so the cut from still to motion
    has nothing to cut — it is the same frame. Using an `image` rather than a
    second `video(freeze=true)` also keeps this to FOUR decoders, not eight.

    Click times, and therefore the poster frames (clip is 4.667 s long):
      phone   4.2 s -> 4.200 s     laptop  12.4 s -> 3.066 s
      tablet  8.0 s -> 3.333 s     web     17.4 s -> 3.399 s

    Preview: /packages/runtime/index.html?project=promos/new/youtube-devices/youtube-devices.promo
promo#youtube-devices

  scene#tour(duration=24 transition=none)

    // The whole shot list. Beat 1 is the establishing wide (framing="all", so
    // no coordinate is typed); every beat after it is a FRAMED kf naming one
    // device at fill=90, and the last returns to the wide with all four live.
    camera(type=perspective fov=38 near=8.5 far=22000 position="0 0 1500" look_at="0 -20 0")
      properties
        frame(smooth=0.35)
          keyframes
            kf(time=0 framing=all fill=97)
            kf(time=2.0 framing=all fill=97 easing=linear)
            kf(time=3.4 node=yt-phone fill=90 easing=easeInOutCubic)
            kf(time=5.6 node=yt-phone fill=90 easing=linear)
            kf(time=7.2 node=yt-tablet fill=90 easing=easeInOutCubic)
            kf(time=9.4 node=yt-tablet fill=90 easing=linear)
            kf(time=11.4 node=yt-laptop fill=90 easing=easeInOutCubic)
            kf(time=13.6 node=yt-laptop fill=90 easing=linear)
            kf(time=16.2 node=yt-web fill=90 easing=easeInOutCubic)
            kf(time=18.6 node=yt-web fill=90 easing=linear)
            kf(time=21.0 framing=all fill=95 easing=easeInOutCubic)
            kf(time=24 framing=all fill=95 easing=linear)

    background(top=#12141c bottom=#05060a)
    lights
      light#amb(type=ambient color=#a8bfe0 intensity=0.85)
      light#key(type=directional color=#ffffff intensity=1.3 position="420 760 900")
      light#fill(type=directional color=#8fa8d8 intensity=0.55 position="-620 200 520")
    environment(hdr="studio_small_04_2k" as_background=false exposure=1.0 blurriness=0.6 intensity=0.3)
    postprocessing
      step(name=render)
      step(name=unreal_bloom strength=0.1 radius=0.4 threshold=0.95)

    haze#hz-a(blend=add opacity=0.13 color=#ff0033 size="2600 1700" pulse=0 decay=0 position="-620 120 -1200")
    haze#hz-b(blend=add opacity=0.11 color=#2563eb size="2900 1900" pulse=0 decay=0 position="560 -160 -1200")
    haze#hz-c(blend=add opacity=0.08 color=#7c3aed size="2200 1500" pulse=0 decay=0 position="0 40 -1260")

    // ===================================================================
    // 01 · IPHONE — 71 × 154 mm of glass. Clicked at 4.2 s.
    // ===================================================================
    iphone#yt-phone(position="-700 -26 40" rotation="0 6 0" body-material=porcelain)
      ui(width=71 height=154)
        card(anchor=top-left w=71 h=154 r=0 fill=#0f0f0f shadow=false)
        // top bar
        card(an