Data Physicalization — our demo

One example among many. Don't reuse its story, arc, shots, props or timings.

Demo: Two Spirals 《兩條螺旋》 (39.4 s) · data-physical.mp4 · source in demo/

Twelve years of global wind and solar capacity (IRENA 2026, via Our World in Data, CC BY 4.0), built as two spirals of real plates on a walnut dial: one plate is 10 GW for both, aluminium for solar, teal acrylic for wind, a brass plate every 100 GW. Chinese on screen, English narration, bilingual subtitles (Chinese line above, English line below). This is an unofficial film made from published data; IRENA and Our World in Data did not make or endorse it.

Story & structure

Logline: in 2014 the world had almost twice as much wind as solar; in 2021 solar passed wind; by 2025 the ratio is the other way round (solar = wind × 1.86).

Arc: the pair (2014, wind and solar side by side, held, then the verdict ×1.95) → the rule (a macro of one plate and one brass plate) → growth (2015–2020 pairs assemble as the camera tracks along the spiral) → the turn (2020 and 2021 pairs held still with four readings, a suck-out, then "2021 · solar passed wind") → the climax (2025: last year's level cascades in, then 52 new plates are fed one by one while the counter rolls to 2,396.7 GW) → the reveal (the crane pulls back to near top view: two spirals and the inlaid ticks become one dial) → the ending (a brass puck engraved ×1.86 falls onto the centre; end card).

Native moves spent: the unit close-up for the rule; the paired climb through the decade; the feed for 2025; chart to installation as the signature pull-back; the last object for the final number. Every number and its source is in demo/FACTS.md.

Shots

One continuous take. Times in seconds; 96 BPM, a bar is 2.5 s.

# Time Shot Camera Native move / note
1 0.0–2.5 the 2014 pair assembles (wind from 0.1, solar from 0.4): 35 acrylic plates, 18 aluminium low side view, pulling back from close first plates land in the first frame
2 2.5–7.5 both readings in one column (349.5 / 178.8 GW), held 2.8 s; verdict "風電 = 太陽能 × 1.95" at 5.0 slow orbit comparison held before the verdict
3 7.5–10.3 brackets on one plate "1 片 = 10 GW" and one brass plate "黃銅 = 100 GW" push into the solar stack's side, f-stop wide the unit close-up
4 10.0–17.5 2015–2020 pairs cascade one every 1.25 s; brass plates ring low lateral track along the spiral, rising with the tops no labels: the inlaid years carry it
5 17.5–22.5 2021 assembles; 2020 and 2021 pairs held with four readings from 18.85; suck-out 21.5; verdict "2021 · 太陽能超過風電" at 21.875 crane up to a locked three-quarter frame, 2–3 % creep the turn
6 22.5–25.3 2022–2025 pairs cascade in quick succession fast track along the spiral the verdict stays in the upper-left third over the move
7 25.3–30.0 2025 solar shoots up to 2024's level, then 52 plates are fed one per 1/10 beat; counter 1,883.2 → 2,396.7 GW, "當年新增 +513.5 GW" crane rising with the top the feed; style frame at 28.6
8 30.0–34.4 the whole set: two spirals, ticks and inlaid years read as a dial crane back and up to ~70° top view, target offset left for the end card chart to installation
9 34.4–39.4 a brass puck engraved ×1.86 falls to the centre (suck-out 33.75–34.375); accent line "2025 · 太陽能裝機是風電的 1.86 倍" with a leader to the puck; end card slow turn of the top view the last object; poster at 37.8

Score structure

96 BPM, 4/4, D major; one chord per bar: Dadd9 – Dadd9 – Bm – Gmaj7 | D – A/C♯ – Bm – G | Asus (bar 8, cut short) | D – Bm – G | A – Gmaj7 | D – D.

Section Time Palette Notes
Wind leads 0–10 glass harp + harp motif (A5 F♯5 E5 D5…), synth pad, bowed vibraphone sparse; the plates' own ticks and brass notes carry the rhythm
Growth 10–20 marimba arpeggio in 8ths, pulse bass in quarters (2nd/3rd harmonics) each pair's cascade is an arpeggio of ticks and glockenspiel / glass notes climbing a D pentatonic ladder (one note per 100 GW)
Crossover 20–21.875 timpani heartbeat on A, a held horn A3 suck-out 21.5–21.875 (music and foley −30 dB)
Turn 21.875 punch (60–120 Hz) + bass drum + timpani D3 + horns D–F♯–A + trombone D2 + glockenspiel F♯6 + metal ring second-loudest moment
2025 22.5–30 marimba 16ths, pulse 8ths, a glockenspiel line D6–E6–F♯6–A6–B6–A6 over the feed; 52 metal ticks; vibraphone chord + timpani when the last plate lands (29.2) the densest stretch
Dial 30–33.75 horns D3/A3/F♯4 and cellos D3 under the crane, marimba back to 8ths suck-out 33.75–34.375
Puck 34.375 punch + bass drum + gran cassa + timpani D3 + tubular bells D5/A4 + metal rings; five small ticks of the puck settling the loudest moment of the film
End 34.4–39.4 harp arpeggio D4…D6, bowed vibraphone D5/A4 fade

Mix (demo/mix.py): stems set against the voice's active RMS (music −10.9 dB, pulse −12.2 dB, foley −8.6 dB, hits −2.3 dB, studio-air bed far under), music ducked ~4 dB under speech; bus compression on music, pulse, foley and bed only; a 36 Hz high-pass (44 Hz, 4th order on hits) and a −5 dB shelf below 62 Hz on everything but the voice; master to −14.4 LUFS with a 4× oversampled true-peak limiter at −4.6 dBTP, then mux.sh (−14 LUFS). The film measures −13.8 LUFS integrated, LRA 6.6 LU.

Palette & props

End card

Left third over the turning dial: 兩條螺旋 (Noto Serif SC), Two Spirals, a rule, DATA PHYSICALIZATION · 數據實物化, LemoLab × Claude Opus 5.5; above it the accent line with its leader to the puck; the data source stays in the top-right corner from the crane on. 4.6 s. The "LemoLab × Claude Opus 5.5" sign-off belongs to this library's demo only; a user's film carries no LemoLab credit and no copy of this card.

Build notes

demo/
  build.sh          one command: fonts (first run) → voice → speech check → cues → events → picture → mix → master → .srt → checks → poster
  index.html        WebGL canvas + 2D overlay canvas, fonts.css
  timeline.js       single source: BPM grid, build times, holds, verdicts, suck-outs, narration + subtitles, every on-screen string (LABELS)
  data.js           the twelve years of both series (IRENA 2026 via OWID) and the unit rule
  set.js            the physical set (lights, walnut dial + inlay, instanced plates per material, the puck), the landing schedule, EVENTS
  film.js           camera keys, reading kit (pairLabels, verdict, counter), subtitles, end card, TEXTS (readcheck), SUBCHECK, EV
  mix.py            score, material foley, voice, suck-outs, mix and master → out/mix.wav, out/stems/
  tools/            export.mjs (voice lines, timeline.json, cues), fonts.mjs (OFL subsets), srt.mjs, subcheck.mjs, holdcheck.py
  data/             the downloaded CSVs and metadata
  FACTS.md, CREDITS, stills/styleframe.jpg