No description
Find a file
Your Name 1ae4251a34 fix: four real defects in the party plumbing
Leaving a project never closed its socket. That was untidy before; with
presence it means peers go on seeing you viewing something you walked away
from, and the old project's deltas land in the next one's db while it loads.
::nav-list, ::nav-create and ::open-project now drop it.

A parked move belongs to the party it came from. Leaving one — or the sender
leaving it — left the park behind, so closing a form afterwards would drag you
back to people you were no longer with. Changing party drops it, and a replay
from someone who is no longer a mate drops it too.

Nav is the only message that steers another browser, and it arrives relayed
from whatever a peer chose to send. A non-integer playhead reaching
scene/assert-frame would have thrown inside the event loop and taken the
editor down; a stack naming a clip would have dropped you into a context you
can't stand in. Validate the shape up front: root-first, timelines all the way
down, a real frame — and ignore what fails rather than parking it forever.

A refused .play() (autoplay policy, in a tab with no interaction yet) left the
echo flag set, swallowing the next genuine play we should have broadcast. The
effect now reports the refusal, which both clears the flag and keeps
:playing? honest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 16:30:06 -04:00
scenes feat: who's viewing, and ad-hoc parties that watch together 2026-09-17 16:21:55 -04:00
server feat: production deploy (Fly + R2) + frame controls and picker glow 2026-06-30 00:56:09 -04:00
tl fix: four real defects in the party plumbing 2026-09-17 16:30:06 -04:00
.dockerignore transclusion fixes and other things by chat 2026-07-06 23:48:01 -04:00
.gitignore feat: production deploy (Fly + R2) + frame controls and picker glow 2026-06-30 00:56:09 -04:00
DEPLOY.md feat: production deploy (Fly + R2) + frame controls and picker glow 2026-06-30 00:56:09 -04:00
Dockerfile feat: production deploy (Fly + R2) + frame controls and picker glow 2026-06-30 00:56:09 -04:00
fly.toml fix: thumbnail parser overflow, autostop-killed jobs, unified playhead 2026-06-30 09:48:08 -04:00
manage.py Add Django backend: users, admin, OTIO + scene persistence 2026-06-28 23:45:49 -04:00
README.md feat: timeline links, network error handling, Tailscale access, mobile fixes 2026-06-29 19:24:40 -04:00
requirements.txt feat: production deploy (Fly + R2) + frame controls and picker glow 2026-06-30 00:56:09 -04:00

scene_analysis

  • tl/ — the lumet frontend (ClojureScript / reagent / re-frame). See tl/.
  • Django backend (this folder) — users, admin, and persistence of OTIO + the timeline scene.

Backend

The backend stores one Project per editing session: the uploaded OTIO source file, the playback fps, and the live scene (the {:tracks :groups} mark-group map the frontend keeps in app-db) as a JSON dump.

Run

python -m venv .venv && .venv/bin/pip install -r requirements.txt
.venv/bin/python manage.py migrate
DJANGO_SUPERUSER_PASSWORD=admin .venv/bin/python manage.py createsuperuser --noinput --username admin --email admin@example.com
.venv/bin/python manage.py seed_demo          # demo project from tl/.../one_two_three.otio
.venv/bin/python manage.py runserver 0.0.0.0:9001   # 0.0.0.0 so it's reachable over Tailscale/LAN

Admin: http://127.0.0.1:9001/admin/ (admin / admin). Upload OTIO and inspect the scene JSON there.

API (session auth; 401 if not logged in)

Method Path Purpose
GET /api/projects/ the current user's projects
GET /api/projects/<id>/scene/ {fps, scene}
PUT /api/projects/<id>/scene/ replace scene and/or fps (JSON body)
GET /api/projects/<id>/otio/ serve the uploaded OTIO file
GET /api/projects/<id>/revisions/ save history (who / when / summary)

Attribution

Annotations are the authored unit, so that's what's attributed — and the server is the authority (client-sent stamps are ignored, so authorship can't be forged). On each scene PUT the server diffs incoming annotation groups against the stored ones and stamps createdBy/editedBy (+ timestamps) from request.user; it also writes a Revision (user, time, +N ~N −N summary, snapshot of the annotation layer). A project is editable by its owner and any collaborators (managed in the admin), so different users get distinct stamps.

The frontend currently loads /one_two_three.otio and persists annotations to localStorage; pointing it at /api/projects/<id>/otio/ and the scene endpoints is the next wiring step (CORS/credentials needed across the dev ports).