🧪 Skills

musicful music generator

Generate AI music or lyrics from natural language with a single sentence. The system auto-detects whether to create a vocal song or pure instrumental BGM, an...

v2.0.1
❤️ 1
⬇️ 88
👁 1
Share

Description


name: music-generator description: | Generate AI music or lyrics from natural language with a single sentence. The system auto-detects whether to create a vocal song or pure instrumental BGM, and automatically polls the task: it returns a preview link first, then the final downloadable audio link. author: Musicful

Music Generator Skill (Full SOP)

Capability Overview

This skill supports the following intents:

  1. Generate a full song with lyrics
  2. Generate pure background music (BGM)
  3. Generate lyrics only (no audio)
  4. Query music generation task status

Users can describe the music they want in plain language. The system auto-determines the mode and handles parameter inference and task tracking.


Triggers and Natural Language Examples

The following natural language requests will trigger this skill:

  • Generate a romantic love song
  • Write lyrics about the night sky
  • Create electronic music suitable for short‑video background
  • Check my music generation progress
  • I want a cheerful background music track

Execution (SOP Step‑by‑Step)

Preflight Check (Mandatory)

  • Read MUSICFUL_API_KEY from the skill folder’s .env (resolved at runtime via the running script path): <skill_root>/.env
    • If not configured (empty/missing), immediately inform the user:
    • Stop subsequent calls and wait for the user to complete configuration before continuing.

The execution flow is intent‑based and incorporates a two‑stage return and a "lyrics‑first" UX:

  • Single command entry: /music_generator, with mode branch control:
    • mode=normal (default): generate and show lyrics → submit generation → return preview (status=2) → return final (status=0)
    • mode=bgm: pure music (instrumental=1), no lyrics → preview first → then final
    • mode=lyrics: return lyrics text immediately
  • When using the "custom lyrics" path (built into the normal flow or future extensions): submit generation directly and poll (preview first, then final)

Scenario A: Generate a Full Song with Lyrics

Typical user inputs:

  • Generate a romantic electronic song
  • Write a sad rock song and generate audio
  • Here are some lyrics, please use them to create the song: [...user‑provided lyrics...]

Detailed Flow

Step 1: Intent Recognition

  • If the user provides complete lyrics, treat it as lyrics‑provided generation;
  • Otherwise, assume lyrics need to be generated automatically and then used to synthesize the song.

Step 2: Lyrics Handling

  • If lyrics are provided → use them directly;
  • If not provided → call the V1 Lyrics API to generate lyrics content;

Step 3: Submit Music Generation Task

  • POST {BASE_URL}/v1/music/generate
  • body: { action: "custom", lyrics: "<lyrics>", style: "<inferred from user>", mv: "<default to latest high‑quality model>" }

Step 4: Automatic Task Polling (Two Stages)

  • GET {BASE_URL}/v1/music/tasks?ids=<task_id[,task_id2,…]>
  • Status semantics (key):
    • status = 2 → preview stage complete (returns audio_url as preview link)
    • status = 0 → full audio complete (returns audio_url as downloadable final link)
    • others → processing or failed (use fail_code/fail_reason)
  • Polling strategy:
    1. On first status=2: immediately announce "preview is ready" and return audio_url for listening;
    2. Continue polling until status=0: then return "final audio is ready" with audio_url (download/publish).

