Tesla Light Show is an official open-source content repository and validation toolkit from Tesla Motors. It enables owners and creators to design, validate, and deploy custom light shows on Tesla vehicles. See the User Guide for day-to-day usage; this guide covers architecture, the FSEQ format specification, validator internals, and contributor guidance.
1. Architecture Overview
This repository is a content distribution repository, not a runtime service. There is no server, no API, and no daemon process.
Repository components:
validator.py — FSEQ validation tool (Python 3.7+, stdlib only)
validator-windows.exe — Pre-compiled Windows binary
validator-macos.zip — Pre-compiled macOS binary
xlights/
tesla_xlights_show_folder.zip — xLights project: standard single-car layout
tesla_xlights_cross_vehicle_folder.zip — xLights project: multi-car coordination layout
examples/
lightshow_example_1_elevator_music.zip (1-car)
lightshow_example_2_*.zip (1-car)
lightshow_example_3_The_Arrival_5_Car/ (5-car, MP3 audio)
lightshow_example_4_Ready_for_Assault_8_Car/ (8-car, WAV audio)
lightshow_example_5_Cyber_Symphony_4_Car/ (4-car, WAV audio)
lightshow_example_6_*.zip (1-car)
lightshow_example_7_*.zip (1-car)
cross-vehicle-shows/
README.md — Multi-car setup guide
images/ — Screenshots used in documentation
Note
All runtime complexity lives off-repository: in the vehicle firmware, in xLights (third-party), and on the USB drive. This repository's software surface is exactly one Python file (
validator.py, 48 lines) plus pre-compiled binaries built from it.
Technology Stack
| Component | Technology | Notes |
|---|---|---|
| Validator | Python 3.7+, stdlib only | dataclasses, struct, sys, datetime |
| Sequence format | FSEQ v2.0 / v2.2 | Binary; produced by xLights |
| Audio formats | MP3, WAV | Loaded from USB alongside .fseq |
| Sequencing tool | xLights (third-party) | Produces .fseq and .xsq files |
| Delivery medium | USB FAT32 drive | LightShow/ folder at root |
Data Flow
Creator:
xLights (Tesla show folder project)
→ lightshow.fseq + lightshow.mp3 / .wav
→ validator.py → pass / ValidationError
→ USB LightShow/ folder
→ Tesla vehicle reads and plays show
2. System Requirements
| Item | Requirement |
|---|---|
| Python | 3.7 or later |
| Platform (Python) | Windows, macOS, Linux |
| Platform (pre-built) | Windows (validator-windows.exe), macOS (validator-macos.zip) |
| xLights | Any version producing FSEQ v2.0 or v2.2 uncompressed output |
| USB | FAT32, any capacity sufficient for .fseq + audio |
| Dependencies | None (standard library only) |
3. Configuration Reference
FSEQ File Format Requirements
The validator reads a fixed-length binary header. All checks are against this header:
| Byte Offset | Size | Struct Format | Field | Required Value | Error if Violated |
|---|---|---|---|---|---|
| 0 | 4 bytes | bytes |
magic | b'PSEQ' |
Unknown file format, expected FSEQ v2.0 |
| 4 | 2 bytes | <H |
start | ≥ 24 | Unknown file format, expected FSEQ v2.0 |
| 6 | 1 byte | <B |
minor | 0 or 2 | Warning only |
| 7 | 1 byte | <B |
major | 2 | Warning only |
| 10 | 4 bytes | <I |
channel_count | 48 or 200 | Expected 48 or 200 channels, got {N} |
| 14 | 4 bytes | <I |
frame_count | ≥ 1 | Unknown file format, expected FSEQ v2.0 |
| 18 | 1 byte | <B |
step_time | ≥ 15 | Unknown file format, expected FSEQ v2.0 |
| 20 | 1 byte | <B |
compression_type | 0 | Expected file format to be V2 Uncompressed |
Duration is computed as (frame_count * step_time / 1000) seconds and must be ≤ 14400 (4 hours).
Important
The FSEQ version check (bytes 6–7) produces a warning message only — it does not cause
sys.exit(1). A file with an unrecognized version will pass validation and can be loaded on the vehicle for testing. Only confirmed incompatibility warrants blocking.
Channel Count by Vehicle
| Channel Count | Vehicle |
|---|---|
| 48 | Model S, Model 3, Model X, Model Y |
| 200 | Cybertruck |
The specific channel-to-light-zone mapping is defined in the xLights show folder projects, not in validator.py. To inspect or modify the mapping, open the relevant xLights project from xlights/.
USB Directory Structure
USB root/
LightShow/
lightshow.fseq (required)
lightshow.mp3 (optional — audio)
lightshow.wav (optional — audio, alternative to .mp3)
The multi-car example structure mirrors this per-car:
lightshow_example_3_The_Arrival_5_Car/
Car #1/
LightShow/
lightshow.fseq
lightshow.mp3
lightshow.xsq (xLights project — not required on USB, reference only)
Car #2/
LightShow/
...
4. Deployment
Single-Car Deployment Checklist
- [ ] Create sequence in xLights using
tesla_xlights_show_folder.zipproject - [ ] Export as FSEQ (uncompressed, correct channel count for your vehicle)
- [ ] Run
validator.py— confirm no errors - [ ] Format USB drive as FAT32
- [ ] Create
LightShow/at USB root - [ ] Copy
lightshow.fseq(and optional audio) toLightShow/ - [ ] Insert USB into vehicle
- [ ] Test show from vehicle UI
Multi-Car Deployment
Each car requires its own USB drive with that car's sequence:
- Open the multi-car xLights project from
xlights/tesla_xlights_cross_vehicle_folder.zip. - Export a separate
.fseqfor each car's channel assignment. - Validate each
.fseqindividually. - Prepare one USB per car, each with its own
LightShow/lightshow.fseq. - Load all USBs simultaneously; trigger all shows at the same moment.
Note
The
.xsqfiles present in multi-car examples (e.g. example 3) are xLights project files included for reference and remixing. They are not read by the vehicle — only.fseqand audio files are required on the USB drive.
5. Operations
Validator CLI Reference
# Validate by path argument
python3 validator.py lightshow.fseq
# Interactive mode (prompts for drag-and-drop)
python3 validator.py
Successful output:
Found {frame_count} frames, step time of {step_time} ms for a total duration of {H:MM:SS}.
Exit codes:
| Exit Code | Meaning |
|---|---|
0 |
Validation passed (with or without version warning) |
1 |
ValidationError raised — file does not meet requirements |
Tip
Interactive mode strips surrounding double-quotes from the input path (Windows drag-and-drop behavior) and leading/trailing spaces (macOS drag-and-drop behavior). On Linux, type or paste the path manually when prompted.
Binary Maintenance
When validator.py logic changes, the pre-compiled binaries must be rebuilt:
- Update
validator.py. - Rebuild
validator-windows.exe(e.g., via PyInstaller on Windows). - Rebuild
validator-macos.zip(e.g., via PyInstaller on macOS). - Commit all three changes together.
Warning
The pre-compiled binaries can silently diverge from
validator.pyif only the Python source is updated. A user on Windows runningvalidator-windows.exewould be validating against the old logic. Always rebuild binaries in the same commit as validator logic changes.
6. Security
validator.py opens the provided path in read-only binary mode (open(file_path, "rb")). It reads at most the first ~21 bytes of the file header and makes no network calls, writes no files, and spawns no subprocesses.
Caution
The script does not sanitize the file path provided by the user. A path like
../../../../etc/passwdwill cause the script to open that file in read-only binary mode. Because the validator expects a binary FSEQ header at offset 0, it will immediately fail withUnknown file format, expected FSEQ v2.0and exit. No data is modified, but the file IS opened. For any automation pipeline that accepts paths from untrusted external sources, validate and canonicalize the path before passing it to the validator.
7. Troubleshooting
Validator Passes But Car Does Not Play the Show
Cause: FSEQ version mismatch beyond the 2.0/2.2 validated range, or firmware incompatibility.
Solution:
- Check for the version warning in validator output.
- If a version warning was printed, download an older xLights release that produces v2.0:
https://github.com/smeighan/xLights/releases - Re-export, re-validate, and re-test.
Warning
A validator pass guarantees the file meets the format constraints the validator checks. It does not guarantee firmware compatibility for FSEQ versions outside the 2.0/2.2 validated set.
Pre-Compiled Binary and Python Source Produce Different Results
Cause: The binaries were compiled from an older version of validator.py.
Solution:
- Check the channel count acceptance logic in
validator.py(line:if channel_count != 48 and channel_count != 200). - Rebuild the binary from the current source.
Note
GitHub issue #85 described exactly this situation — the pre-compiled binary expected 48 channels only, while the Python source had already been updated to accept 200. Always use
validator.pydirectly when in doubt about binary freshness.
8. Developer Internals
Module Reference — validator.py
The entire software component of this repository. 48 lines, Python 3.7+, stdlib only.
Classes
| Class | Base | Fields | Purpose |
|---|---|---|---|
ValidationError |
Exception |
— | Raised on any FSEQ constraint violation |
ValidationResults |
dataclasses.dataclass |
frame_count: int, step_time: int, duration_s: int |
Return value from validate() |
Functions
| Function | Signature | Returns | Raises |
|---|---|---|---|
validate |
validate(file) -> ValidationResults |
ValidationResults on success |
ValidationError on any constraint violation |
validate() — Detailed Read Sequence
magic = file.read(4) # offset 0: magic bytes
start, minor, major = struct.unpack("<HBB", file.read(4)) # offset 4-7
file.seek(10)
channel_count, frame_count, step_time = struct.unpack("<IIB", file.read(9)) # offset 10-18
file.seek(20)
compression_type, = struct.unpack("<B", file.read(1)) # offset 20
Bytes 8–9 (offsets skipped by seek(10)) and bytes 19 (skipped by seek(20)) are present in the FSEQ v2.0 header but are not checked by this validator. These correspond to the sequence UUID and related fields in the FSEQ specification.
Note
The
duration_sfield inValidationResultsis typed asintin the dataclass definition but receives the result offrame_count * step_time / 1000, which is afloatin Python 3. Thetimedeltacall in the error message handles this correctly; the field nameduration_simplies seconds.
Main Block
The __main__ block:
- Reads
sys.argv[1]if provided; otherwise callsinput()for drag-and-drop. - Strips
"surrounding quotes (Windows drag-and-drop adds these). - Strips leading/trailing spaces (macOS drag-and-drop adds these).
- Opens file in binary read mode.
- Calls
validate(file). - On success: prints
Found {frame_count} frames, step time of {step_time} ms for a total duration of {timedelta}. - On
ValidationError: prints the error message, callsinput("Press Enter to exit..."), exits with code 1. - On success: calls
input("Press Enter to exit...")before returning.
The input("Press Enter to exit...") pattern keeps the terminal window open after double-clicking the script or compiled binary on Windows/macOS, so users can read the result.
Code Patterns and Conventions
| Pattern | Description |
|---|---|
| No external dependencies | validator.py imports only stdlib modules. Users should never need pip install. |
| Interactive fallback | No-argument invocation triggers input() for drag-and-drop — usable by non-technical users. |
| Fail-fast validation | Checks are ordered: format first, then channel count, then duration. The first violation raises immediately. |
| Binary-mode file reads | open(..., "rb") — safe for all OS line-ending handling, required for binary FSEQ parsing. |
FSEQ Format Background
FSEQ (Falcon SEQuence) is a binary format originating from the Falcon Player project for holiday light sequencing. xLights produces FSEQ files compatible with Falcon Player. Tesla's subset restriction — exactly 48 or 200 channels, no compression, v2.0 or v2.2 — is enforced purely by validator.py. The format itself supports many more channel counts and compression options.
Repository Structure Deep Dive
teslamotors/light-show @ 9f94951
│
├── validator.py Core validation tool (48 lines)
├── validator-windows.exe Pre-compiled binary (Windows)
├── validator-macos.zip Pre-compiled binary (macOS)
│
├── xlights/
│ ├── tesla_xlights_show_folder.zip Single-car channel layout
│ └── tesla_xlights_cross_vehicle_folder.zip Multi-car channel layout
│
├── cross-vehicle-shows/
│ └── README.md Car positioning + channel docs
│
├── examples/
│ ├── lightshow_example_1_elevator_music.zip (1-car, ZIP)
│ ├── lightshow_example_2_*.zip (1-car, ZIP)
│ ├── lightshow_example_3_The_Arrival_5_Car/ (5-car folder)
│ │ ├── Car #1/LightShow/{fseq, mp3, xsq}
│ │ └── Car #2..#5/LightShow/{fseq, mp3, xsq}
│ ├── lightshow_example_4_Ready_for_Assault_8_Car/ (8-car folder)
│ │ └── Car #1..#8/LightShow/{fseq, wav}
│ ├── lightshow_example_5_Cyber_Symphony_4_Car/ (4-car folder)
│ │ └── Car #1..#4/LightShow/{fseq, wav}
│ ├── lightshow_example_6_*.zip (1-car, ZIP)
│ └── lightshow_example_7_*.zip (1-car, ZIP)
│
└── images/ ~50 screenshots for documentation
Testing
No automated test suite is included. Manual validation testing:
| Test Case | Expected Result |
|---|---|
Known-good 48-channel .fseq |
Frame count and duration printed; exit 0 |
Known-good 200-channel .fseq |
Frame count and duration printed; exit 0 |
| Wrong channel count | Expected 48 or 200 channels, got {N}; exit 1 |
| Compressed FSEQ | Expected file format to be V2 Uncompressed; exit 1 |
| Non-FSEQ file | Unknown file format, expected FSEQ v2.0; exit 1 |
| Duration > 4 hours | Expected total duration to be less than 4 hours, got {duration}; exit 1 |
| FSEQ v2.2 file | Warning printed; frame count and duration printed; exit 0 |
Contributing
The repository accepts GitHub pull requests. Key contribution areas:
Extending channel support (issue #141):
- Update the channel count check in
validator.py:if channel_count != 48 and channel_count != 200→ expand to additional supported values. - Create or update xLights show folder project(s) with the new channel layout.
- Rebuild pre-compiled binaries for Windows and macOS.
- Add or update example shows demonstrating the new channels.
Adding new example shows:
- Follow the folder structure in examples 3–5 for multi-car (per-car
LightShow/folder withlightshow.fseq+ audio). - Validate all
.fseqfiles before submitting. - Include the
.xsqsource file for remixability.