Pick BGM that doesn't fight the voiceover. Watches the video, returns a hook + ffmpeg ducking spec, prints the license.
Strong domain-specific tool design with clear naming (verb_noun pattern), comprehensive descriptions (avg 180 chars), and well-structured schemas. All 12 tools have input schemas with typed parameters and descriptions. Output schemas are documented in descriptions. Error handling uses SonicError wrapper with recovery guidance. Main gaps: missing tool annotations (readOnlyHint/destructiveHint), no pagination support for list-like tools, and some parameter descriptions could be more prescriptive about constraints. Composition is excellent, tools chain naturally (ingest → analyze → recommend → mix). Security is solid (no secrets in params, SSRF protection, ToS warnings).
Analyze up to 20 clips, cluster moods, return one consistent mini-playlist for the series.
Produce a structured VideoSonic profile for BGM matching. platform_hint: instagram_story | instagram_reel | tiktok | youtube_short | youtube_long | generic. Uses Gemini video understanding when GEMINI_API_KEY is set; otherwise local ffmpeg/audio heuristics (and optional faster-whisper / PySceneDetect if installed). Always fills search_queries even if analysis is weak. extra_notes: optional caption/script the user already has — used as a hint, not as a replacement for watching the video.
Export the mix spec + ffmpeg recipe + attribution without requiring a render. This is the editor companion output (CapCut / Premiere / DaVinci / agent). Set render=true to also write preview files (same as preview_mix).
Generate a bed when the catalog misses. Always marked source=generated. Refuses unless i_understand_not_commercially_cleared=true. Local fallback is a sine-tremolo demo. NOT cleared for ads. Check Suno/Stable Audio/Lyria terms before swapping in a real generator. Generated tracks are excluded from recommend_bgm auto catalogs.
Return one track's metadata, license string, attribution text, and URLs.
Missing tool annotations (readOnlyHint, destructiveHint, idempotentHint). Tools like 'status', 'get_track', 'search_music' are read-only but lack explicit annotation. Destructive tools like 'ingest_video', 'preview_mix', 'generate_bed' lack destructiveHint. LLMs cannot infer safety properties without annotations.
Parameter descriptions lack prescriptive constraints. 'catalog' accepts 'auto|seed|jamendo|freesound|library' but description does not enumerate valid values as an enum constraint. 'platform_hint' similarly lacks explicit enum. LLMs hallucinate invalid values without formal constraints.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 65 | 2026-07-28+ | v2 |
Ingest a local video path or public http(s) URL. Accepts a filesystem path or an HTTPS video URL. YouTube/TikTok/Instagram via yt-dlp is OFF unless SONICMATCH_ALLOW_YTDLP=1 (ToS + extractor risk). Rejects file://, http, loopback, and private IPs (SSRF). Size-capped. Extracts duration/fps/aspect with ffprobe, a 16 kHz mono wav, up to 12 scene keyframes, and a 360p proxy. Returns an asset_id. Never returns video bytes. Call this first. Then call analyze_video_music with the asset_id.
Mix BGM under the video: hook trim, loop if needed, optional speech ducking. Returns preview mp3 + low-res mp4 paths, the ffmpeg command, and a mix_spec JSON an editor (CapCut / Premiere / DaVinci / your agent) can re-apply. Ducking uses ffmpeg sidechaincompress when the video has speech. Seed tracks without audio files get a synthesized CC0 demo bed so the pipeline still runs offline.
Rank license-safe BGM. Pass asset_id and/or a VideoSonic profile. Defaults instrumental_only=True when speech_coverage > 0.25. catalog: auto | seed | jamendo | freesound | library auto = seed always, plus Jamendo/Freesound/user-library when configured. Each recommendation includes score, reason, suggested song in/out (12–20s high-energy slice), ducking hint, and license_ok_for_platform. max_results is clamped to 3–7. brand_kit: name previously saved with save_brand_kit.
Save a brand kit (BPM lock + no vocals + mood whitelist). Pass brand_kit=name to recommend_bgm.
Free-text search over seed + optional Jamendo / Freesound / user library.
Show ffmpeg/yt-dlp availability and which music adapters have keys.
Snap detected scene cuts onto a beat grid. Returns EDL-ish spans and intro/peak/outro acts. bpm defaults to the VideoSonic suggested_bpm midpoint, or the track BPM if track_id is set.
No pagination support for list-like results. 'search_music' returns up to 10 results (limit param), 'recommend_bgm' clamped to 3-7, but no cursor/offset or total_count in response. Large result sets risk context window exhaustion. Missing next_cursor or pagination metadata.
Incomplete output schema documentation. Tools return complex objects (VideoSonicProfile, mix_spec, EDL spans) but response structure is not formally documented in tool descriptions. LLMs must infer field names and types from context.
Error handling lacks actionable recovery guidance in some tools. 'get_track' and 'search_music' may fail silently or return empty results, but descriptions do not explain fallback strategies or what to do if a track is not found.