diff --git a/CHANGELOG.md b/CHANGELOG.md index b526920..1926c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,29 @@ All notable changes to capcut-cli are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.13.0] — 2026-07-08 + +Six features in one release — the top of the opportunity backlog, bundled. Two build on prior art from the [capcut-cli-david](https://github.com/Davidb-2107/capcut-cli-david) fork (thanks @Davidb-2107); see #36. ### Added -- `lint --fix` — auto-repair mechanically-fixable draft defects (`cue-too-long`, `caption-overlap`). Trims over-long captions to the configured cap and shortens overlapping caption pairs so each ends where the next begins. Writes atomically with a `.bak` snapshot; combine with `--dry-run` to preview without touching the draft. Non-fixable issues (`missing-material`, `missing-file`, `line-too-long`, `caption-gap-too-small`) are still reported and continue to drive the exit code. Closes #40. +- `sync-timelines [--apply] [--force-write]` — reconcile a CapCut >= 8.7 draft whose `template-2.tmp` / `draft_info.json` timeline mirror has drifted from `draft_content.json`, so CLI edits are honored by the app instead of silently ignored. `draft_content.json` is always canonical and is treated read-only. Accepts only a project directory or its `draft_content.json` (any other filename exits 1). Plan-only by default: the per-target drift report includes each mirror's mtime plus `newer_mirrors` / `canonical_stale`, and warns when `draft_content.json` is older than a drifted mirror (you would overwrite newer edits). `--apply` refuses that direction unless you add `--force-write` (exit 1), then rewrites **only** the drifted mirrors — the canonical file is never re-sorted or backed up, and in-sync mirrors are left untouched; `reconciled` / `backups` list exactly the files written. No-ops with exit 0 when all targets already agree. An unreadable (binary/encrypted) mirror is reported unreconcilable (`ok:false`, `in_sync:false`, exit 2) and stays idempotent on re-run instead of pretending success. `--apply --dry-run` reports the plan only (`would_reconcile`, `reconciled: []`). `diagnose` now recommends the plan form (with a back-up caution) instead of deferring to issue #35. Closes #39. +- `lint --fix` — auto-repair mechanically-fixable draft defects, now four codes: `cue-too-long` (trims over-long captions to the configured cap), `caption-overlap` (shortens overlapping pairs so each ends where the next begins), `line-too-long` (greedy word wrap that swaps spaces for newlines 1:1, keeping styled-range byte offsets valid; never splits words — instances the wrap cannot actually fix, i.e. space-less/CJK text and over-cap single words, are stamped `fixable:false`), and `caption-gap-too-small` (pulls the earlier caption's end back to restore the minimum gap; never moves starts, never creates a new overlap). The gap repair honors a hard floor — exported `MIN_CAPTION_DURATION_US = 100_000` (100ms) — so a shrink that would land a caption below the floor is skipped and stamped `fixable:false` for that instance instead of collapsing it. Writes atomically with a `.bak` snapshot; combine with `--dry-run` to preview. `missing-material` and `missing-file` stay report-only deliberately: the only mechanical repairs would delete user timeline content or act on host-dependent paths. Closes #40. +- `lint` — new report-only rule `unknown-effect-slug` (**info** severity, exit 0): flags effect/filter/animation resource ids in the draft that are not in the bundled enum table, surfacing them before CapCut silently drops them (the silent-failure mode reported across ecosystem tools, e.g. GuanYixuan/pyCapCut#12). Info rather than warning because store-downloaded effects on app-authored drafts are legitimate; only CLI-written stale slugs are at risk. +- `export-srt [--granularity line|word] [--format srt|vtt]` — word-level caption export. Captions created by `caption --karaoke` carry real per-word timing and export it exactly; plain captions interpolate word timing proportionally by word length (stated in `--help`). SRT + word emits one cue per word; VTT + word emits one cue per phrase with inline `` karaoke timestamps for burn-in pipelines. Defaults (`line`, `srt`) reproduce the previous output byte-identically. +- `keyframe ... --easing ` — CapCut-native easing curves, also accepted per-line (`easing` key) in `keyframe --batch` JSONL and in the `compile` spec's keyframe op. The app does not store named curve types: the UI writes `FreeCurveInOut` bezier control handles on both keyframes of the eased segment, and the emitted encodings are locked against a UI-oracle capture (prior art: capcut-cli-david). The `ken-burns` skill default changed linear → ease-out to match what the CapCut UI itself produces. +- `detect-scenes