UMBRA

The Umbra script language.

An Umbra script is a plain-text list of timed camera commands, written relative to the eclipse contacts so it works at any location. Many people don't choose to write them by hand, the Script Wizard and the AI assistant generate it for you. This page explains what they produce, so you can read, tweak, and trust your sequence.

You usually don't start from scratch. Build a script with the in-app Script Wizard (a few questions) or the AI assistant (describe your goal), then come here to understand and fine-tune the result. Umbra also reads and writes the Solar Eclipse Maestro .txt format, so existing scripts import directly.

The basics

Contacts & timing

Every shot is anchored to a contact, with a sign and an offset:

ContactMeaning
C1First contact, the partial phase begins.
C2Second contact, totality begins (the diamond ring).
MAXMaximum eclipse (mid-totality).
C3Third contact, totality ends.
C4Fourth contact, the eclipse ends.

The sign is - (before the contact) or + (after). The offset is MM:SS.s (minutes:seconds.tenths). So C2,-,00:08.0 means 8 seconds before totality, and MAX,+,00:02.5 means 2.5 seconds after maximum. For an offset of an hour or more, add an hours field: HH:MM:SS.s (so one hour is 01:00:00.0, not 01:00.0).

Other anchors: sunrise, sunset, and wall-clock time

You're not limited to the contacts. Any of these can stand in for the contact in the reference field, with the same sign + offset:

