Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Project persistence — .screenproj — ED.23

When the CMX 600 turned editing into a decision list, that list became the thing you filed in the can beside the negative: reopen the can, feed the list back, and you had your cut — no frame of original ever copied. ED.23 is that can. Because an EditProject is only value types — segment ranges, zoom windows, framing config, a pointer at the source — saving it is just serializing the decision list to JSON, and reopening it is parsing the JSON back.

flowchart LR
  P["EditProject\n(the decision list)"] -->|to_screenproj| J[".screenproj (JSON)"]
  J -->|from_screenproj| P2["EditProject (identical)"]
  P -.points at.-> SRC["source .mp4 (untouched)"]
  P2 -.points at.-> SRC

edit::persist is the whole format: to_screenproj / from_screenproj over serde_json, pretty-printed so the file is human-readable and diff-friendly. The round-trip is lossless and pure — proven without touching the filesystem — so save↔reload is identical by construction. On the shell side, editor_save_project writes <recording>.screenproj beside the source and editor_load_project reads it back; the Save button in the editor lives next to Export.

```admonish note title="serde_json joins edit — and it stays wasm-clean" edit was deliberately serde-only; persistence promotes serde_json from a dev-dependency to a real one. It's wasm-safe (no filesystem of its own — the file I/O lives in the native app commands), so edit remains GPU-free and wasm-clean, and the round-trip test runs in the gate with no GPU or disk. The file carries a SCHEMA_VERSION so a future format change migrates rather than mis-parses.