Promote manual-URL flow to primary path; Rust-only bootstrap - #5
Open
scrumlord8 wants to merge 18 commits into
Open
Promote manual-URL flow to primary path; Rust-only bootstrap#5scrumlord8 wants to merge 18 commits into
scrumlord8 wants to merge 18 commits into
Conversation
Replace the Rust scaffold with a fully functional Python CLI that actually does what the project promises. The full pipeline is operational: - Discover trending TikTok sounds via Creative Center scraping - Generate X/Twitter viral clip search queries with engagement filters - Download sounds and clips from any yt-dlp-supported URL (TikTok, X, YouTube, etc.) - Compose real MP4 videos with normalized audio, scaled/cropped clips, and muxing - All commands output structured JSON for agent consumption Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TikTok: API-first with layered HTML fallback (__NEXT_DATA__, script scan, regex) so it survives SSR restructuring instead of breaking on a single JSON path. Twitter: execute live search via Twitter API v2 when TWITTER_BEARER_TOKEN is set, fall back to guided discovery URLs with setup instructions. Compose: add --loudness presets (viral -8, social -10, podcast -14, broadcast -23 LUFS). Default changed from -14 to -8 because this tool makes social media content, not podcasts. https://claude.ai/code/session_019gPk1X2KQ5mw6z2QCUYStU
…apper 56 tests covering: - TikTok: all 3 extraction strategies, normalize_sound field mapping, API fallback, limit enforcement - Twitter: query building, API search with/without bearer token, min_likes filtering, guided fallback - Loudness: preset values, ordering (viral > social > podcast), resolve with names/numeric values, error on unknown - CLI: command structure, --loudness option presence - FFmpeg: loudnorm filter param construction for all preset levels https://claude.ai/code/session_019gPk1X2KQ5mw6z2QCUYStU
…se-i5LUV Harden discovery modules and fix compose loudness for viral content
Complete Rust rewrite of the capcut-cli Python MVP. Every command now runs natively — single binary, no Python runtime, no pip install. Modules ported: - config.rs: paths, loudness presets (viral/social/podcast/broadcast) - output.rs: JSON envelope matching Python format exactly - deps.rs: ffmpeg detection (PATH + ~/.capcut-cli/bin), yt-dlp binary download - media/ffmpeg.rs: all 8 subprocess wrappers (normalize, trim, scale, crop, concat, mux, loop, get_duration) - media/downloader.rs: yt-dlp wrapper with cookie retry on block detection - media/compose.rs: full 5-step pipeline with loudness preset resolution - discover/tiktok.rs: API-first + 3-strategy HTML fallback (scraper + regex) - discover/twitter.rs: Twitter API v2 live search + guided fallback - library.rs: asset CRUD with JSON manifest, import/list/show/delete - cli.rs: clap subcommand tree matching Python's command structure exactly CLI parity: deps check/install, discover tiktok-sounds/x-clips, library import/list/show/delete, compose with --loudness. 6 unit tests passing. Zero warnings. Builds on Rust 1.94 edition 2024. https://claude.ai/code/session_019gPk1X2KQ5mw6z2QCUYStU
The py/ directory (1,949 lines) was the original MVP. The Rust port in src/ is a complete replacement with the same CLI interface and JSON envelope format. https://claude.ai/code/session_019gPk1X2KQ5mw6z2QCUYStU
…se-i5LUV Claude/refactor discovery compose i5 luv Ditched Python and went full Rust mode
Increases test count from 6 to 50. Covers: - CLI argument parsing for all commands (deps, discover, library, compose) - Clap validation: required args, defaults, error cases - Asset/Manifest/ComposeResult JSON serialization and round-trips - Output envelope structure (success/error, hint omission, duration) - Platform detection (TikTok, YouTube, X/Twitter, Instagram, unknown) - Asset type detection (explicit override, TikTok music auto-detect) - File matching helper (found/not-found paths) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full MVP re-write in Rust
Rewrite capcut-cli in Rust and add agent-first discovery, import, and autopilot workflows
Two phone-friendly ways to run real discovery and produce three composed
MP4s alongside their source audio and clip assets:
- .github/workflows/build-clips.yml: manual-dispatch workflow that checks
for API tokens, installs ffmpeg/yt-dlp, builds the CLI, runs discovery
and compose via scripts/build-clips.sh, and uploads a clips/ artifact.
- .devcontainer/: Rust+Python devcontainer with a post-create step that
wires yt-dlp into ~/.capcut-cli/bin and builds the release binary; pairs
with `make clips` for one-command runs inside Codespaces.
- scripts/build-clips.sh: discovers one trending sound + three ranked X
clips, imports each, composes clip_{1,2,3}.mp4, and stages the real
source references plus a manifest.json under ./clips.
- README: documents both paths and the required repo/Codespace secrets.
The CLI is Rust-only; yt-dlp itself is distributed as a standalone Linux binary by the upstream project, and 'deps install' already downloads it. Using that path keeps Python off the install surface for both the Action and the devcontainer.
Product decision: discovery depends on gated APIs (TikTok Research access, X paid-tier search) whose availability we can't guarantee. Treat "fresh input in, finished clip out" as the honest minimum viable truth and make the compose pipeline the solid thing the tool does. - README rewritten around the manual-URL flow. The Quick Start, batch guide, and command reference all center on library import + compose. The discover/autopilot commands are moved into an "Optional: API-gated discovery (experimental)" section with explicit caveats about token gating. Stale claims removed. Python references stripped. - scripts/build-clips-from-urls.sh: primary batch path. Takes one supplied sound URL plus three supplied clip URLs and produces a self-contained clips/ folder with finished MP4s, source references, and a provenance manifest. - .github/workflows/build-clips.yml: gains a mode selector; urls mode is the default, discovery mode is opt-in behind both repo secrets. - tests/e2e_url_to_clip.rs: end-to-end smoke test that exercises the full library import → compose pipeline via a yt-dlp shim, so the honest minimum viable truth is verifiable without network access. - .github/workflows/test.yml: runs cargo test --all-targets on every push so the spine stays provable in CI. - library/manifest.json plus small synthetic demo fixtures under library/sounds/assets/snd_demo001 and library/clips/clp_demo001 so compose works immediately on a fresh clone and the compose smoke test has real bytes to exercise. - src/config.rs: CAPCUT_YTDLP_PATH env override so tests can inject a yt-dlp shim. Production path unchanged. - src/media/downloader.rs: merge two duplicate #[cfg(test)] mod tests blocks that were preventing cargo test from compiling at all. - .gitignore: trimmed Python section, whitelisted the committed demo fixtures, anchored the batch-output ignore to the repo root.
- .env.example: reframe TWITTER_BEARER_TOKEN and TIKTOK_RESEARCH_ACCESS_TOKEN as optional (they only affect API-gated discovery, not the primary library import + compose flow). Note the pricing reality for the X token. Document the new CAPCUT_YTDLP_PATH test hook. - library/sounds/README.md: reflect the actual directory layout (assets/ is where imports land), mark the nested manifest.json as a legacy seed, and point readers at the authoritative library/manifest.json. - .devcontainer/post-create.sh: drop the Python mention from the header comment now that the bootstrap is entirely Rust-native.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reshape the CLI around its working spine: given a sound URL and three clip URLs, produce three composed MP4s. Discovery via TikTok/X APIs stays available but is demoted to an opt-in experimental path, since the tokens are gated (TikTok Research) or paid ($200/mo X Basic).
What's new
scripts/build-clips-from-urls.shimports sound + 3 clips, composes, and writes a provenance manifest toclips/. No tokens required.build-clips.yml) with amodeselector:urls(default) ordiscovery(opt-in, token-gated). Runnable from a phone.capcut-cli deps install. No Python anywhere in the toolchain.tests/<e2e_url_to_clip.rs>) exercises import → compose with a yt-dlp shim, so CI verifies the spine without network.snd_demo001,clp_demo001) + top-levellibrary/manifest.jsonso existing library-dependent tests pass out of the box.Agent execution options
Three ways to run it, in order of friction:
make clipswith URLs in env vars; full Rust toolchain, fastest iteration.TIKTOK_RESEARCH_ACCESS_TOKENand/orTWITTER_BEARER_TOKEN. Documented but unverified against live APIs.Please focus review on
tests/<e2e_url_to_clip.rs>(is this the test seam you'd want?)CAPCUT_YTDLP_PATHenv override insrc/<config.rs>— small surface, test-only, but it is a prod code path.gitignorewhitelist pattern for committed demo fixtures