AnchorMeaning
L HH:MM[:SS]Local clock time at your eclipse site (the location you set, in its time zone), e.g. L 13:32. The wall-clock you almost always want: the time on a watch where you're standing. A bare time with no letter (13:32) also means local.
A HH:MM[:SS]Absolute UTC time, for anyone who plans in universal time, e.g. A 18:32. (Matches Solar Eclipse Maestro's A designator.)
SUNRISELocal sunrise at your site on the eclipse date, e.g. SUNRISE,+,30:00.0 = 30 min after sunrise.
SUNSETLocal sunset at your site, e.g. SUNSET,-,01:00:00.0 = an hour before sunset (SUNSET,-,01:00.0 would be one minute before).
LASTThe previous timed item, e.g. LAST,+,00:05.0 = 5 s after the last shot.

Note on wall-clock: L is the time zone of your chosen eclipse location, not your computer's clock and not UTC, and it's the default if you give no letter. So an L script reads naturally for wherever the eclipse is, regardless of where you built it. A is UTC if you prefer that. Umbra resolves every anchor to the real moment for your site, so sunrise-, sunset-, and clock-anchored scripts all stay correct. (The time goes in the same field as the letter, separated by a space: TAKEPIC,L 13:32,+,00:00.0,….)

TAKEPIC: fire a frame

The workhorse. One line fires one frame on one camera, with full exposure settings:

TAKEPIC,C2,-,00:08.0,CAM1,1/4000,8.0,200,0.000,RAW,None,N,Diamond ring
FieldWhat it is
TAKEPICThe command.
C2Reference anchor: a contact (C1–C4), a magnitude trigger (below), SUNRISE / SUNSET, LAST, or an absolute time (L local / A UTC).
-Sign: - before / + after the contact.
00:08.0Offset from the contact, MM:SS.s.
CAM1Camera name: the unique name you give a body in the Cameras panel. Umbra links it to that camera's serial number, so the same name always targets the same physical body (even after a reconnect). This must match a connected camera's name, or rename a body to match.
1/4000Shutter: a fraction like 1/2000 or decimal seconds like 1.5. Leave it blank (or write auto) to shoot aperture-priority and let the body meter the shutter.
8.0Aperture (f-number). Umbra sets this on the body before the frame. Leave it blank (or write auto) to shoot shutter-priority and let the body meter the aperture.
200ISO. Set on the body before the frame. Leave it blank (or write auto) for Auto ISO (set Auto ISO and your ceiling on the camera; Umbra won't overwrite it).
0.000Exposure compensation, in stops (e.g. -1.0, +0.667). Applied to the body before the frame; use 0.000 for none. Most useful paired with aperture-priority or Auto ISO.
RAWFile format. Not controlled yet. Your camera shoots in whatever RAW/JPEG mode it's set to; Umbra doesn't change it (RAW is the right setting for an eclipse). Want Umbra to set the format? Reach out.
NoneLegacy Solar-Eclipse-Maestro column (filter / mirror-lockup). Umbra keeps it for compatibility and ignores it; leave it as the examples show.
NIncrement flag (Solar Eclipse Maestro compatible). Controls whether Umbra re-sends the exposure to the body before this frame. Y or blank = increment: only send the settings that actually changed since the last frame (the fast path; same-exposure runs and shutter-only brackets fire quicker). N = send everything this frame even if unchanged, a deliberate full re-assert (slower, useful as a belt-and-suspenders guarantee of a known state).
Diamond ringA comment/label for this frame (shown on the timeline and in logs).

Each camera fires the lines that carry its name, so several cameras run in parallel from one script. Keep at least the body's safe gap between two frames on the same camera (the Wizard's Spacing control sets a sustainable default), and never let one exposure overlap the next on that body.

Auto modes and your camera's dial. When you leave a field blank, Umbra simply doesn't write it and lets the camera choose. For that to meter correctly, set the body's mode dial to match: Av / A (aperture-priority) for a blank shutter, Tv / S (shutter-priority) for a blank aperture, and turn on the body's Auto ISO for a blank ISO. For totality itself, full manual (every field set) is still the safest choice; the auto modes shine for partials, where the light is changing.

Partial-phase loops: FOR (VAR) and magnitude triggers

To shoot the long partial phases, you don't list hundreds of lines. A loop steps a variable and fires a frame each step, anchored to eclipse magnitude (percent covered) rather than a contact:

# A frame every 0.5% magnitude through ingress (C1 → C2)
FOR,(VAR),0.5,0.5,99.5
TAKEPIC,MAGPRE (VAR),+,00:00.0,CAM1,1/500,8.0,100,0.000,RAW,None,N,Partial ingress
ENDFOR

PLAY: spoken cues

Speak a countdown or reminder out loud at a contact-relative moment, so you can keep your eyes on the sky:

PLAY,C2,-,00:00:20.0,Filters_Off.wav, , , , , , , ,Remove filters now

The empty middle columns are placeholders (legacy format). Today Umbra speaks the cue with your chosen text-to-speech voice: it reads the comment if present, otherwise it turns the filename into words (Filters_Off.wav → "Filters Off"). It does not yet play the actual .wav file, that's a planned option. Pick the voice in Settings → Voice Cues. The Wizard adds a standard set (two minutes, thirty seconds, filters off, totality, fifteen seconds left, filters on).

Solar Eclipse Maestro compatibility

Umbra reads the Solar Eclipse Maestro .txt format, so your existing scripts load and run. Beyond TAKEPIC, these SEM commands are understood:

CommandWhat Umbra does
TAKEBSTBurst: expands to N single-frame captures (the count is the exposure-comp column, e.g. …,200,10,… = 10). This is a software burst Umbra paces itself, independent of the camera's drive dial, so leave the dial on Single (see below).
RAMPUP / RAMPDN / RAMPSUDExposure ramp: N frames stepping the shutter by the EV in the two trailing columns (up, down, or up-then-down).
TAKEBKT + BKTDATABracket: expands using the most recent BKTDATA,<count>,<EV>,<pattern>.
SETEXPRecognized as set-exposure-only; it fires no frame (Umbra sets exposure per shot anyway).
LVSTART / LVSTOP / CHGCSSLRecognized and accepted silently (live-view / drive-speed aren't simulated).

References U1–U4 map to C1–C4. A reference Umbra doesn't model yet just skips that line with a warning, so the rest of the script still loads. If a command you rely on isn't covered, tell me.

Keep the camera's drive dial on Single. Umbra fires one frame per script line and paces bursts itself, so it never needs a continuous/burst drive mode. On a burst dial some bodies (Sony especially, which has no single-frame command over USB) spray a whole burst from one fire and can wedge writing to the card in the middle of totality. Umbra checks the dial at detect and warns you, but Single is the setting you want. Want a lot of frames through totality? Tighten the spacing between TAKEPIC lines, that gives you density without the buffer-flood risk.

Advanced (rarely needed)

A complete example

# Partial ingress, a frame every 0.5% magnitude
FOR,(VAR),0.5,0.5,99.5
TAKEPIC,MAGPRE (VAR),+,00:00.0,CAM1,1/500,8.0,100,0.000,RAW,None,N,Partial ingress
ENDFOR

# Voice cues into totality
PLAY,C2,-,00:00:20.0,Filters_Off.wav, , , , , , , ,Remove filters now
PLAY,C2,+,00:00:02.0,Totality.wav, , , , , , , ,Totality

# Diamond ring + beads
TAKEPIC,C2,-,00:03.0,CAM1,1/4000,8.0,200,0.000,RAW,None,N,Diamond ring
TAKEPIC,C2,-,00:01.0,CAM1,1/2000,8.0,200,0.000,RAW,None,N,Baily's beads

# Corona bracket around maximum
TAKEPIC,MAX,+,00:00.0,CAM1,1/1000,8.0,200,0.000,RAW,None,N,Inner corona
TAKEPIC,MAX,+,00:01.0,CAM1,1/250,8.0,200,0.000,RAW,None,N,Mid corona
TAKEPIC,MAX,+,00:02.0,CAM1,1/30,8.0,200,0.000,RAW,None,N,Outer corona

# Exit diamond ring
TAKEPIC,C3,+,00:02.0,CAM1,1/2000,8.0,200,0.000,RAW,None,N,Exit diamond ring
Tip: after editing, press Play in Simulated timing to watch the whole sequence fire on a timeline before you ever point a camera at the sky, and run the Simulation Analyzer against a test card to confirm every frame landed. New to the app? Start with the getting-started guide.