Repository navigation
Releases: Y0lan/dj-edit
Release list
v0.3.0 — content-aware Insta360 + GUI launcher + codex round-1 fixes
Content-aware Insta360 reveals + GUI wrapper. v0.2 hardcoded yaw targets,
so reveals had a coin-flip chance of pointing at the DJ booth versus a wall.
v0.3 scores Insta360 ERP footage frame-by-frame for motion + brightness and
points camera moves at the actual content.
Added
bin/score-360.py— content-aware Insta360 yaw scoring. Samples
source frames at 1 fps in grayscale, slices into 8 horizontal yaw segments
(45° each), and emits per-segment motion + brightness scores to
sphere_score.json. Single-pipe ffmpeg → numpy, near-constant memory.lib/sphere.py:best_yaw_at— pure helper that queriessphere_score
at a given source-local time and returns the yaw with highest weighted
motion + brightness. ReturnsNoneon all-zero windows so callers fall
back to move defaults. ERP-circular smoothing pools seam-adjacent
segments so subjects straddling 337.5/22.5° aren't dropped.start_yawparameter onorbit,crowd_reveal,bpm_sync_orbit,
breakdown_drift— content-aware anchoring. Defaultstart_yaw=0
preserves v0.2 behavior byte-identically.start_yaw+ shortest-path delta ondrop_impact— a target yaw of
337.5° now whips -22.5° (the short way) instead of spinning 337.5°.- Enhanced
dj-edit-mac.commandwith launch menu (New / Re-edit recent /
Quick test / Demo / Doctor), style picker (signature / aggressive / clean),
reference picker (anyma / fisher / rinse), and a "quick test" mode that
renders only the highest-intensity drop (~3 min) before committing to a
full 30-50 min render. Recent projects saved at~/.dj-edit-recent. dj-edit score-360subcommand (placeholder shipped in v0.2.1, now backed
by real implementation).
Fixed — codex round 1 (HIGH severity)
build-edl.pywas queryingsphere_scorewith master-timeline time but
frames are source-local. Multi-Insta360 setups also always read
source_index=0. Now passessource_t=src_inand
source_path=finfo["path"]so each clip resolves to its own source at the
right time.drop_impactwhipped the long way around whentarget_yaw > 180°.
Now computes a signed shortest-path delta in [-180, 180] and animates
start_yaw + delta * progress.
Fixed — codex round 1 (MEDIUM severity)
score-360.pystderr=PIPE could deadlock on long sources where ffmpeg
emits decode warnings faster than Python reads stdout. Switched to
DEVNULLand added-nostdin -hide_banner -nostats.sphere.best_yaw_atreturned arbitrary yaw=22.5° on all-zero/black
windows. Now returnsNoneand the caller falls back to the move's
default yaw.score-360.pynow emitssource_path(project-relative) alongside
basename, so multi-source matching inbuild-edl.pyworks.
Upgrade
brew upgrade dj-edit
v0.2.1 — auto-open output folder after run + deliver — friend was lost without it
Third friend-feedback patch. He ran dj-edit run on his real footage and
texted "can't find where the final video is."
Fixed
dj-edit runanddj-edit delivernow auto-open the output folder
when done. Previously onlydj-edit quickstartdid this. Both
commands now print the location +open out/on macOS (andxdg-open
on Linux only when a display is attached, to avoid hanging headless).dj-edit score-360subcommand placeholder — v0.3+ will ship a real
implementation (content-aware Insta360 yaw scoring). v0.2.1 dispatcher
handles "script not yet installed" gracefully so therunchain can
evolve in v0.3 without breaking v0.2.x users.
Upgrade
brew upgrade dj-edit
v0.2.0 — Tier A eased moves + Tier B music-driven moves + Tier D move pools (with codex-loop hardening)
The Insta360 movement upgrade. v0.1.x reframed via static stock moves (orbit at
constant speed, dolly-zoom linear); v0.2 makes camera motion cinematic and
music-aware.
Added — Tier A: eased motion primitives
Every move (orbit, tilt_reveal, dolly_zoom, crowd_reveal) now uses
cosine ease-in-out instead of linear ramps. Two new combined-motion primitives:
counter_motion: yaw turns one direction while pitch oscillates and h_fov
breathes. Three orthogonal motions from one cheap source.dolly_with_drift: push-in plus slow yaw drift. Subject-lock effect.
Added — Tier B: music-driven moves
bpm_sync_orbit: yaw rotates exactly N bars per full turn, BPM-locked.kick_pulse_fov: h_fov pumps at BPM frequency for subliminal beat sync.drop_impact: 4-phase preset (freeze → whip → dolly-zoom → hold) for
the moment of impact.build_tension: quadratic-ease h_fov tightening into the drop.breakdown_drift: ultra-slow yaw + slow pitch tilt for breakdowns.
Added — Tier D: stochastic move pools
lib/selector.pick_move_for_event: weighted RNG pick, intensity-biased,
with 3-pick avoid-repeat window. Same set rendered twice → different cuts.presets/styles/{aggressive,clean,signature}.json: weight overrides.
aggressiveships drop_impact every drop + whip-pans dominating;cleanis
cinematic and slow;signatureis the balanced default.presets/references/{anyma,fisher,rinse}.json: artist-style packs.--style,--reference,--seedCLI flags ondj-edit edl.
Fixed — codex round 1 + 2 (CRITICAL)
TIis normalized [0,1] in sendcmd, NOT seconds. Rewrote every move's
math to useT(absolute seconds) instead of bareTI. The v0.1 expressions
like45*TImeant "45 degrees TOTAL" — not "45 deg/sec" as designed.- Commas inside sendcmd expressions break parsing (verified in ffmpeg
n8.1.1). Replaced piecewiseif(lt(x,a),b,c)with multi-line time-windowed
commands (each command on its own line, no nested if). Replacedpow(T,2)
withT*T. - Render cache only hashed EDL JSON, not cmd file contents. Tweaking a
move generator while EDL JSON stayed byte-identical → cache served stale
video. Now hashes EDL plus every referenced.cmdfile's content. _generate_move_cmdreturned a relative cmd path. Broke whenrender.sh
was invoked from a different cwd. Now returns.resolve()absolute path.target_yaw or 60.0made explicittarget_yaw=0.0impossible. Now uses
target_yaw is Nonecheck.load_pool_overridessilently fell back to defaults on--style typo.
Now warns to stderr (with the resolved file path) for missing pack files,
malformed JSON, or pack entries referencing unknown move names.- Intensity not clamped. Negative or >1 event intensities could produce
zero or negative weights in pool selection. Clamped to [0, 1].
Added — Tests + CI hardening
- 131 pytest tests (up from 41 in v0.1.x). Includes:
- 21 lib/moves invariant tests (
no-pow,no-if,no-commas,uses-T) - 14 selector pool-selection tests (weight bias, avoid-repeat, packs load)
- 60 shipped-preset hygiene tests (12 presets × 5 invariants) — this
test set automatically catches the codex round 1 regression class (where
presets weren't regenerated after a lib rewrite).
- 21 lib/moves invariant tests (
- Full quickstart
--demoend-to-end smoke verified: drop detected, set_9x16- set_16x9 + highlight + per-drop clip all produced in ~8 seconds.
Verified end-to-end
All 12 generated .cmd files render through real ffmpeg n8.1.1 sendcmd (orbit,
drop-impact, build-tension, kick-pulse-fov tested with rgbtestsrc input;
frames at t=0 and t=1s have different md5sums → motion confirmed).
Upgrade
brew upgrade dj-edit
v0.1.3 — fix quickstart --demo: bake audio into demo video + sharpen drop transient
Second friend-feedback patch. dj-edit quickstart --demo now actually completes
end-to-end with a detected drop and a rendered per-drop clip.
Fixed
demo_video.mp4had no audio track.dj-edit syncrequires camera scratch
audio to cross-correlate against the master — without it, no offsets, empty
EDL, zero clips. Fix: bake the demo audio INTO the demo video so sync resolves
trivially.- Synthesized drop didn't trigger detection. The previous demo "drop" at
t=15s was a slow volume ramp, which librosa'sonset_strengthsaw as nothing
remarkable. Fix: regeneratedemo_audio.wavwith a sharp sub-bass impact at
t=15s plus a noise impulse for the onset trigger. Analyze now finds:
build @ 7s + drop @ 15s (intensity 1.0).
Result
dj-edit quickstart --demo now produces in 8.6s:
set_9x16.mp4+set_16x9.mp4(full 30s timeline)highlight_9x16.mp4(drop reel)drops/drop_01_t00m15s_int100.mp4(timestamp + intensity in filename)drops/INDEX.txt(tracklist)
A proper smoke test of the install.
Upgrade
brew upgrade dj-edit
v0.1.2 — fix doctor false-positive + brew formula /Applications crash
First friend-feedback patch. Two real bugs hit on macOS install.
Fixed
- Brew install crash on
/Applications. The formula tried to write
dj-edit-mac.commanddirectly to/Applicationsvia Ruby'sFile.write,
which fails inside brew's install sandbox. Friend had to manually patch
the formula to skip that step. Fix: install the .command intoshare/
only;caveatsinstruct the user to copy it to/Applicationsthemselves
(one extracpline, but no install crash). - Doctor false-positive on filter detection. Friend's
dj-edit doctor
reportedloudnorm(and earlierdrawtext) as missing even though
ffmpeg -filters | grep loudnormshowed them present. Root cause: the
regex^ ?[.TS]+ +<name> +was sensitive to ffmpeg's leading-whitespace
pattern, which varies across versions/builds. Fix: parse column 2
directly with awk ($2 == filter_name). Same fix on the encoder check.
Upgrade for existing users
brew upgrade dj-edit
v0.1.1 — render cache + 41 pytest unit tests + CI matrix
Quality + resilience pass. No new user-facing features; faster re-runs and confidence in correctness.
Added
- Output-level render cache in
bin/render.sh. Keyed onsha256(canonical_edl_json).
Re-runs with the same EDL skip the encode entirely and copy from cache (<1s vs 25-40 min). - 41 pytest unit tests across
lib/treatments,lib/selector,lib/moves, and
bin/sync-cameras.robust_offset. Catches regressions in pure logic without needing
real video fixtures. - GitHub Actions CI: matrix on
ubuntu-latest+macos-latest× Python 3.11/3.12.
Runs pytest, bash/python syntax checks, anddj-edit quickstart --demosmoke test. scripts/release.shone-command release helper. Bumps version, tags, creates
GitHub release, computes tarball SHA256, updates the brew formula in the tap.
Fixed
robust_offsetinbin/sync-cameras.pynow takes optionalcam_durto filter out
clipping-at-master-end artifacts more aggressively. Caught bytest_sync_helpers.py.- Attempted a per-chunk render cache approach for mid-render resume, but reverted due to
3-5x slowdown vs monolithic (per-chunk decode setup on a 64GB source doesn't share work).
Output-level cache is the cleaner solution for the common iteration case.
Notes
- v0.2 will add: per-camera LUTs (color match), Songrec track-ID burn-in,
--style
knob that actually changes pacing, watermark + endcard. Seelexical-percolating-bee.md
in the plan archive for full backlog.
v0.1.0 — Initial public release
First public release of dj-edit.
Auto-edit DJ-set videos with audio-driven cuts. Detects drops, builds, breakdowns from a master audio recording and produces 9:16 + 16:9 outputs with beat-snapped cuts, virtual-camera reframing, and drop-impact treatments.
What works in v0.1.0
- Single-camera Sony A7-III + Tascam recorder workflow (tested on real 90+ min sets)
- Multi-feature audio analysis (librosa onset + band RMS + spectral centroid + beat_track at 128 BPM hint)
- Affine camera sync via onset-envelope cross-correlation with median-offset estimator
- Multi-aspect render (9:16 + 16:9) via one ffmpeg
filter_complexgraph - Platform auto-detect encoder:
videotoolbox(macOS) /vaapi(Linux) /libx264(fallback) - Per-drop clip extraction with timestamp + intensity in filename
- Top-6 drops highlight reel
- macOS GUI launcher (
dj-edit-mac.commandvia osascript folder pickers) dj-edit doctorhealth checkdj-edit quickstart --demosmoke test with bundled 30s synthesized fixture
Install (macOS)
```bash
brew tap Y0lan/dj-edit
brew install dj-edit
```
Then double-click `/Applications/dj-edit-mac.command` or run `dj-edit help`.
Install (Linux / from source)
```bash
git clone https://github.com/Y0lan/dj-edit.git
cd dj-edit
./setup.sh
```
Status
This is an alpha release. Multi-camera (Insta360 + DJI) path exists but is undertested. Pre-built Homebrew bottles will land in v0.1.1 once CI infra is set up — for now the brew formula builds from source (~3 min extra install time).
Built with Claude Code (Claude Opus 4.7).