diff --git a/CHANGELOG.md b/CHANGELOG.md index 1569867..ec02070 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,25 @@ All notable changes to capcut-cli are documented here. The format follows [Keep ## [Unreleased] +## [0.29.0] — 2026-10-09 + +### Added + +- `caption --words ` builds captions from word timings produced by an external aligner, so Whisper does not have to be installed. The format is detected automatically: Whisper / whisper.cpp `segments[].words[]`, WhisperX `word_segments[]`, or a plain `{word|text|char, start, end}` array with times in seconds, `start_ms`/`end_ms` or `start_time`/`end_time` (per-character forced-aligner output). The result reports `words_format`, `words_skipped` and `source_words`. Entries without timing are skipped; entries that end before they start or go back in time are refused with `refused [words-invalid]` naming the entry. Grouping, CJK joining without spaces, `--script`, `--karaoke` and `--word-reveal` behave exactly as with Whisper words. `--words` cannot be combined with `--audio`, `--from-segment`, `--audio-stream`, `--ffmpeg-cmd` or `--whisper-*`. +- `batch --plan < ops.jsonl` validates the operations under dry-run without touching the draft and writes a reviewable plan: `project`, `draft_sha256`, the normalized `operations`, `operations_sha256` (over key-sorted JSON) and a per-operation `preview`. `batch --apply-plan ` reads no stdin and applies the plan through the normal transactional batch. It refuses with `refused [plan-draft-changed]` when the draft changed since the plan was written, `refused [plan-tampered]` when the operations no longer match their hash, and `refused [plan-project-mismatch]` when the plan names another project. Without `--continue-on-error` a failing operation writes no plan. +- `render` (including `--dry-run`) reports a `fidelity` census of what the proxy leaves out compared with the app: `faithful`, `expected_duration_us`, the `checked` categories, and per dropped category a count, up to 20 segment ids and a hint (missing media, closed main-track gaps, uncomposited overlay tracks, unburned text, stickers, transitions, effects, filters, masks, keyframes, text/video animations, blend modes, chroma key, matting). `render --strict` refuses with `refused [render-unfaithful]` before anything is written. +- After a real render, `render` probes the written file with ffprobe (`--ffprobe-cmd` selects the binary) and reports `verification`: `{ verified, duration_us, expected_duration_us, drift_us, tolerance_us, within_tolerance }`, with a tolerance of one frame at the render fps. When ffprobe is missing or cannot read the file it reports `verified: false` with a reason. `render --verify` exits non-zero on drift beyond tolerance or an unverifiable file; the file stays on disk and the JSON result is still printed. +- `tts --lexicon ` applies pronunciation rules (`{"rules":[{"text","say","case_sensitive"?}]}` or a bare array) to the text handed to the TTS engine only: longest match first, at word boundaries for rule edges that are word characters (`SQL` never fires inside `MySQLite`; CJK rules match anywhere). Malformed lexicons refuse with `refused [lexicon-invalid]`, and equal-length rules that say different things at the same position refuse with `refused [lexicon-ambiguous]`, both before any engine runs. The result reports `lexicon: { rules, applied, spoken_text }` with offsets in UTF-16 code units into the trimmed text. Works with `--text` and `--text-file`. +- `lint` reports `segment-overlap` (error) when two segments on the same non-text track (video, audio, sticker, effect, filter …) overlap, naming the track, both segment ids and the overlap in µs. `lint --fix` repairs overlaps of at most one frame at the draft's fps (the independent-rounding overlap) by ending the earlier segment where the next begins, keeping its source duration in proportion to speed. Wider overlaps are reported, not fixed. Text tracks keep `caption-overlap`. +- `lint` reports `segment-offscreen` (warning) for video, photo, sticker and text segments that cannot be seen: the clip's box lies entirely outside the canvas (material size fitted into `canvas_config`, rotation allowed for), a scale axis is 0, or opacity is 0. Segments whose position, scale or alpha is keyframed are not judged on that property. No `--fix`. +- Every undo-history snapshot now records what made it: `.capcut-cli-history/.journal.jsonl` gets `{ index, time, command, argv, before_sha256, after_sha256 }` per write (library callers record `command: null`), trimmed together with the snapshots. `restore --list` shows `command`, `argv` and `time` per step; older snapshots without a journal line list with nulls. A torn or unreadable journal never breaks a write or a restore. +- Whisper-free caption routes are documented in `docs/quickstart.zh-CN.md` (不装 Whisper 的字幕路线) and `examples/short-video-narration.md`: the app's own auto captions followed by `restyle` / `export-srt`, `import-srt`, and `caption --words`. + +### Changed + +- `doctor`'s Whisper hint names `caption --words` and `import-srt` as routes that work without Whisper. The check's status is unchanged. +- `lint --frame-grid --fix` derives repaired source durations through the same helper as the new overlap repair: at speed 1 nothing changes; on clips at other speeds whose source duration matched target × speed (within 1%), the source duration now follows the snapped target duration instead of being left as it was. + ## [0.28.0] — 2026-10-03 ### Added diff --git a/README.md b/README.md index 5350520..b47fb16 100644 --- a/README.md +++ b/README.md @@ -105,9 +105,10 @@ The host reads a draft and passes its JSON as tool input. The component itself h ## Release notes +> **New in v0.29.0:** captions from any aligner's word timings without Whisper (`caption --words`); reviewed batch plans bound to the draft (`batch --plan` / `--apply-plan`); a render fidelity census and output-duration check (`render --strict` / `--verify`); TTS pronunciation lexicons (`tts --lexicon`); `segment-overlap` and `segment-offscreen` lint checks; and `restore --list` naming the command behind each step. Full details in the [changelog](./CHANGELOG.md). + > **New in v0.28.0:** opt-in active-timeline selection; compilation into empty app-created projects; compact command discovery and selection by name for agents; Windows command-path quoting fixed in Python client v0.1.3; and Python client CI on Linux, macOS, and Windows. Full details in the [changelog](./CHANGELOG.md). -> **New in v0.27.0:** content-safe media replacement; automatic import registration after replacement and relink; recursive, ambiguity-safe relinking; exact fractional-second compile boundaries; operation preflight and failed-build cleanup; payload-bound queue IDs; canonical project locks; bounded queue results; and local OTIO file/relative references. Full details in the [changelog](./CHANGELOG.md). For an existing nested project, use `capcut diagnose --active-timeline` to inspect the selected document before editing. The opt-in follows the pointer on unverified builds and refuses invalid or conflicting selected documents; it does not bypass write guards. diff --git a/README.zh-CN.md b/README.zh-CN.md index ec02a4d..343fb82 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -82,9 +82,10 @@ Claude Code 也可以把它作为插件加载: ## 发布说明 +> **v0.29.0 新增:** 用任意对齐工具的逐字/逐词时间戳生成字幕,无需安装 Whisper(`caption --words`);与草稿哈希绑定、可先审后执行的批量计划(`batch --plan` / `--apply-plan`);渲染保真度清单与输出时长校验(`render --strict` / `--verify`);TTS 发音词典(`tts --lexicon`);`segment-overlap` 与 `segment-offscreen` 两项 lint 检查;`restore --list` 显示每一步由哪条命令产生。完整说明见[更新日志](./CHANGELOG.md)。 + > **v0.28.0 新增:** 显式选择活动时间线、向应用创建的空项目编译,以及精简的命令发现索引与按命令名筛选;Python 客户端 v0.1.3 修复 Windows 命令路径的引号解析,并在 Linux、macOS、Windows 上运行客户端 CI。详见 [更新日志](./CHANGELOG.md)。 -> **v0.27.0 新增:** 按文件内容安全替换媒体;替换和重链接后自动更新媒体导入登记;递归搜索并报告同名歧义;精确处理小数秒时间边界;编译前校验操作并清理失败输出;将队列 ID 绑定到任务参数;统一项目锁;限制队列输出;以及解析 OTIO 的本地文件 URL 和相对路径。完整说明见[更新日志](./CHANGELOG.md)。 ## 使用 capcut-cli 构建 diff --git a/docs/command-reference.json b/docs/command-reference.json index 60a64aa..5c4fc61 100644 --- a/docs/command-reference.json +++ b/docs/command-reference.json @@ -1,6 +1,6 @@ { "name": "capcut-cli", - "version": "0.28.0", + "version": "0.29.0", "schema_version": 2, "description": "Edit CapCut/JianYing draft_content.json directly. JSON in, JSON out.", "global_flags": [ @@ -1405,7 +1405,7 @@ { "name": "tts", "summary": "Synthesize a voiceover from text via a local TTS command (--tts-cmd) and add it as an audio segment.", - "usage": "capcut tts [start] [duration] (--text | --text-file ) --tts-cmd