Skip to content
Back to skills

Ima Voice Ai

BSecurity

Use for AI music generation via IMA Open API. Supports text_to_music with 3 models. IMPORTANT — Default model selection rule: always recommend the NEWEST and most POPULAR model, NOT the cheapest. Default: Suno (model_id=sonic, model_version=sonic-v5, 25pts) — latest engine, full-featured with custom mode, lyrics, vocal gender, style tags. Alternative: DouBao BGM (model=GenBGM, 30pts) for background music; DouBao Song (model=GenSong, 30pts) for songs. Use Suno sonic by default unless user asks...

  • 16 stars
  • 0 votes
  • 0 copies
  • 8 views
  • Added June 7, 2026
code-qualitypythongobashnodetestinggitapisecurity

Works with

  • cli
  • api
  • mcp

Security analysis

B85/100
  • highPerforms destructive filesystem operations

Pro scans all 10 files and shows the line behind each finding

Scanned June 7, 2026

npx -y skills add modbender/skill-library-mcp --skill ima-voice-ai --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ima Voice Ai?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ima Voice Ai
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/modbender-ima-voice-ai/badge)](https://www.skillsdirectory.com/skills/modbender-ima-voice-ai)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: IMA Studio Music Generation
version: 1.0.1
category: file-generation
author: IMA Studio (imastudio.com)
keywords: imastudio, music generation, ai music
argument-hint: "[music description or lyrics]"
description: >
  Use for AI music generation via IMA Open API. Supports text_to_music with 3 models.
  IMPORTANT — Default model selection rule: always recommend the NEWEST and most POPULAR model,
  NOT the cheapest. Default: Suno (model_id=sonic, model_version=sonic-v5, 25pts) — latest
  engine, full-featured with custom mode, lyrics, vocal gender, style tags. Alternative:
  DouBao BGM (model=GenBGM, 30pts) for background music; DouBao Song (model=GenSong, 30pts)
  for songs. Use Suno sonic by default unless user asks for BGM/song only.
  Output is MP3/WAV. Requires an ima_* API key.
---

# IMA Voice AI Creation

## ⚙️ How This Skill Works

**For transparency:** This skill uses a bundled Python script (`scripts/ima_voice_create.py`) to call the IMA Open API. The script:
- Sends your prompt to `https://api.imastudio.com` (IMA's servers)
- Uses `--user-id` **only locally** as a key for storing your model preferences
- Returns a music URL when generation is complete

**What gets sent to IMA servers:**
- ✅ Your music prompt/description
- ✅ Model selection (Suno/DouBao)
- ❌ NO API key in prompts (key is used for authentication only)
- ❌ NO user_id (it's only used locally)

**What's stored locally:**
- `~/.openclaw/memory/ima_prefs.json` - Your model preferences (< 1 KB)
- `~/.openclaw/logs/ima_skills/` - Generation logs (auto-deleted after 7 days)
- See [SECURITY.md](SECURITY.md) for complete privacy policy

### Agent Execution (Internal Reference)

> **Note for users:** You can review the script source at `scripts/ima_voice_create.py` anytime.  
> **This skill uses only `api.imastudio.com`** (no image upload needed for music generation, unlike image/video skills which also use `imapi.liveme.com`).

Use the bundled script internally:

```bash
# Generate music — Suno sonic-v5
python3 {baseDir}/scripts/ima_voice_create.py \
  --api-key  $IMA_API_KEY \
  --task-type text_to_music \
  --model-id  sonic \
  --prompt   "upbeat lo-fi hip hop, 90 BPM, no vocals" \
  --user-id  {user_id} \
  --output-json

# DouBao BGM
python3 {baseDir}/scripts/ima_voice_create.py \
  --api-key  $IMA_API_KEY \
  --model-id  GenBGM \
  --prompt   "calm ambient piano background" \
  --user-id  {user_id} \
  --output-json
```

The script outputs JSON — parse it to get the result URL and pass it to the user via the UX protocol messages below.

---

## Overview

Call IMA Open API to create AI-generated music/audio. All endpoints require an `ima_*` API key. The core flow is: **query products → create task → poll until done**.

---

## 🔒 Security & Transparency Policy

> **This skill is community-maintained and open for inspection.**

### 🌐 Network Architecture

**This skill uses a simpler network architecture than image/video skills:**

| Skill Type | Domains Used | Why |
|------------|--------------|-----|
| **ima-voice-ai** (this skill) | ✅ `api.imastudio.com` only | Music generation doesn't require image uploads |
| ima-image-ai, ima-video-ai | `api.imastudio.com` + `imapi.liveme.com` | Image/video tasks need image upload service |

**Why the difference?**
- **Music generation** (text_to_music) only needs text prompts → single API endpoint
- **Image/video generation** (i2i, i2v tasks) needs image file uploads → requires separate upload service

**Security verification:**
```bash
# Verify this skill only uses api.imastudio.com:
grep -n "https://" scripts/ima_voice_create.py

# Expected output:
# Only https://api.imastudio.com (no imapi.liveme.com)
```

---

### ✅ What Users CAN Do

**Full transparency:**
- ✅ **Review all source code**: Check `scripts/ima_voice_create.py` and `ima_logger.py` anytime
- ✅ **Verify network calls**: **This skill uses only `api.imastudio.com`** (music generation doesn't require image uploads). Verify by running: `grep -n "https://" scripts/ima_voice_create.py`
- ✅ **Inspect local data**: View `~/.openclaw/memory/ima_prefs.json` and log files
- ✅ **Control privacy**: Delete preferences/logs anytime, or disable file writes (see below)

**Configuration allowed:**
- ✅ **Set API key** in environment or agent config:
  - Environment variable: `export IMA_API_KEY=ima_your_key_here`
  - OpenClaw/MCP config: Add `IMA_API_KEY` to agent's environment configuration
  - Get your key at: https://imastudio.com
- ✅ **Use scoped/test keys**: Test with limited API keys, rotate after testing
- ✅ **Disable file writes**: Make prefs/logs read-only or symlink to `/dev/null`

**Data control:**
- ✅ **View stored data**: `cat ~/.openclaw/memory/ima_prefs.json`
- ✅ **Delete preferences**: `rm ~/.openclaw/memory/ima_prefs.json` (resets to defaults)
- ✅ **Delete logs**: `rm -rf ~/.openclaw/logs/ima_skills/` (auto-cleanup after 7 days anyway)
- ✅ **Review security**: See [SECURITY.md](SECURITY.md) for complete privacy policy

### ⚠️ Advanced Users: Fork & Modify

If you need to modify this skill for your use case:
1. **Fork the repository** (don't modify the original)
2. **Update your fork** with your changes
3. **Test thoroughly** with limited API keys
4. **Document your changes** for troubleshooting

**Note:** Modified skills may break API compatibility or introduce security issues. Official support only covers the unmodified version.

### ❌ What to AVOID (Security Risks)

**Actions that could compromise security:**
- ❌ Sharing API keys publicly or in skill files
- ❌ Modifying API endpoints to unknown servers
- ❌ Disabling SSL/TLS certificate verification
- ❌ Logging sensitive user data (prompts, IDs, etc.)
- ❌ Bypassing authentication or billing mechanisms

**Why this matters:**
1. **API Compatibility**: Skill logic aligns with IMA Open API schema
2. **Security**: Malicious modifications could leak credentials or bypass billing
3. **Support**: Modified skills may not be supported
4. **Community**: Breaking changes affect all users

### 📁 File System Access (Declared)

This skill reads/writes the following files:

| Path | Purpose | Size | Auto-cleanup | User Control |
|------|---------|------|--------------|--------------|
| `~/.openclaw/memory/ima_prefs.json` | User model preferences | < 1 KB | No | Delete anytime |
| `~/.openclaw/logs/ima_skills/` | Generation logs | ~10-50 KB/day | 7 days | Delete anytime |

**What's stored:**
- ✅ Model preferences (e.g., "last used: Suno sonic-v5")
- ✅ Timestamps (e.g., "2026-02-27 12:34:56")
- ✅ Task IDs and HTTP status codes
- ❌ NO API keys
- ❌ NO personal data
- ❌ NO prompts or generated content

**Full transparency:** See [SECURITY.md](SECURITY.md) for data flow diagram and privacy policy.

### 📋 Privacy & Data Handling Summary

**What this skill does with your data:**

| Data Type | Sent to IMA? | Stored Locally? | User Control |
|-----------|-------------|-----------------|--------------|
| Music prompts | ✅ Yes (required for generation) | ❌ No | None (required) |
| API key | ✅ Yes (authentication header) | ❌ No | Set via env var |
| user_id (optional CLI arg) | ❌ **Never** (local preference key only) | ✅ Yes (as prefs file key) | Change `--user-id` value |
| Model preferences | ❌ No | ✅ Yes (~/.openclaw) | Delete anytime |
| Generation logs | ❌ No | ✅ Yes (~/.openclaw) | Auto-cleanup 7 days |

**Privacy recommendations:**
1. **Use test/scoped API keys** for initial testing
2. **Note**: `--user-id` is **never sent to IMA servers** - it's only used locally as a key for storing preferences in `~/.openclaw/memory/ima_prefs.json`
3. **Review source code** at `scripts/ima_voice_create.py` to verify network calls (search for `create_task` function)
4. **Rotate API keys** after testing or if compromised

**Get your IMA API key:** Visit https://imastudio.com to register and get started.

### 🔧 For Skill Maintainers Only

**Version control:**
- All changes must go through Git with proper version bumps (semver)
- CHANGELOG.md must document all changes
- Production deployments require code review

**File checksums (optional):**
```bash
# Verify skill integrity
sha256sum SKILL.md scripts/ima_voice_create.py
```

If users report issues, verify file integrity first.

---

## 🧠 User Preference Memory

> User preferences **override** recommended defaults. If a user has generated before, use their preferred model — not the system default.

### Storage: `~/.openclaw/memory/ima_prefs.json`

```json
{
  "user_{user_id}": {
    "text_to_music": { "model_id": "sonic", "model_name": "Suno", "credit": 25, "last_used": "..." }
  }
}
```

If the file or key doesn't exist, fall back to the ⭐ Recommended Defaults below.

### When to Read (Before Every Generation)

1. Load `~/.openclaw/memory/ima_prefs.json` (silently, no error if missing)
2. Look up `user_{user_id}.text_to_music`
3. **If found** → use that model; mention it:
   ```
   🎵 根据你的使用习惯,将用 [Model Name] 帮你生成音乐…
   • 模型:[Model Name](你的常用模型)
   • 预计耗时:[X ~ Y 秒]
   • 消耗积分:[N pts]
   ```
4. **If not found** → use the ⭐ Recommended Default (Suno sonic-v5)

### When to Write (After Every Successful Generation)

Save the used model to `~/.openclaw/memory/ima_prefs.json` under `user_{user_id}.text_to_music`.  
See `ima-image-ai/SKILL.md` → "User Preference Memory" for the full Python write snippet.

### When to Update (User Explicitly Changes Model)

| Trigger | Action |
|---------|--------|
| `用XXX` / `换成XXX` | Switch + save as new preference |
| `以后都用XXX` / `always use XXX` | Save + confirm: `✅ 已记住!以后音乐生成默认用 [XXX]` |
| `用便宜的` / `cheapest` | Use DouBao BGM/Song; do NOT save unless user says "以后都用" |

---

## ⭐ Recommended Defaults

> **These are fallback defaults — only used when no user preference exists.**  
> **Always default to the newest and most popular model. Do NOT default to the cheapest.**

| Task | Default Model | model_id | model_version | Cost | Why |
|------|--------------|----------|---------------|------|-----|
| text_to_music | **Suno (sonic-v5)** | `sonic` | `sonic` | 25 pts | Latest Suno engine, best quality |
| text_to_music (BGM only) | **DouBao BGM** | `GenBGM` | `GenBGM` | 30 pts | Background music |
| text_to_music (song) | **DouBao Song** | `GenSong` | `GenSong` | 30 pts | Song generation |

**Selection guide by use case:**
- Custom song with lyrics, vocals, style → **Suno sonic-v5** (default)
- Background music / ambient loop → **DouBao BGM**
- Simple song generation → **DouBao Song**
- User explicitly asks for cheapest → DouBao BGM/Song (6pts each) — only if explicitly requested

> ⚠️ For Suno: `model_version` inside `parameters` (e.g. `sonic-v5`) is different from the outer `model_version` field (which is `sonic`). Always set both.

---

## 💬 User Experience Protocol (IM / Feishu / Discord) v1.1 🆕

> **v1.1 Update:** Added Step 0 to ensure correct message ordering in group chats (learned from ima-image-ai v1.2).
>
> Music generation completes in 10~45 seconds. **Never let users wait in silence.**  
> Always follow all 5 steps below, every single time.

### 🚫 Never Say to Users

| ❌ Never say | ✅ What users care about |
|-------------|--------------------------|
| `ima_voice_create.py` / 脚本 / script | — |
| 自动化脚本 / automation | — |
| 自动处理产品列表 / 查询接口 | — |
| 自动解析参数 / 智能轮询 | — |
| attribute_id / model_version / form_config | — |
| API 调用 / HTTP 请求 / 任何技术参数名 | — |

Only tell users: **model name · estimated time · credits · result (audio file/player) · plain-language status**.

---

### Estimated Generation Time per Model

| Model | Estimated Time | Poll Every | Send Progress Every |
|-------|---------------|------------|---------------------|
| DouBao BGM | 10~25s | 5s | 10s |
| DouBao Song | 10~25s | 5s | 10s |
| Suno (sonic-v5) | 20~45s | 5s | 15s |

`estimated_max_seconds` = upper bound (e.g. 45 for Suno, 25 for DouBao BGM/Song).

---

### Step 0 — Initial Acknowledgment Reply (Normal Reply) 🆕

**⚠️ CRITICAL:** This step ensures correct message ordering in group chats.

**Before doing anything else**, reply to the user with a friendly acknowledgment message using your **normal reply** (not `message` tool). This reply will automatically appear FIRST in the conversation.

**Example acknowledgment messages:**
```
好的!马上帮你生成轻松的背景音乐 🎵
```
```
收到!用 Suno 为你创作一首歌 🎶
```
```
OK! Starting music generation with DouBao BGM 🎵
```

**Rules:**
- Keep it short and warm (< 15 words)
- Match the user's language (Chinese/English)
- Include relevant emoji (🎵/🎶/🎸/🎹)
- This is your ONLY normal reply — all subsequent updates use `message` tool

**Why this matters:**
- Normal replies automatically appear FIRST in the conversation thread
- `message` tool pushes appear in chronological order AFTER your initial reply
- This ensures users see: "好的!" → "🎵 开始生成..." → "✅ 成功!" (correct order)

---

### Step 1 — Pre-Generation Notification (Push via message tool)

**After Step 0 reply**, use the `message` tool to push a notification immediately to the group/channel:

```python
# Agent implementation
message(
    action="send",
    target=group_id,  # or channel_id for Discord
    message="""🎵 开始生成音乐,请稍候…
• 模型:[Model Name]
• 预计耗时:[X ~ Y 秒]
• 消耗积分:[N pts]"""
)
```

**User-facing message template:**
```
🎵 开始生成音乐,请稍候…
• 模型:[Model Name]
• 预计耗时:[X ~ Y 秒]
• 消耗积分:[N pts]
```

**Cost transparency:**
- Balanced (Suno 25 pts): "使用 Suno(25 积分,功能最全)"
- DouBao alternatives (30 pts each): "使用 DouBao BGM(30 积分)" — only if user explicitly requests DouBao or background music type

> Adapt language to match the user. English → `🎵 Starting music generation, please wait [X~Y] seconds…`

---

### Step 2 — Progress Updates

Poll the task detail API every **5s**.  
Send a progress update every `[Send Progress Every]` seconds per the table above.

```
⏳ 音乐生成中… [P]%
已等待 [elapsed]s,预计最长 [max]s
```

**Progress formula:**
```
P = min(95, floor(elapsed_seconds / estimated_max_seconds * 100))
```

- **Cap at 95%** — never show 100% until the API returns `success`
- If `elapsed > estimated_max`: keep P at 95% and append `「快好了,稍等…」`

---

### Step 3 — Success Notification (Push audio via message tool)

When task status = `success`, use the `message` tool to **send the generated audio directly** (not as a text URL):

**Agent implementation:**
```python
# Get result URL from script output or task detail API
result = get_task_result(task_id)
audio_url = result["medias"][0]["url"]

# Push audio + caption to group/channel
message(
    action="send",
    target=group_id,
    media=audio_url,  # Feishu/Discord will render the audio
    caption=f"""✅ 音乐生成成功!
• 模型:[Model Name]
• 耗时:预计 [X~Y]s,实际 [actual]s
• 消耗积分:[N pts]

🔗 原始链接:{audio_url}"""
)
```

**User-facing message:**
```
✅ 音乐生成成功!
• 模型:[Model Name]
• 耗时:预计 [X~Y]s,实际 [actual]s
• 消耗积分:[N pts]

🔗 原始链接:https://ws.esxscloud.com/.../audio.wav

[音频直接显示为文件卡片,可点击播放]
```

**Platform-specific notes:**
- **Feishu**: `message(action=send, media=url, caption="...")` — caption appears with audio file card
- **Discord**: Audio embeds automatically from URL; caption can be in message text
- **Telegram**: Use `message(action=send, media=url, caption="...")`

**⚠️ Important**: 
- Always send audio via `media` parameter (file card/player) + include URL in caption text
- Do NOT use local file paths like `/tmp/audio.wav` — use HTTP URL from API
- Users expect: (1) clickable audio file card + (2) raw URL link for sharing/downloading
- Format: `media=audio_url` + `caption="...🔗 原始链接:{audio_url}"`

---

### Step 4 — Failure Notification (Push via message tool)

When task status = `failed` or any API/network error, push a failure message with alternative suggestions:

**Agent implementation:**
```python
message(
    action="send",
    target=group_id,
    message="""❌ 音乐生成失败
• 原因:[natural_language_error_message]
• 建议改用:
  - [Alt Model 1]([特点],[N pts])
  - [Alt Model 2]([特点],[N pts])

需要我帮你用其他模型重试吗?"""
)
```

**⚠️ CRITICAL: Error Message Translation**

**NEVER show technical error messages to users.** Always translate API errors into natural language:

| Technical Error | ❌ Never Say | ✅ Say Instead (Chinese) | ✅ Say Instead (English) |
|----------------|-------------|------------------------|------------------------|
| `"Invalid product attribute"` / `"Insufficient points"` | Invalid product attribute | 生成参数配置异常,请稍后重试 | Configuration error, please try again later |
| `Error 6006` (credit mismatch) | Error 6006 | 积分计算异常,系统正在修复 | Points calculation error, system is fixing |
| `Error 6010` (attribute_id mismatch) | Attribute ID does not match | 模型参数不匹配,请尝试其他模型 | Model parameters incompatible, try another model |
| `error 400` (bad request) | error 400 / Bad request | 音乐参数设置有误,请调整描述后重试 | Music parameter error, adjust description and retry |
| `resource_status == 2` | Resource status 2 / Failed | 音乐生成遇到问题,建议换个模型试试 | Music generation failed, try another model |
| `status == "failed"` (no details) | Task failed | 这次生成没成功,要不换个模型试试? | Generation unsuccessful, try a different model? |
| `timeout` | Task timed out / Timeout error | 音乐生成时间过长已超时,建议用更快的模型 | Music generation took too long, try a faster model |
| Network error / Connection refused | Connection refused / Network error | 网络连接不稳定,请检查网络后重试 | Network connection unstable, check network and retry |
| API key invalid | Invalid API key / 401 Unauthorized | API 密钥无效,请联系管理员 | API key invalid, contact administrator |
| Rate limit exceeded | 429 Too Many Requests / Rate limit | 请求过于频繁,请稍等片刻再试 | Too many requests, please wait a moment |
| Model unavailable | Model not available / 503 Service Unavailable | 当前模型暂时不可用,建议换个模型 | Model temporarily unavailable, try another model |
| Lyrics format error (Suno only) | Invalid lyrics format | 歌词格式有误,请调整后重试 | Lyrics format error, adjust and retry |
| Prompt too short/long | Prompt length invalid | 音乐描述过短或过长,请调整到合适长度 | Music description too short or long, adjust length |

**Generic fallback (when error is unknown):**
- Chinese: `音乐生成遇到问题,请稍后重试或换个模型试试`
- English: `Music generation encountered an issue, please try again or use another model`

**Best Practices:**
1. **Focus on user action**: Tell users what to do next, not what went wrong technically
2. **Be reassuring**: Use phrases like "建议换个模型试试" instead of "生成失败了"
3. **Avoid blame**: Never say "你的描述有问题" → say "描述需要调整一下"
4. **Provide alternatives**: Always suggest 1-2 alternative models in the failure message
5. **Music-specific**: 
   - For Suno lyrics errors, suggest simplifying lyrics or using auto-generated lyrics
   - For prompt length errors, give example length (e.g., "建议20-100字")
   - For BGM requests, recommend DouBao BGM over Suno

**Failure fallback table:**

| Failed Model | First Alt | Second Alt |
|-------------|-----------|------------|
| Suno | DouBao BGM(30pts,背景音乐) | DouBao Song(30pts,歌曲生成) |
| DouBao BGM | DouBao Song(30pts) | Suno(25pts,功能最强) |
| DouBao Song | DouBao BGM(30pts) | Suno(25pts,功能最强) |

---

### Step 5 — Done (No Further Action Needed) 🆕

**v1.1 Note:** After completing Steps 0-4:
- ✅ **Step 0** already sent your normal reply (appears FIRST in chat)
- ✅ **Steps 1-4** pushed all updates via `message` tool (appear in order)
- ✅ **No further action needed** — conversation is complete

**Do NOT:**
- ❌ Reply again with `NO_REPLY` (you already replied in Step 0)
- ❌ Send duplicate confirmation messages
- ❌ Use `message` tool to send the same content twice

**Why this works:**
```
User: "帮我生成一段轻松的背景音乐"
  ↓
[Step 0] Your normal reply:  "好的!马上帮你生成轻松的背景音乐 🎵"  ← Appears FIRST
  ↓
[Step 1] message tool push:  "🎵 开始生成音乐..."  ← Appears SECOND
  ↓
[Step 2] message tool push:  "⏳ 正在生成中… 45%"  ← (if task takes >15s)
  ↓
[Step 3] message tool push:  "✅ 音乐生成成功! [Audio File]"  ← Appears LAST
  ↓
[Step 5] Done. No further replies.
```

---

## Supported Models

### text_to_music (3 models)

| Name | model_id | version_id | Cost | Key form_config |
|------|----------|------------|------|-----------------|
| **Suno** | `sonic` | `sonic` | 25 pts | `model_version=sonic-v5` (latest), `custom_mode=true`, `make_instrumental`, `auto_lyrics`, `tags`, `negative_tags`, `vocal_gender`, `title` |
| DouBao BGM | `GenBGM` | `GenBGM` | 30 pts | — |
| DouBao Song | `GenSong` | `GenSong` | 30 pts | — |

**Model guidance:**
- **Suno**: Most powerful option. Supports full custom mode with genre tags, explicit instrumental toggle, vocal gender selection, and negative tags to exclude unwanted styles.
- **DouBao BGM**: Lightweight background music generation. Ideal for ambient / background tracks.
- **DouBao Song**: Song generation. Good for structured vocal compositions.

**What you can generate:**
- Background music (lo-fi, ambient, cinematic, electronic, jazz, classical…)
- Custom jingles or theme songs with specific BPM and key
- Vocal or instrumental tracks with mood direction
- Short loops or full-length compositions

**Prompt writing tips (for Suno `gpt_description_prompt`):**
- Genre: `"lo-fi hip hop"`, `"orchestral cinematic"`, `"upbeat pop"`, `"dark ambient"`
- Tempo: `"80 BPM"`, `"fast tempo"`, `"slow ballad"`
- Vocals: `"no vocals"` → set `make_instrumental=true`; `"female vocals"` → `vocal_gender="female"`
- Mood: `"happy and energetic"`, `"melancholic"`, `"tense and dramatic"`
- Negative: `negative_tags="heavy metal, distortion"` to exclude styles
- Duration hint: `"60 seconds"`, `"30 second loop"`

## Environment

Base URL: `https://api.imastudio.com`

Required/recommended headers for all `/open/v1/` endpoints:

| Header | Required | Value | Notes |
|--------|----------|-------|-------|
| `Authorization` | ✅ | `Bearer ima_your_api_key_here` | API key authentication |
| `x-app-source` | ✅ | `ima_skills` | Fixed value — identifies skill-originated requests |
| `x_app_language` | recommended | `en` / `zh` | Product label language; defaults to `en` if omitted |

```
Authorization: Bearer ima_your_api_key_here
x-app-source: ima_skills
x_app_language: en
```

---

## ⚠️ MANDATORY: Always Query Product List First

> **CRITICAL**: You MUST call `/open/v1/product/list` BEFORE creating any task.  
> The `attribute_id` field is REQUIRED in the create request. If it is `0` or missing, you get:  
> `"Invalid product attribute"` → `"Insufficient points"` → task fails completely.  
> **NEVER construct a create request from the model table alone. Always fetch the product first.**

### How to get attribute_id

```python
# Step 1: Query product list
GET /open/v1/product/list?app=ima&platform=web&category=text_to_music

# Step 2: Walk the tree to find your model
for group in response["data"]:
    for version in group.get("children", []):
        if version["type"] == "3" and version["model_id"] == target_model_id:
            attribute_id  = version["credit_rules"][0]["attribute_id"]
            credit        = version["credit_rules"][0]["points"]
            model_version = version["id"]
            model_name    = version["name"]
```

### Quick Reference: Known attribute_ids

⚠️ **Production warning**: `attribute_id` and `credit` values change frequently. Always call `/open/v1/product/list` at runtime; table below is pre-queried reference (2026-02-27).

| Model | model_id | attribute_id | credit | Notes |
|-------|----------|-------------|--------|-------|
| Suno (sonic-v4) | `sonic` | **2370** | 25 pts | Default |
| DouBao BGM | `GenBGM` | **4399** | 30 pts | BGM专用 |
| DouBao Song | `GenSong` | **4398** | 30 pts | 歌曲专用 |
| All others | — | → query `/open/v1/product/list` | — | Always runtime query |

### Common Mistakes (and resulting errors)

| Mistake | Error |
|---------|-------|
| `attribute_id` is 0 or missing | `"Invalid product attribute"` → Insufficient points |
| `attribute_id` outdated (production changed) | Same errors; always query product list first |
| `prompt` at outer level | Prompt ignored |
| `cast` missing from inner `parameters` | Billing failure |
| Suno: `model_version` in `parameters` not set to `sonic-v5` | Wrong engine used |

---

## Core Flow

```
1. GET /open/v1/product/list?app=ima&platform=web&category=text_to_music
   → REQUIRED: Get attribute_id, credit, model_version, form_config defaults

2. POST /open/v1/tasks/create
   → Must include: attribute_id, model_name, model_version, credit, cast, prompt (nested!)

3. POST /open/v1/tasks/detail  {task_id: "..."}
   → Poll every 3–5s until medias[].resource_status == 1
   → Extract url from completed media (mp3)
```

---

## Supported Task Types

| category | Capability | Input |
|----------|------------|-------|
| `text_to_music` | Text → Music | prompt |

---

## Detail API status values

| Field | Type | Values |
|-------|------|--------|
| **`resource_status`** | int or `null` | `0`=处理中, `1`=可用, `2`=失败, `3`=已删除;`null` 当作 0 |
| **`status`** | string | `"pending"`, `"processing"`, `"success"`, `"failed"` |

| `resource_status` | `status` | Action |
|-------------------|----------|--------|
| `0` or `null` | `pending` / `processing` | Keep polling |
| `1` | `success` (or `completed`) | Stop when **all** medias are 1; read `url` |
| `1` | `failed` | Stop, handle error |
| `2` / `3` | any | Stop, handle error |

> **Important**: Treat `resource_status: null` as 0. Stop only when **all** medias have `resource_status == 1`. Check `status != "failed"` when rs=1.

---

## API 1: Product List

```
GET /open/v1/product/list?app=ima&platform=web&category=text_to_music
```

Returns a **V2 tree structure**: `type=2` nodes are model groups, `type=3` nodes are versions (leaves). Only `type=3` nodes contain `credit_rules` and `form_config`.

**How to pick a version:**
1. Traverse nodes to find `type=3` leaves
2. Use `model_id` and `id` (= `model_version`) from the leaf
3. Pick `credit_rules[].attribute_id`
4. Use `form_config[].value` as default `parameters` values

---

## API 2: Create Task

```
POST /open/v1/tasks/create
```

### text_to_music

No image input. `src_img_url: []`, `input_images: []`.

```json
{
  "task_type": "text_to_music",
  "enable_multi_model": false,
  "src_img_url": [],
  "parameters": [{
    "attribute_id":  "<from credit_rules>",
    "model_id":      "<model_id>",
    "model_name":    "<model_name>",
    "model_version": "<version_id>",
    "app":           "ima",
    "platform":      "web",
    "category":      "text_to_music",
    "credit":        "<points>",
    "parameters": {
      "prompt":       "upbeat electronic, 120 BPM, no vocals",
      "n":            1,
      "input_images": [],
      "cast":         {"points": "<points>", "attribute_id": "<attribute_id>"}
    }
  }]
}
```

**Prompt tips for music generation:**
- Genre: `"upbeat electronic"`, `"classical piano"`, `"ambient chill"`
- Tempo: `"120 BPM"`, `"slow tempo"`
- Vocals: `"no vocals"`, `"male vocals"`, `"female vocals"`
- Mood: `"happy"`, `"melancholic"`, `"energetic"`
- Duration hint: `"60 seconds"`, `"short loop"`

**Key fields**:

| Field | Required | Description |
|-------|----------|-------------|
| `parameters[].credit` | ✅ | Must equal `credit_rules[].points`. Error 6006 if wrong. |
| `parameters[].parameters.prompt` | ✅ | Prompt must be nested here, NOT at top level. |
| `parameters[].parameters.cast` | ✅ | `{"points": N, "attribute_id": N}` — mirror of credit. |
| `parameters[].parameters.n` | ✅ | Number of outputs (usually `1`). |

Response: `data.id` = task ID for polling.

---

## API 3: Task Detail (Poll)

```
POST /open/v1/tasks/detail
{"task_id": "<id from create response>"}
```

Poll every 3–5s. Completed response:

```json
{
  "id": "task_abc",
  "medias": [{
    "resource_status": 1,
    "url":          "https://cdn.../output.mp3",
    "duration_str": "60s",
    "format":       "mp3"
  }]
}
```

Output fields: `url` (mp3), `duration_str`, `format`.

---

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Placing `prompt` at param top-level | `prompt` must be inside `parameters[].parameters` |
| Wrong `credit` value | Must exactly match `credit_rules[].points` (error 6006) |
| Missing `app` / `platform` in parameters | Required — use `ima` / `web` |
| Single-poll instead of loop | Poll until `resource_status == 1` for ALL medias |
| Not checking `status != "failed"` | `resource_status=1` + `status="failed"` = actual failure |

---

## Python Example

```python
import time
import requests

BASE_URL = "https://api.imastudio.com"
API_KEY  = "ima_your_key_here"
HEADERS  = {
    "Authorization":  f"Bearer {API_KEY}",
    "Content-Type":   "application/json",
    "x-app-source":   "ima_skills",
    "x_app_language": "en",
}


def get_products(category: str) -> list:
    """Returns flat list of type=3 version nodes from V2 tree."""
    r = requests.get(
        f"{BASE_URL}/open/v1/product/list",
        headers=HEADERS,
        params={"app": "ima", "platform": "web", "category": category},
    )
    r.raise_for_status()
    nodes = r.json()["data"]
    versions = []
    for node in nodes:
        for child in node.get("children") or []:
            if child.get("type") == "3":
                versions.append(child)
            for gc in child.get("children") or []:
                if gc.get("type") == "3":
                    versions.append(gc)
    return versions


def create_music_task(prompt: str, product: dict) -> str:
    """Returns task_id."""
    rule = product["credit_rules"][0]
    form_defaults = {f["field"]: f["value"] for f in product.get("form_config", []) if f.get("value") is not None}

    nested_params = {
        "prompt": prompt,
        "n":      1,
        "input_images": [],
        "cast":   {"points": rule["points"], "attribute_id": rule["attribute_id"]},
        **form_defaults,
    }

    body = {
        "task_type":          "text_to_music",
        "enable_multi_model": False,
        "src_img_url":        [],
        "parameters": [{
            "attribute_id":  rule["attribute_id"],
            "model_id":      product["model_id"],
            "model_name":    product["name"],
            "model_version": product["id"],
            "app":           "ima",
            "platform":      "web",
            "category":      "text_to_music",
            "credit":        rule["points"],
            "parameters":    nested_params,
        }],
    }
    r = requests.post(f"{BASE_URL}/open/v1/tasks/create", headers=HEADERS, json=body)
    r.raise_for_status()
    return r.json()["data"]["id"]


def poll(task_id: str, interval: int = 3, timeout: int = 300) -> dict:
    deadline = time.time() + timeout
    while time.time() < deadline:
        r = requests.post(f"{BASE_URL}/open/v1/tasks/detail", headers=HEADERS, json={"task_id": task_id})
        r.raise_for_status()
        task   = r.json()["data"]
        medias = task.get("medias", [])
        if medias:
            if any(m.get("status") == "failed" for m in medias):
                raise RuntimeError(f"Task failed: {task_id}")
            rs = lambda m: m.get("resource_status") if m.get("resource_status") is not None else 0
            if any(rs(m) == 2 for m in medias):
                raise RuntimeError(f"Task failed: {task_id}")
            if all(rs(m) == 1 for m in medias):
                return task
        time.sleep(interval)
    raise TimeoutError(f"Task timed out: {task_id}")


# text_to_music
products = get_products("text_to_music")
task_id  = create_music_task("upbeat electronic, 120 BPM, no vocals", products[0])
result   = poll(task_id)
print(result["medias"][0]["url"])          # mp3 URL
print(result["medias"][0]["duration_str"]) # e.g. "60s"
```

Files in this skill

  • CHANGELOG_CLAWHUB.md7.1 KB
  • INSTALL.md5 KB
  • README.md6.3 KB
  • SCREENSHOT_GUIDE.md7.8 KB
  • SECURITY.md7.8 KB
  • SKILL.md33.3 KB
  • clawhub.json3.7 KB
  • requirements.txt115 B
  • scripts/ima_logger.py3.5 KB
  • scripts/ima_voice_create.py27.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.