Step 5: Return Results to the User (Two‑Stage × Two Songs)

  • The system by default generates two songs/two task_ids (e.g., ids=[id1,id2]). For each id, perform the two‑stage return independently:
    • Stage 1: when this id reaches status=2 → return the preview link (audio_url)
    • Stage 2: keep polling this id → when status=0 → return the full mp3 download link (audio_url)
  • Recommended output format (one block per song):
    • title: </li> <li>prompt: <original user description></li> <li>lyrics: <full lyrics for lyric mode; empty for BGM></li> <li>preview: <preview link (status=2)></li> <li>full: <final mp3 (status=0)></li> </ul> </li> </ul> <hr> <h2>Scenario B: Generate Pure Background Music</h2> <p>:white_check_mark: Typical user inputs:</p> <ul> <li>Generate a piece of pure background music</li> <li>I want an electronic instrumental suitable for video background</li> </ul> <h3>Detailed Flow</h3> <p><strong>Step 1: Intent Recognition</strong></p> <ul> <li>Detect semantics like "pure music/background music/accompaniment" → enter the pure BGM flow.</li> </ul> <p><strong>Step 2: Submit Music Generation Task</strong></p> <ul> <li>POST {BASE_URL}/v1/music/generate</li> <li>body: <code>{ action: "auto", style: "<inferred from user>", mv: "<default latest model>", instrumental: 1 }</code></li> </ul> <p><strong>Step 3: Automatic Task Polling (Two Stages)</strong></p> <ul> <li>Same as Scenario A: status=2 → preview; status=0 → full</li> </ul> <p><strong>Step 4: Return Preview & Final Links (Two Steps)</strong></p> <ul> <li>Stage 1: preview link (status=2)</li> <li>Stage 2: final link (status=0)</li> </ul> <hr> <h2>Scenario C: Generate Lyrics Only</h2> <p>:white_check_mark: User inputs:</p> <ul> <li>Write lyrics about a summer beach</li> <li>I only need lyrics, about a rainy day</li> </ul> <h3>Process</h3> <ul> <li>POST {BASE_URL}/v1/lyrics body: <code>{ prompt: "<user description>" }</code></li> <li>Return: <code>{ lyrics: "<AI‑generated lyrics>" }</code></li> </ul> <hr> <h2>Scenario D: Query Music Generation Task Status</h2> <p>:white_check_mark: User inputs:</p> <ul> <li>Check the progress of task_id=abc123</li> <li>See how far my song generation has progressed</li> </ul> <h3>Detailed Flow</h3> <ol> <li>Extract task_id from the user input;</li> <li>GET {BASE_URL}/v1/music/tasks?ids=<task_id></li> <li>Return task status and audio information.</li> </ol> <hr> <h2>Parameter Inference Rules</h2> <table> <thead> <tr> <th>Parameter</th> <th>Source</th> <th>Default/Notes</th> </tr> </thead> <tbody> <tr> <td><code>style</code></td> <td>Inferred from user input</td> <td>Default to Pop/general if none</td> </tr> <tr> <td><code>mv</code></td> <td>Default high‑quality</td> <td>Prefer latest high‑quality</td> </tr> <tr> <td><code>instrumental</code></td> <td>Set to 1 for BGM</td> <td>Otherwise 0</td> </tr> <tr> <td><code>lyrics</code></td> <td>User‑provided / auto</td> <td>—</td> </tr> <tr> <td><code>title</code></td> <td>Inferred or auto‑named</td> <td>—</td> </tr> </tbody> </table> <blockquote> <p>BASE_URL and API Key:</p> <ul> <li>MUSICFUL_BASE_URL (default: <a href="https://api.musicful.ai">https://api.musicful.ai</a>)</li> <li>MUSICFUL_API_KEY (read from the skill folder’s .env; environment variable MUSICFUL_API_KEY is also honored if set)</li> <li>Entry points: scripts/musicful_api.py, CLI: scripts/run_musicful.py / scripts/dispatch_music_generator.py</li> <li>Important: ensure MUSICFUL_API_KEY is configured before calling; if missing, the server may respond with HTTP 500 (helps pinpoint auth/config issues quickly).</li> </ul> </blockquote> <hr> <h2>Error Handling and Fallback</h2> <ol> <li>If the request is unclear (e.g., "generate music" without clarifying lyrics vs BGM) → ask a follow‑up;</li> <li>If the API call fails → return clear failure reason and suggestions;</li> <li>If polling times out → prompt the user to wait or retry.</li> </ol> <hr> <h2>Unified Return Format</h2> <p>Success:</p> <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span>{ <span style="color:#f92672">"status"</span>: <span style="color:#e6db74">"success"</span>, <span style="color:#f92672">"data"</span>: { <span style="color:#960050;background-color:#1e0010">...</span> } } </span></span></code></pre><p>Error:</p> <pre tabindex="0" style="color:#f8f8f2;background-color:#272822;"><code><span style="display:flex;"><span>{ <span style="color:#f92672">"status"</span>: <span style="color:#e6db74">"error"</span>, <span style="color:#f92672">"message"</span>: <span style="color:#e6db74">"<reason>"</span> } </span></span></code></pre><h2>Example Dialogues</h2> <ul> <li> <p>User: Generate a sad rock song</p> </li> <li> <p>Skill: Shows generated lyrics → submits job → returns preview link → returns full mp3 link</p> </li> <li> <p>User: An ambient BGM for a quiet night</p> </li> <li> <p>Skill: Submits job (instrumental=1) → returns preview → returns full</p> </li> <li> <p>User: Write lyrics about the night sky</p> </li> <li> <p>Skill: Returns generated lyrics</p> </li> </ul> </div></section><!-- Changelog --><!-- Version History --><!-- Reviews --><div id="reviews-section"><section><h2 class="text-lg font-semibold text-gray-900 mb-4">Reviews (0)</h2><!-- Sign in prompt --> <div class="bg-gray-50 rounded-lg p-4 mb-6 text-sm text-gray-500"><a href="/auth/login" class="text-brand-600 hover:text-brand-700 font-medium">Sign in</a> to write a review.</div><!-- Empty state --> <div class="bg-gray-50 rounded-xl p-8 text-center"><p class="text-sm text-gray-500">No reviews yet. Be the first to review!</p></div></section></div><!-- Comments --><div id="comments-section"><section><h2 class="text-lg font-semibold text-gray-900 mb-4" id="comments">Comments (0)</h2><div class="bg-gray-50 rounded-lg p-4 mb-6 text-sm text-gray-500"><a href="/auth/login" class="text-brand-600 hover:text-brand-700 font-medium">Sign in</a> to join the discussion.</div><div class="bg-gray-50 rounded-xl p-8 text-center"><p class="text-sm text-gray-500">No comments yet. Be the first to share your thoughts!</p></div></section></div></div><!-- Sidebar (1/3) --><div class="space-y-6"><!-- Platforms --><div class="bg-white rounded-xl border border-gray-200 p-5"><h3 class="text-sm font-semibold text-gray-900 mb-3">Compatible Platforms</h3><div class="flex flex-wrap gap-2"></div></div><!-- Tags --><!-- Links --><div class="bg-white rounded-xl border border-gray-200 p-5"><h3 class="text-sm font-semibold text-gray-900 mb-3">Links</h3><div class="space-y-2"><a href="https://clawhub.ai/skills/musicful-music-generator" target="_blank" rel="noopener noreferrer" class="flex items-center gap-2 text-sm text-brand-600 hover:text-brand-700">📂 Source Code</a> </div></div><!-- Pricing (DISABLED: free-only mode — always show Free) --><div class="bg-white rounded-xl border border-gray-200 p-5"><h3 class="text-sm font-semibold text-gray-900 mb-3">Pricing</h3><span class="text-sm font-medium text-green-700 bg-green-50 px-3 py-1 rounded-full">Free</span></div></div></div><!-- Related Items --><section class="mt-12"><h2 class="text-xl font-bold text-gray-900 mb-6">Related Configs</h2><div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"><div class="relative"><a href="/item/skill-self-improving-agent" class="card-hover block"><div class="flex items-start justify-between gap-3 mb-3"><div class="flex items-center gap-2 min-w-0"><span class="badge-skill">🧪 Skill</span><h3 class="text-base font-semibold text-gray-900 truncate">self-improving-agent</h3></div><span class="shrink-0 text-xs font-medium text-green-700 bg-green-50 px-2 py-0.5 rounded-full mr-6">Free</span> </div><p class="text-sm text-gray-500 mb-3 line-clamp-2">Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Clau...</p><div class="flex items-center justify-between"><div class="flex items-center gap-3 text-xs text-gray-500"><span class="flex items-center gap-0.5"><span>❤️</span> 2.0k</span> <span class="flex items-center gap-0.5"><span>⬇️</span> 218k</span></div></div></a> <button data-compare-slug="skill-self-improving-agent" onclick="event.preventDefault();event.stopPropagation();toggleCompare(this.dataset.compareSlug)" class="absolute top-3 right-3 w-6 h-6 flex items-center justify-center rounded border border-gray-200 text-gray-400 hover:text-brand-600 hover:border-brand-300 transition-colors" title="Add to comparison"><svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line> <line x1="12" y1="20" x2="12" y2="4"></line> <line x1="6" y1="20" x2="6" y2="14"></line></svg></button></div><div class="relative"><a href="/item/self-improving-agent" class="card-hover block"><div class="flex items-start justify-between gap-3 mb-3"><div class="flex items-center gap-2 min-w-0"><span class="badge-skill">🧪 Skill</span><h3 class="text-base font-semibold text-gray-900 truncate">Self Improving Agent</h3></div><span class="shrink-0 text-xs font-medium text-green-700 bg-green-50 px-2 py-0.5 rounded-full mr-6">Free</span> </div><p class="text-sm text-gray-500 mb-3 line-clamp-2">Captures learnings, errors, and corrections to enable continuous improvement. And also 50+ models for image generation, video generation, text-to-speech, spe...</p><div class="flex items-center justify-between"><div class="flex items-center gap-3 text-xs text-gray-500"><span class="flex items-center gap-0.5"><span>❤️</span> 2.0k</span> <span class="flex items-center gap-0.5"><span>⬇️</span> 206k</span></div></div></a> <button data-compare-slug="self-improving-agent" onclick="event.preventDefault();event.stopPropagation();toggleCompare(this.dataset.compareSlug)" class="absolute top-3 right-3 w-6 h-6 flex items-center justify-center rounded border border-gray-200 text-gray-400 hover:text-brand-600 hover:border-brand-300 transition-colors" title="Add to comparison"><svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line> <line x1="12" y1="20" x2="12" y2="4"></line> <line x1="6" y1="20" x2="6" y2="14"></line></svg></button></div><div class="relative"><a href="/item/find-skills" class="card-hover block"><div class="flex items-start justify-between gap-3 mb-3"><div class="flex items-center gap-2 min-w-0"><span class="badge-skill">🧪 Skill</span><h3 class="text-base font-semibold text-gray-900 truncate">Find Skills</h3></div><span class="shrink-0 text-xs font-medium text-green-700 bg-green-50 px-2 py-0.5 rounded-full mr-6">Free</span> </div><p class="text-sm text-gray-500 mb-3 line-clamp-2">Search, discover, and install skills from the open agent skills ecosystem to extend agent capabilities for specific tasks or domains.</p><div class="flex items-center justify-between"><div class="flex items-center gap-3 text-xs text-gray-500"><span class="flex items-center gap-0.5"><span>❤️</span> 814</span> <span class="flex items-center gap-0.5"><span>⬇️</span> 199k</span></div></div></a> <button data-compare-slug="find-skills" onclick="event.preventDefault();event.stopPropagation();toggleCompare(this.dataset.compareSlug)" class="absolute top-3 right-3 w-6 h-6 flex items-center justify-center rounded border border-gray-200 text-gray-400 hover:text-brand-600 hover:border-brand-300 transition-colors" title="Add to comparison"><svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line> <line x1="12" y1="20" x2="12" y2="4"></line> <line x1="6" y1="20" x2="6" y2="14"></line></svg></button></div><div class="relative"><a href="/item/skill-summarize" class="card-hover block"><div class="flex items-start justify-between gap-3 mb-3"><div class="flex items-center gap-2 min-w-0"><span class="badge-skill">🧪 Skill</span><h3 class="text-base font-semibold text-gray-900 truncate">Summarize</h3></div><span class="shrink-0 text-xs font-medium text-green-700 bg-green-50 px-2 py-0.5 rounded-full mr-6">Free</span> </div><p class="text-sm text-gray-500 mb-3 line-clamp-2">--- name: summarize description: Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube). homepage: https://summarize.sh metadata: {"clawdbot":{"emoji":"🧾","requires":{"b</p><div class="flex items-center justify-between"><div class="flex items-center gap-3 text-xs text-gray-500"><span class="flex items-center gap-0.5"><span>❤️</span> 609</span> <span class="flex items-center gap-0.5"><span>⬇️</span> 160k</span></div></div></a> <button data-compare-slug="skill-summarize" onclick="event.preventDefault();event.stopPropagation();toggleCompare(this.dataset.compareSlug)" class="absolute top-3 right-3 w-6 h-6 flex items-center justify-center rounded border border-gray-200 text-gray-400 hover:text-brand-600 hover:border-brand-300 transition-colors" title="Add to comparison"><svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line> <line x1="12" y1="20" x2="12" y2="4"></line> <line x1="6" y1="20" x2="6" y2="14"></line></svg></button></div></div></section></div></main><footer class="bg-white border-t border-gray-200 mt-16"><div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12"><div class="grid grid-cols-2 md:grid-cols-5 gap-8"><!-- Brand --><div class="col-span-2 md:col-span-1"><a href="/" class="flex items-center gap-2 text-lg font-bold text-brand-600"><span>☕</span> <span>Skillbrew</span></a><p class="mt-2 text-sm text-gray-500">Brew your perfect agent</p></div><!-- Product --><div><h3 class="text-sm font-semibold text-gray-900 mb-3">Product</h3><ul class="space-y-2"><li><a href="/browse" class="text-sm text-gray-500 hover:text-gray-700">Browse</a></li><li><a href="/collections" class="text-sm text-gray-500 hover:text-gray-700">Collections</a></li><li><a href="/weekly" class="text-sm text-gray-500 hover:text-gray-700">Weekly</a></li><li><a href="/submit" class="text-sm text-gray-500 hover:text-gray-700">Submit</a></li></ul></div><!-- Community --><div><h3 class="text-sm font-semibold text-gray-900 mb-3">Community</h3><ul class="space-y-2"><li><a href="https://github.com/skillbrew-dev" target="_blank" rel="noopener" class="text-sm text-gray-500 hover:text-gray-700">GitHub</a></li><li><a href="https://discord.gg/zuXQfjUW" target="_blank" rel="noopener" class="text-sm text-gray-500 hover:text-gray-700">Discord</a></li><li><a href="mailto:skillbrew@skillbrew.dev" class="text-sm text-gray-500 hover:text-gray-700">Email</a></li></ul></div><!-- Resources --><div><h3 class="text-sm font-semibold text-gray-900 mb-3">Resources</h3><ul class="space-y-2"><li><a href="/api/docs" class="text-sm text-gray-500 hover:text-gray-700">API Docs</a></li><li><a href="/feed.xml" class="text-sm text-gray-500 hover:text-gray-700">RSS Feed</a></li></ul></div><!-- Legal --><div><h3 class="text-sm font-semibold text-gray-900 mb-3">Legal</h3><ul class="space-y-2"><li><a href="/about" class="text-sm text-gray-500 hover:text-gray-700">About</a></li><li><a href="/privacy" class="text-sm text-gray-500 hover:text-gray-700">Privacy Policy</a></li><li><a href="/terms" class="text-sm text-gray-500 hover:text-gray-700">Terms of Service</a></li></ul></div></div><div class="mt-8 pt-8 border-t border-gray-200"><p class="text-sm text-gray-400 text-center">© 2026 Skillbrew. All rights reserved.</p></div></div></footer><!-- Compare floating bar --><div id="compare-bar" class="fixed bottom-0 left-0 right-0 bg-white border-t border-gray-200 shadow-lg py-3 px-4 z-50 hidden"><div class="max-w-7xl mx-auto flex items-center justify-between"><span class="text-sm text-gray-700"><strong id="compare-count">0</strong> items selected for comparison</span><div class="flex items-center gap-2"><button onclick="clearCompareSet()" class="px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 transition-colors">Clear</button> <button onclick="goCompare()" class="px-4 py-1.5 text-sm font-medium text-white bg-brand-600 rounded-lg hover:bg-brand-700 transition-colors">Compare Now</button></div></div></div><script> document.body.addEventListener('htmx:responseError', function(event) { if (event.detail.xhr.status === 401) { window.location.href = '/auth/login?return_url=' + encodeURIComponent(window.location.pathname); } }); // Include CSRF token in all HTMX requests document.body.addEventListener('htmx:configRequest', function(evt) { var meta = document.querySelector('meta[name="csrf-token"]'); if (meta) { evt.detail.headers['X-CSRF-Token'] = meta.content; } }); // Compare set (localStorage) function getCompareSet() { try { return JSON.parse(localStorage.getItem('sb_compare') || '[]'); } catch { return []; } } function saveCompareSet(set) { localStorage.setItem('sb_compare', JSON.stringify(set)); updateCompareBar(); } function toggleCompare(slug) { let set = getCompareSet(); const idx = set.indexOf(slug); if (idx >= 0) { set.splice(idx, 1); } else { if (set.length >= 3) { set.shift(); } set.push(slug); } saveCompareSet(set); updateCompareButtons(); } function clearCompareSet() { saveCompareSet([]); updateCompareButtons(); } function goCompare() { const set = getCompareSet(); if (set.length >= 2) { window.location.href = '/compare?items=' + set.join(','); } } function updateCompareBar() { const set = getCompareSet(); const bar = document.getElementById('compare-bar'); const count = document.getElementById('compare-count'); if (bar) { if (set.length >= 2) { bar.classList.remove('hidden'); } else { bar.classList.add('hidden'); } if (count) count.textContent = set.length; } } function updateCompareButtons() { const set = getCompareSet(); document.querySelectorAll('[data-compare-slug]').forEach(btn => { const slug = btn.dataset.compareSlug; if (set.includes(slug)) { btn.classList.add('bg-brand-50', 'text-brand-600', 'border-brand-300'); btn.classList.remove('text-gray-400', 'border-gray-200'); btn.title = 'Remove from comparison'; } else { btn.classList.remove('bg-brand-50', 'text-brand-600', 'border-brand-300'); btn.classList.add('text-gray-400', 'border-gray-200'); btn.title = 'Add to comparison'; } }); } document.addEventListener('DOMContentLoaded', function() { updateCompareBar(); updateCompareButtons(); }); document.body.addEventListener('htmx:afterSwap', function() { updateCompareButtons(); }); </script></body></html>