DEV Community

Cover image for Magic Lamp Ep.1

Magic Lamp Ep.1

"You'll like it — not a lot, but you'll like it."
— Paul Daniels

Paul Daniels never actually made things appear from nowhere. The secret to his act was subtler: he made you see life in the lifeless. A silk handkerchief folded just so. A coin that hesitated before vanishing. The magic wasn't in the props — it was in the relationship between performer and object. The audience believed because the performer believed first.

This is a project that works the same way.


🎭 The Performance

PIXSTARS is a 20-minute silent theatrical piece for a live event. The setup is deliberately sparse:

  • One performer on stage
  • One animatronic desk lamp named Pinokio
  • A live piano
  • A deconstructed rendering of Guns N' Roses' November Rain
  • No dialogue. Not a single word.

The lamp is not a prop. It is a co-performer. It has 14 distinct personality states — from INERT to ARROGANT to DYING to REBORN — and moves through them on choreographed cues as the music plays. The performer holds three simultaneous character identities (Rockstar, Creator, Witness). The lamp holds the mirror.

Think Kim Ki-duk, not Cirque du Soleil. Sparse. Patient. Emotionally loaded.


🪄 The Paul Daniels Problem

When Paul Daniels placed a lifeless prop on his table, it was just an object. The moment he began working with it — tilting, pausing, reacting — it became a character. The prop hadn't changed. The frame around it had.

Building Pinokio means solving the same problem in code: how do you cross the line from object that moves to character that lives?

The answer, it turns out, is architecture.

A lamp that moves on command is a prop. A lamp that has emotional states, reacts to music, speaks with its body, and wakes up on cue — that's a character. The difference is not hardware. It's the layer of abstraction between the mechanical and the theatrical.

This series documents exactly how that abstraction is built.


🏗️ The Stack

Before we get into code, here is the complete hardware and software picture.

Hardware:

Component Role
Mac Mini M4 Pro Show control host, runs everything
Pololu Mini Maestro 24-ch USB servo controller Lamp motion brain
4x MG996R servos Large articulation: base, shoulder, elbow, head tilt
2x MG90S servos Fine motion
MEAN WELL LRS-50-5 PSU 5V servo rail, isolated from logic
Arduino Nano NeoPixel serial bridge (the Maestro doesn't speak NeoPixel)
NeoPixel RGBW ring Lamp head LED indicator
Logitech C920 webcam Mounted near lamp — gaze source or projection input
Raspberry Pi Zero 2 WH Satellite node: mic, speaker, LED — no soldering required
Enttec DMX USB Pro Stage lighting control

Software subsystems (all on the Mac Mini):

┌─────────────────────────────────────────────────────┐
│                   SHOW CONDUCTOR                    │
│           conductor/main.py  (YAML timeline)        │
└────────┬──────────┬──────────┬──────────┬───────────┘
         │ OSC      │ OSC      │ OSC      │ OSC
         ▼          ▼          ▼          ▼
    Port 3819   Port 9001   Port 9002   Port 9003
    ┌───────┐  ┌────────┐  ┌──────────┐  ┌─────────┐
    │Ardour │  │  Lamp  │  │Projection│  │Lighting │
    │  DAW  │  │adapter │  │(pygame)  │  │  (DMX)  │
    └───────┘  └────────┘  └──────────┘  └─────────┘
                                  all mirrored to
                              Port 9004 / WS 8765
                         ┌──────────────────────┐
                         │    Digital Twin      │
                         │  (BabylonJS + Deno)  │
                         └──────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Every subsystem speaks OSC (Open Sound Control) over UDP on localhost. The conductor doesn't know or care whether the lamp adapter talks to real servos or a simulator — it just sends /lamp/state CURIOUS and moves on.

That decoupling is the key architectural decision. More on that in episode 2.


🎛️ OSC: The Nervous System

OSC is the protocol that holds the show together. It's a UDP-based message format originally designed for musical instruments and live sound, which makes it a natural fit for real-time stage control. Messages look like:

/lamp/state        CURIOUS
/projection/scene  DISNEY_CASTLE
/lighting/state    DISNEY_SOFT
/toggle_roll       (Ardour play/stop)
Enter fullscreen mode Exit fullscreen mode

Each subsystem listens on its own port. The conductor dispatches all messages for a single cue within the same 50ms polling tick. The result is near-simultaneous state transitions across audio, video, light, and motion.

The complete port map:

# conductor/config.py
ARDOUR_OSC_PORT     = 3819   # Ardour 9 control surface
LAMP_OSC_PORT       = 9001   # Lamp personality adapter
PROJECTION_OSC_PORT = 9002   # Pygame display
LIGHTING_OSC_PORT   = 9003   # Enttec DMX USB Pro
TWIN_OSC_PORT       = 9004   # Digital Twin OSC bridge
TWIN_WS_PORT        = 8765   # Digital Twin WebSocket (browser)
Enter fullscreen mode Exit fullscreen mode

⏱️ The Timeline: 15 Cues, 9 Minutes 15 Seconds

The entire show lives in a single YAML file. Here's a slice:

# conductor/timeline.yaml (excerpt)
cues:
  - time: 0.0
    name: SHOW_START
    lamp: INERT
    projection: BLACKOUT
    lighting: BLACKOUT
    ardour: {command: transport_play}

  - time: 60.0
    name: DRUMS_BEGIN
    lamp: CURIOUS

  - time: 340.0
    name: OVERHEATING
    lamp: OVERHEATING
    lighting: OVERHEAT

  - time: 380.0
    name: LAMP_DEATH
    lamp: DYING
    lighting: DEATH

  - time: 460.0
    name: REVEAL_AI
    lamp: WEAK
    projection: AI_SIGNATURE
    lighting: REBIRTH
Enter fullscreen mode Exit fullscreen mode

At second 0, the lamp is INERT and Ardour begins playing. By second 60, the drums enter and the lamp becomes CURIOUS. By second 380, it is DYING. The arc from object to character to death to rebirth — all scripted, all precise, all driven by this YAML.

Paul Daniels rehearsed his timing with a stopwatch. So does Pinokio.


🔮 What's Coming in This Series

Episode Topic
1 (this one) Architecture overview — the magic prop metaphor
2 The Show Conductor — OSC dispatching and timeline execution
3 14 Personalities in a Lampshade — servo states and motion vocabulary
4 Light the Stage — DMX control, pygame projection, and the digital twin
5 Finding Its Voice — HiveMind, Coqui XTTS, and the Raspberry Pi satellite

By the end of episode 5, Pinokio will have gone from a desk lamp on a table to a character capable of reacting to music, shifting emotional states on cue, speaking in a synthesised voice, and lighting up its own head in synchrony with its mood — all orchestrated from a single Python process on a Mac Mini.

Not a lot. But you'll like it.


Next: Episode 2 — The Show Conductor: how 15 YAML cues orchestrate five subsystems in real time.

Top comments (0)