tellers-timeline
tellers-ai/tellers-timelineOpen-source, cross-language library for reading, writing, validating, and editing a simplified subset of OTIO (OpenTimelineIO) JSON files. The core is written in Rust; bindings are available for Python, JavaScript (WASM), and Dart.
What it implements
- Timeline, Stack, Tracks — top-level structure matching the OTIO schema
- Clips — with
duration,source(MediaSource), effects, and metadata - Gaps — silence/black filler between clips
- MediaSource — URL-based media reference with
startanddurationaccessors - Effects — per-clip effect parameters (volume, position, rich text overlays)
- Metadata — arbitrary metadata, Tellers-specific data nested under the
tellers.ainamespace - IDs — optional, auto-generated (48-bit entropy, 12-char strings); can be omitted for portability
- Time values — seconds as
f64
Build and test
Requires just and a Rust toolchain. For Python bindings, also install maturin.
# Build all crates (excludes WASM and Python bindings)
just build-all
# Run all tests (Rust + Python + WASM build check)
just test-all
# Regenerate the JSON Schema from code
just regen-schema JSON Schema
The library is validated against a JSON Schema (Draft-07) generated from the Rust types. A minimal timeline looks like:
{
"OTIO_SCHEMA": "Timeline.1",
"name": "My Edit",
"tracks": {
"OTIO_SCHEMA": "Stack.1",
"children": [
{
"OTIO_SCHEMA": "Track.1",
"kind": "Video",
"children": [
{
"type": "clip",
"duration": 5.0,
"source": {
"url": "https://cdn.example.com/shot1.mp4",
"start": 0.0,
"duration": 5.0
}
},
{
"type": "gap",
"duration": 0.5
},
{
"type": "clip",
"duration": 3.2,
"source": {
"url": "https://cdn.example.com/shot2.mp4",
"start": 1.0,
"duration": 3.2
}
}
]
}
]
}
}
The full schema lives at spec/otio.schema.json in the repository and is regenerated with just regen-schema.
Bindings
Python
Built with maturin (PyO3). Run maturin develop from bindings/python to install locally.
# Install with maturin (from the bindings/python directory)
# maturin develop
from tellers_timeline import Timeline, Track, Clip, MediaSource
tl = Timeline(name="My Edit")
track = tl.add_video_track()
clip = Clip(
duration=5.0,
source=MediaSource(url="https://cdn.example.com/shot1.mp4", start=0.0, duration=5.0),
)
track.append(clip)
# Serialize to OTIO JSON
print(tl.to_json()) JavaScript (WASM)
Compiled to wasm32-unknown-unknown. Build with cargo build -p tellers-timeline-wasm --target wasm32-unknown-unknown.
// Built as a WASM module — import after running scripts/generate_api.sh
import init, { Timeline } from './tellers_timeline_wasm.js';
await init();
const tl = new Timeline("My Edit");
const track = tl.addVideoTrack();
track.appendClip({ duration: 5.0, source: { url: "https://cdn.example.com/shot1.mp4", start: 0, duration: 5.0 } });
console.log(tl.toJson()); Dart
Dart bindings are available under bindings/dart in the repository.
Track operations
- Append, insert, move, and delete items on a track
- Resize clips (trim in/out points)
- Split a clip at a given time (IDs are kept unique)
- Add and remove tracks from the stack
- Mute tracks (Python bindings)