Purpose-built NLE timeline + scene compositor components for Dash 4 — frame-accurate scrubbing, draggable playhead, snapping, audio waveforms, and a hybrid DOM+Canvas preview scene with a background children slot for any Dash component.
Project description
Dash NLE Timeline
Non-linear-editor (NLE) timeline & scene compositor components for Plotly Dash.
Frame-accurate scrubbing · draggable playhead · snapping · audio waveforms · trim / split / delete · hybrid DOM + Canvas preview scene · full Dash callback interoperability.
Documentation · Discord · YouTube · GitHub
Maintained by Pip Install Python LLC.
Overview
dash-nle-timeline brings a purpose-built video-editor timeline to Plotly Dash. A
calendar/scheduler widget thinks in dates; a video editor needs an integer frame grid, a real
draggable playhead, snapping to clip edges / markers / grid, audio waveforms, and edits expressed as
data. This library is exactly that — written in TypeScript on React 18 and compiled with
dash-component-boilerplate, so everything is driven from pure Python.
- Frame-accurate timeline — integer frames are the canonical unit; seconds are derived from
fps - Full editing surface — drag to move (cross-track), drag edges to trim/resize, split at the
playhead, delete; every edit reported as a single
lastEditevent - Audio waveforms — painted from precomputed
peaks(minmax/magnitude); no audio decoding in the browser - Snapping — to clip edges, the playhead, markers, and the frame grid, with a pixel-space threshold for a constant feel at any zoom
- Playback & transport — rAF playback loop, built-in transport bar with timecode, keyboard
shortcuts, and an imperative
commandprop - Scene compositor — a hybrid DOM + Canvas preview (
DashNleScene) that renders any Dash component as its background and overlays image/video/text layers with per-layer visibility windows - Control plane / media plane split — only small JSON crosses Dash callbacks; your media stays in
a
<video>, an audio engine, or a server render, driven off the timeline's outputs
The package ships the compiled JS bundle — a normal pip install needs no Node.
Installation
pip install dash-nle-timeline
Quick Start
import dash_nle_timeline as nle
from dash import Dash, Input, Output, callback, html
app = Dash(__name__)
app.layout = html.Div([
nle.DashNleTimeline(
id="tl", fps=30, duration=300,
tracks=[
{"id": "v1", "kind": "video", "label": "V1"},
{"id": "a1", "kind": "audio", "label": "A1"},
],
clips=[
{"id": "c1", "trackId": "v1", "start": 0, "duration": 90, "label": "intro.mp4"},
{"id": "c2", "trackId": "a1", "start": 0, "duration": 220, "label": "music.wav",
"peaks": [...], "peaksFormat": "minmax"},
],
),
html.Pre(id="out"),
])
@callback(Output("out", "children"), Input("tl", "playhead"))
def show(frame):
return f"frame {frame}"
if __name__ == "__main__":
app.run(debug=True)
Edits (move / trim / resize / split / delete) persist on their own — the component applies them to
its optimistic clips state and reports each one as a single lastEdit event. Write clips back
from a callback only when you want to validate or override.
Documentation
Full documentation, with live examples, lives at the open-source documentation index maintained by Pip Install Python LLC:
📚 pip-install-python.com
You can also run the bundled demo locally:
pip install -r requirements.txt
pip install -e .
python usage.py # open http://127.0.0.1:8060
usage.py exercises the full surface: scrubbing, selection, move/trim/resize/split/delete,
waveforms from precomputed peaks, the imperative command prop, playback, and the scene preview
synced to the playhead.
Components
| Component | What it is |
|---|---|
DashNleTimeline |
Multi-track, frame-accurate NLE timeline: playhead, playback, editing, snapping, waveforms, markers, keyboard shortcuts, and an imperative command channel. |
DashNleScene |
Hybrid DOM + Canvas preview compositor: renders a background (any Dash component and/or a native XYZ tileset) plus overlay image/video/text layers at the current playhead, with a screen-space camera. |
Both load from a single bundled JS file — no extra external_scripts, CSS, or React setup.
Wire the two together with a plain callback:
@callback(Output("scene", "playhead"), Input("tl", "playhead"))
def sync(frame):
return frame
The data boundary
- Frames are canonical.
fpsandduration(in frames) define the grid;playheadis an integer frame that round-trips both ways (scrub in the browser, or set it from Python). tracksis a list of dicts —{"id", "kind": "video" | "audio" | "camera", "label", "color"}.clipsis a list of dicts —id,trackId,start,duration, plus optionalinPoint,label,color,thumbnails,locked, and (audio)peaks/peaksFormat. It is both an input and optimistic round-trip state: user edits persist without any callback.lastEdit(output) reports each user edit as one event — move, trim, resize, split, delete — so Python can validate, override, or mirror it into your own model.selectedClipIds/selectedClipIdround-trip; drive selection from Python too.command(input) is the imperative channel —play,pause,seek,splitAtPlayhead,copy,paste,duplicate,selectAll,zoomToFit, … — de-duplicated byid.
DashNleTimeline in depth
- Time —
fps,duration(frames),playhead(round-trips),playing,loop; rAF playback loop with a throttledplayheadround-trip. - View —
pixelsPerSecond(zoom),scrollX(pan);Ctrl/⌘ + wheelzooms anchored at the cursor. - Editing — drag to move (cross-track), drag edges to trim/resize,
Sto split at the playhead,Deleteto delete; snapping viasnapping/snapThreshold. - Waveforms — precomputed
peakspainted on a per-lane canvas; formatsminmax(interleaved[min0, max0, …]) andmagnitude. - Markers & keyframes —
markers({"id", "frame", "label", "color"}) on the ruler; camera-keyframe diamonds oncameratracks viacameraKeyframes. - Keyboard — the
keyboardprop (default on) toggles all shortcuts: Space, arrows (Shift = 1s),Ssplit,Delete,⌘/Ctrl + C/V/Dcopy/paste/duplicate,⌘/Ctrl + Aselect all, Home/End,+/-zoom. - Transport bar — the
controlsprop (default on): to-start / step / play-pause / step + timecode above the ruler. - Theming —
theme="dark"/"light", plusstyle/classNamepassthrough.
API reference
DashNleTimeline props (selected)
| Prop | Type | Description |
|---|---|---|
fps / duration |
int | Frame rate and total length in frames — the canonical time grid |
playhead |
int | Current frame — input and output |
playing / loop |
bool | Playback state (rAF loop inside the component) |
tracks |
list | Track dicts (video / audio / camera) |
clips |
list | Clip dicts — input and optimistic round-trip state |
lastEdit |
output | The most recent user edit as a single event |
selectedClipIds / selectedClipId |
list / str | Selection — round-trips both ways |
markers |
list | Ruler markers {"id", "frame", "label", "color"} |
cameraKeyframes |
list | Keyframe diamonds rendered on camera tracks |
snapping / snapThreshold |
bool / int | Snap to edges / playhead / markers / grid; pixel-space threshold |
pixelsPerSecond / scrollX |
number | Zoom and horizontal pan |
command |
dict | Imperative channel (seek, togglePlay, zoomToFit, …), de-duped by id |
keyboard / controls |
bool | Toggle shortcuts / the built-in transport bar |
theme / style / className |
— | Appearance and sizing |
DashNleScene props (selected)
| Prop | Type | Description |
|---|---|---|
playhead |
int | Frame to render — drive it from the timeline |
resolution |
list | Design-space [width, height] of the scene |
children |
Dash components | Background slot — a map, a plot, a video feed, anything |
tileset |
dict | Native XYZ tile background |
layers |
list | Overlay layers (image / video / text) with [start, end) visibility windows |
camera |
dict | Screen-space camera (pan / zoom over the scene) |
The full prop tables are generated into dash_nle_timeline/DashNleTimeline.py and
dash_nle_timeline/DashNleScene.py docstrings by dash-generate-components.
Development
# Install dependencies
npm install # TypeScript + webpack toolchain
pip install -r requirements.txt
# Build the JS bundle + regenerate the Python wrappers
npm run build # webpack UMD bundle + dash-generate-components → dash_nle_timeline/*.py
npm run watch # JS-only rebuild loop (when prop signatures don't change)
# Standalone smoke test
python usage.py # http://127.0.0.1:8060
# Build a distribution
python -m build
- TypeScript source of truth:
src/ts/—components/holds the two public components,internal/the subcomponents, andtime.ts/snap.ts/waveform.ts/edits.ts/tiles.tsare pure helpers. - The built bundle and generated wrappers are committed, so
pip install -e .works without npm. dash_nle_timeline/__init__.pyis hand-maintained (it registers the UMD bundle) —dash-generate-componentsdoes not regenerate it.- Keep the version in
package.jsonandpyproject.tomlin sync when cutting a release.
Requirements
- Python >= 3.8
- Dash >= 4.1
- Node.js >= 16 (for development / rebuilding the JS bundle only)
Community & support
Come build with us:
- 💬 Discord — discord.gg/WEnZR35mrK
- ▶️ YouTube — @2plotai
- 🐛 Issues — github.com/pip-install-python/dash-nle-timeline/issues
More from Pip Install Python LLC
dash-nle-timeline is one of several tools built and maintained by Pip Install Python LLC:
| Project | What it is |
|---|---|
| 📚 Pip Install Python | Open-source documentation index for the Python & Dash ecosystem |
| 🔀 PiratesBargain.com | E-commerce / digital commerce |
| 🧠 ai-agent.buzz | Infinite AI canvas |
| 🎬 2plot.media | Videography application |
License
MIT — see LICENSE. Built by Pip Install Python LLC to bring a real video-editing timeline into the Dash framework.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dash_nle_timeline-0.0.1.tar.gz.
File metadata
- Download URL: dash_nle_timeline-0.0.1.tar.gz
- Upload date:
- Size: 173.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abe016e696595d03da6e12688948a79d56a8e9d46bb24da44055f9fe3a3347da
|
|
| MD5 |
5f01eeaf3e2bd5e1f4e4dda2d92c57da
|
|
| BLAKE2b-256 |
eed3890ed339b7380a4273810014d7bd6eced7a36bde90dba43bec3ba7ecdba2
|
File details
Details for the file dash_nle_timeline-0.0.1-py3-none-any.whl.
File metadata
- Download URL: dash_nle_timeline-0.0.1-py3-none-any.whl
- Upload date:
- Size: 177.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
32606a542012bc613b24af34071f58e8b5c5ebbd583718a52104d13c83b6e455
|
|
| MD5 |
35e2061748c254b09557ca87416131a1
|
|
| BLAKE2b-256 |
1be6b115dcf703cff6e799628c0e22c8da2f7f63430437a5a9a18b80f51abbcc
|