> ## Documentation Index
> Fetch the complete documentation index at: https://docs.api.box/llms.txt
> Use this file to discover all available pages before exploring further.

# 快速开始

> 几分钟内开始使用 Suno API 生成AI音乐、歌词和音频内容

## 欢迎使用 Suno API

Suno API 让您能够使用最先进的AI模型创建高质量的AI生成音乐、歌词和音频内容。无论您是在构建音乐应用、自动化创意工作流程，还是开发音频内容，我们的API都为音乐生成和音频处理提供了全面的工具。

<CardGroup cols={3}>
  <Card title="生成音乐" icon="wand-magic-sparkles" href="/cn/suno-api/generate-music">
    创建带或不带歌词的原创音乐曲目
  </Card>

  <Card title="延长音乐" icon="plus" href="/cn/suno-api/extend-music">
    无缝延长现有音乐曲目
  </Card>

  <Card title="生成歌词" icon="list-check" href="/cn/suno-api/generate-lyrics">
    从文本提示创建创意歌词
  </Card>

  <Card title="音乐视频" icon="video" href="/cn/suno-api/create-music-video">
    将音频轨道转换为可视化音乐视频
  </Card>

  <Card title="上传翻唱" icon="upload" href="/cn/suno-api/upload-and-cover-audio">
    将上传的音频转换为新风格
  </Card>

  <Card title="上传扩展" icon="arrow-up-right-from-square" href="/cn/suno-api/upload-and-extend-audio">
    上传音频文件并无缝扩展
  </Card>

  <Card title="人声分离" icon="wave-sine" href="/cn/suno-api/separate-vocals-from-music">
    从音乐中分离人声和伴奏
  </Card>

  <Card title="WAV转换" icon="file-audio" href="/cn/suno-api/convert-to-wav-format">
    将音频转换为高质量WAV格式
  </Card>

  <Card title="获取歌词" icon="align-left" href="/cn/suno-api/get-timestamped-lyrics">
    获取带时间戳的同步歌词
  </Card>

  <Card title="添加伴奏" icon="music" href="/cn/suno-api/add-instrumental">
    为现有音频轨道添加伴奏元素
  </Card>

  <Card title="添加人声" icon="microphone" href="/cn/suno-api/add-vocals">
    为器乐音乐生成人声轨道
  </Card>

  <Card title="增强音乐风格" icon="sparkles" href="/cn/suno-api/boost-music-style">
    使用V4\_5对话式提示词增强风格描述
  </Card>
</CardGroup>

## 身份验证

所有 API 请求都需要使用 Bearer 令牌进行身份验证。请从 [API 密钥管理页面](https://api.box/api-key) 获取您的 API 密钥。

<Warning>
  请妥善保管您的 API 密钥，切勿公开分享。如果怀疑密钥泄露，请立即重置。
</Warning>

### API 基础 URL

```
https://apibox.erweima.ai
```

### 身份验证请求头

```http theme={null}
Authorization: Bearer YOUR_API_KEY
```

## 快速开始指南

### 第一步：生成您的第一个音乐曲目

从一个简单的音乐生成请求开始：

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://apibox.erweima.ai/api/v1/generate" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "一首平静舒缓的钢琴曲，带有柔和的旋律",
      "customMode": false,
      "instrumental": true,
      "model": "V4_5ALL",
      "callBackUrl": "https://your-app.com/callback",
      "vocalGender": "m",
      "styleWeight": 0.65,
      "weirdnessConstraint": 0.3,
      "audioWeight": 0.7
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://apibox.erweima.ai/api/v1/generate', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      prompt: '一首平静舒缓的钢琴曲，带有柔和的旋律',
      customMode: false,
      instrumental: true,
      model: 'V4_5ALL',
      callBackUrl: 'https://your-app.com/callback',
      vocalGender: 'm',
      styleWeight: 0.65,
      weirdnessConstraint: 0.3,
      audioWeight: 0.7
    })
  });

  const data = await response.json();
  console.log('任务ID:', data.data.taskId);
  ```

  ```python Python theme={null}
  import requests

  url = "https://apibox.erweima.ai/api/v1/generate"
  headers = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json"
  }

  payload = {
      "prompt": "一首平静舒缓的钢琴曲，带有柔和的旋律",
      "customMode": False,
      "instrumental": True,
      "model": "V4_5ALL",
      "callBackUrl": "https://your-app.com/callback",
      "vocalGender": "m",
      "styleWeight": 0.65,
      "weirdnessConstraint": 0.3,
      "audioWeight": 0.7
  }

  response = requests.post(url, json=payload, headers=headers)
  result = response.json()

  print(f"任务ID: {result['data']['taskId']}")
  ```

  ```php PHP theme={null}
  <?php
  $url = 'https://apibox.erweima.ai/api/v1/generate';
  $headers = [
      'Authorization: Bearer YOUR_API_KEY',
      'Content-Type: application/json'
  ];

  $payload = [
      'prompt' => '一首平静舒缓的钢琴曲，带有柔和的旋律',
      'customMode' => false,
      'instrumental' => true,
      'model' => 'V4_5ALL',
      'callBackUrl' => 'https://your-app.com/callback',
      'vocalGender' => 'm',
      'styleWeight' => 0.65,
      'weirdnessConstraint' => 0.3,
      'audioWeight' => 0.7
  ];

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

  $response = curl_exec($ch);
  curl_close($ch);

  $result = json_decode($response, true);
  echo "任务ID: " . $result['data']['taskId'];
  ?>
  ```
</CodeGroup>

### 第二步：检查任务状态

使用返回的任务ID检查生成状态：

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://apibox.erweima.ai/api/v1/generate/record-info?taskId=YOUR_TASK_ID" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(`https://apibox.erweima.ai/api/v1/generate/record-info?taskId=${taskId}`, {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  });

  const result = await response.json();

  if (result.data.status === 'SUCCESS') {
    console.log('生成完成！');
    console.log('音频轨道:', result.data.response.data);
  } else if (result.data.status === 'PENDING') {
    console.log('正在生成中...');
  } else {
    console.log('生成失败:', result.data.status);
  }
  ```

  ```python Python theme={null}
  import requests
  import time

  def check_task_status(task_id, api_key):
      url = f"https://apibox.erweima.ai/api/v1/generate/record-info?taskId={task_id}"
      headers = {"Authorization": f"Bearer {api_key}"}
      
      response = requests.get(url, headers=headers)
      result = response.json()
      
      status = result['data']['status']
      
      if status == 'SUCCESS':
          print("生成完成！")
          tracks = result['data']['response']['data']
          for i, track in enumerate(tracks):
              print(f"音轨 {i+1}: {track['audio_url']}")
          return tracks
      elif status == 'PENDING':
          print("正在生成中...")
          return None
      else:
          print(f"生成失败: {status}")
          return None

  # 轮询直到完成
  task_id = "YOUR_TASK_ID"
  while True:
      tracks = check_task_status(task_id, "YOUR_API_KEY")
      if tracks:
          break
      time.sleep(30)  # 等待30秒后再次检查
  ```
</CodeGroup>

### 响应格式

**成功响应：**

```json theme={null}
{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "5c79****be8e"
  }
}
```

**任务状态响应：**

```json theme={null}
{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "5c79****be8e",
    "status": "SUCCESS",
    "response": {
      "data": [
        {
          "id": "8551****662c",
          "audio_url": "https://example.cn/****.mp3",
          "stream_audio_url": "https://example.cn/****",
          "image_url": "https://example.cn/****.jpeg",
          "prompt": "一首平静舒缓的钢琴曲",
          "title": "宁静钢琴",
          "tags": "平静, 舒缓, 钢琴",
          "duration": 198.44,
          "createTime": "2025-01-01 00:00:00"
        }
      ]
    }
  }
}
```

## 核心功能

* **文本转音乐**：输入文字描述，生成相应的音乐作品
* **延长音乐**：基于现有音频，无缝创建更长版本
* **生成歌词**：从创意提示生成结构化歌词内容
* **上传翻唱**：上传音频文件，转换为不同的音乐风格
* **上传扩展**：上传音频文件并在保持风格的同时无缝扩展
* **人声分离**：将音乐分离为人声、伴奏等独立轨道，支持高级干声分离
* **格式转换**：支持WAV等多种高质量音频格式输出
* **音乐视频**：将音频转换为视觉化的音乐视频
* **添加人声**：为现有的器乐音乐生成人声轨道
* **添加伴奏**：为人声轨道创建器乐伴奏
* **风格增强**：使用V4\_5+对话式提示词提升和优化现有音乐的风格特色
* **带时间戳歌词**：获取同步歌词用于卡拉OK式应用

## AI 模型

为您的需求选择合适的模型：

<CardGroup cols={3}>
  <Card title="V4_5ALL" icon="list-check">
    **扩展功能**

    支持更长的歌词（5000字符）和风格描述（1000字符）
  </Card>

  <Card title="V4" icon="wand-magic-sparkles">
    **改进的人声**

    最长4分钟，增强的人声质量
  </Card>

  <Card title="V4_5" icon="rocket">
    **更好的歌曲结构**

    最长1分钟，改进的歌曲组织
  </Card>

  <Card title="V4_5PLUS" icon="image">
    **更丰富的音色**

    最长8分钟，新的创作方式
  </Card>

  <Card title="V5" icon="star">
    **最新模型**

    增强的质量和功能
  </Card>

  <Card title="V5_5" icon="sparkles">
    **个性化声线**

    释放你的声音：定制模型，贴合你的独特品味 — 适用接口下与 V5 参数与限制一致
  </Card>
</CardGroup>

## 生成模式

<ParamField path="customMode" type="boolean" required>
  控制参数复杂度：

  * `false`: 简单模式，仅需要提示词
  * `true`: 高级模式，需要风格和标题
</ParamField>

<ParamField path="instrumental" type="boolean" required>
  决定音乐是否包含人声：

  * `true`: 仅纯音乐（无歌词）
  * `false`: 包含人声/歌词
</ParamField>

## 关键参数

<ParamField path="prompt" type="string" required>
  对所需音乐的文本描述。请具体说明流派、情绪和乐器。

  **字符限制：**

  * 非自定义模式：500字符
  * 自定义模式（V4）：3000字符
  * 自定义模式（V4\_5, V4\_5PLUS, V5, V5\_5 & V4\_5ALL）：5000字符
</ParamField>

<ParamField path="style" type="string">
  音乐风格规范（仅自定义模式）。

  **示例：** 爵士、古典、电子、流行、摇滚、嘻哈

  **字符限制：**

  * V4：200字符
  * V4\_5, V4\_5PLUS, V5, V5\_5 & V4\_5ALL：1000字符
</ParamField>

<ParamField path="title" type="string">
  生成音乐曲目的标题（仅自定义模式）。

  **最大长度：** 80字符
</ParamField>

## 完整工作流程示例

以下是一个生成带歌词音乐并等待完成的完整示例：

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    class SunoAPI {
      constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://apibox.erweima.ai/api/v1';
      }
      
      async generateMusic(prompt, options = {}) {
        const response = await fetch(`${this.baseUrl}/generate`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            prompt,
            customMode: options.customMode || false,
            instrumental: options.instrumental || false,
            model: options.model || 'V4_5ALL',
            style: options.style,
            title: options.title,
            negativeTags: options.negativeTags,
            callBackUrl: options.callBackUrl || 'https://your-app.com/callback',
            vocalGender: options.vocalGender,
            styleWeight: options.styleWeight,
            weirdnessConstraint: options.weirdnessConstraint,
            audioWeight: options.audioWeight
          })
        });
        
        const result = await response.json();
        if (result.code !== 200) {
          throw new Error(`生成失败: ${result.msg}`);
        }
        
        return result.data.taskId;
      }
      
      async extendMusic(audioId, options = {}) {
        const response = await fetch(`${this.baseUrl}/generate/extend`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            audioId,
            defaultParamFlag: options.defaultParamFlag || false,
            model: options.model || 'V4_5ALL',
            prompt: options.prompt,
            style: options.style,
            title: options.title,
            continueAt: options.continueAt,
            callBackUrl: options.callBackUrl || 'https://your-app.com/callback',
            vocalGender: options.vocalGender,
            styleWeight: options.styleWeight,
            weirdnessConstraint: options.weirdnessConstraint,
            audioWeight: options.audioWeight
          })
        });
        
        const result = await response.json();
        if (result.code !== 200) {
          throw new Error(`延长失败: ${result.msg}`);
        }
        
        return result.data.taskId;
      }
      
      async generateLyrics(prompt, callBackUrl) {
        const response = await fetch(`${this.baseUrl}/lyrics`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            prompt,
            callBackUrl
          })
        });
        
        const result = await response.json();
        if (result.code !== 200) {
          throw new Error(`歌词生成失败: ${result.msg}`);
        }
        
        return result.data.taskId;
      }
      
      async addVocals(uploadUrl, prompt, style, title, negativeTags, options = {}) {
        const response = await fetch(`${this.baseUrl}/generate/add-vocals`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            uploadUrl,
            prompt,
            style,
            title,
            negativeTags,
            model: options.model || 'V4_5PLUS',
            callBackUrl: options.callBackUrl || 'https://your-app.com/callback',
            vocalGender: options.vocalGender,
            styleWeight: options.styleWeight,
            weirdnessConstraint: options.weirdnessConstraint,
            audioWeight: options.audioWeight
          })
        });
        
        const result = await response.json();
        if (result.code !== 200) {
          throw new Error(`添加人声失败: ${result.msg}`);
        }
        
        return result.data.taskId;
      }
      
      async addInstrumental(uploadUrl, title, tags, negativeTags, options = {}) {
        const response = await fetch(`${this.baseUrl}/generate/add-instrumental`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${this.apiKey}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            uploadUrl,
            title,
            tags,
            negativeTags,
            model: options.model || 'V4_5PLUS',
            callBackUrl: options.callBackUrl || 'https://your-app.com/callback',
            vocalGender: options.vocalGender,
            styleWeight: options.styleWeight,
            weirdnessConstraint: options.weirdnessConstraint,
            audioWeight: options.audioWeight
          })
        });
        
        const result = await response.json();
        if (result.code !== 200) {
          throw new Error(`添加伴奏失败: ${result.msg}`);
        }
        
        return result.data.taskId;
      }
      
      async waitForCompletion(taskId, maxWaitTime = 600000) { // 最长等待10分钟
        const startTime = Date.now();
        
        while (Date.now() - startTime < maxWaitTime) {
          const status = await this.getTaskStatus(taskId);
          
          if (status.status === 'SUCCESS') {
            return status.response;
          } else if (status.status.includes('FAILED') || status.status === 'SENSITIVE_WORD_ERROR') {
            throw new Error(`生成失败: ${status.errorMessage || status.status}`);
          }
          
          // 等待10秒后再次检查
          await new Promise(resolve => setTimeout(resolve, 10000));
        }
        
        throw new Error('生成超时');
      }
      
      async getTaskStatus(taskId) {
        const response = await fetch(`${this.baseUrl}/generate/record-info?taskId=${taskId}`, {
          headers: {
            'Authorization': `Bearer ${this.apiKey}`
          }
        });
        
        const result = await response.json();
        return result.data;
      }
      
      async getRemainingCredits() {
        const response = await fetch(`${this.baseUrl}/generate/credit`, {
          headers: {
            'Authorization': `Bearer ${this.apiKey}`
          }
        });
        
        const result = await response.json();
        return result.data.credits;
      }
    }

    // 使用示例
    async function main() {
      const api = new SunoAPI('YOUR_API_KEY');
      
      try {
        // 检查剩余积分
        const credits = await api.getRemainingCredits();
        console.log(`剩余积分: ${credits}`);
        
        // 生成带歌词的音乐
        console.log('开始生成音乐...');
        const taskId = await api.generateMusic(
          '一首关于童年回忆的怀旧民谣',
          { 
            customMode: true,
            instrumental: false,
            model: 'V4_5',
            style: '民谣, 原声吉他, 怀旧',
            title: '童年梦想'
          }
        );
        
        // 等待完成
        console.log(`任务ID: ${taskId}。等待完成...`);
        const result = await api.waitForCompletion(taskId);
        
        console.log('音乐生成成功！');
        console.log('生成的曲目：');
        result.data.forEach((track, index) => {
          console.log(`曲目 ${index + 1}:`);
          console.log(`  标题: ${track.title}`);
          console.log(`  音频URL: ${track.audio_url}`);
          console.log(`  时长: ${track.duration}秒`);
          console.log(`  标签: ${track.tags}`);
        });
        
        // 延长第一个曲目
        const firstTrack = result.data[0];
        console.log('\n延长第一个曲目...');
        const extendTaskId = await api.extendMusic(firstTrack.id, {
          defaultParamFlag: true,
          prompt: '继续一个充满希望的副歌',
          style: '民谣, 振奋',
          title: '童年梦想延长版',
          continueAt: 60,
          model: 'V4_5'
        });
        
        const extendResult = await api.waitForCompletion(extendTaskId);
        console.log('音乐延长成功！');
        console.log('延长曲目URL:', extendResult.data[0].audio_url);
        
      } catch (error) {
        console.error('错误:', error.message);
      }
    }

    main();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests
    import time

    class SunoAPI:
        def __init__(self, api_key):
            self.api_key = api_key
            self.base_url = 'https://apibox.erweima.ai/api/v1'
            self.headers = {
                'Authorization': f'Bearer {api_key}',
                'Content-Type': 'application/json'
            }
        
        def generate_music(self, prompt, **options):
            data = {
                'prompt': prompt,
                'customMode': options.get('customMode', False),
                'instrumental': options.get('instrumental', False),
                'model': options.get('model', 'V4_5ALL'),
                'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback')
            }
            
            if options.get('style'):
                data['style'] = options['style']
            if options.get('title'):
                data['title'] = options['title']
            if options.get('negativeTags'):
                data['negativeTags'] = options['negativeTags']
            if options.get('vocalGender'):
                data['vocalGender'] = options['vocalGender']
            if options.get('styleWeight'):
                data['styleWeight'] = options['styleWeight']
            if options.get('weirdnessConstraint'):
                data['weirdnessConstraint'] = options['weirdnessConstraint']
            if options.get('audioWeight'):
                data['audioWeight'] = options['audioWeight']
            
            response = requests.post(f'{self.base_url}/generate', 
                                   headers=self.headers, json=data)
            result = response.json()
            
            if result['code'] != 200:
                raise Exception(f"生成失败: {result['msg']}")
            
            return result['data']['taskId']
        
        def extend_music(self, audio_id, **options):
            data = {
                'audioId': audio_id,
                'defaultParamFlag': options.get('defaultParamFlag', False),
                'model': options.get('model', 'V4_5ALL'),
                'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback')
            }
            
            if options.get('prompt'):
                data['prompt'] = options['prompt']
            if options.get('style'):
                data['style'] = options['style']
            if options.get('title'):
                data['title'] = options['title']
            if options.get('continueAt'):
                data['continueAt'] = options['continueAt']
            if options.get('vocalGender'):
                data['vocalGender'] = options['vocalGender']
            if options.get('styleWeight'):
                data['styleWeight'] = options['styleWeight']
            if options.get('weirdnessConstraint'):
                data['weirdnessConstraint'] = options['weirdnessConstraint']
            if options.get('audioWeight'):
                data['audioWeight'] = options['audioWeight']
            
            response = requests.post(f'{self.base_url}/generate/extend', 
                                   headers=self.headers, json=data)
            result = response.json()
            
            if result['code'] != 200:
                raise Exception(f"延长失败: {result['msg']}")
            
            return result['data']['taskId']
        
        def generate_lyrics(self, prompt, callback_url):
            data = {
                'prompt': prompt,
                'callBackUrl': callback_url
            }
            
            response = requests.post(f'{self.base_url}/lyrics', 
                                   headers=self.headers, json=data)
            result = response.json()
            
            if result['code'] != 200:
                raise Exception(f"歌词生成失败: {result['msg']}")
            
            return result['data']['taskId']
        
        def add_vocals(self, upload_url, prompt, style, title, negative_tags, **options):
            data = {
                'uploadUrl': upload_url,
                'prompt': prompt,
                'style': style,
                'title': title,
                'negativeTags': negative_tags,
                'model': options.get('model', 'V4_5PLUS'),
                'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback')
            }
            
            if options.get('vocalGender'):
                data['vocalGender'] = options['vocalGender']
            if options.get('styleWeight'):
                data['styleWeight'] = options['styleWeight']
            if options.get('weirdnessConstraint'):
                data['weirdnessConstraint'] = options['weirdnessConstraint']
            if options.get('audioWeight'):
                data['audioWeight'] = options['audioWeight']
            
            response = requests.post(f'{self.base_url}/generate/add-vocals', 
                                   headers=self.headers, json=data)
            result = response.json()
            
            if result['code'] != 200:
                raise Exception(f"添加人声失败: {result['msg']}")
            
            return result['data']['taskId']
        
        def add_instrumental(self, upload_url, title, tags, negative_tags, **options):
            data = {
                'uploadUrl': upload_url,
                'title': title,
                'tags': tags,
                'negativeTags': negative_tags,
                'model': options.get('model', 'V4_5PLUS'),
                'callBackUrl': options.get('callBackUrl', 'https://your-app.com/callback')
            }
            
            if options.get('vocalGender'):
                data['vocalGender'] = options['vocalGender']
            if options.get('styleWeight'):
                data['styleWeight'] = options['styleWeight']
            if options.get('weirdnessConstraint'):
                data['weirdnessConstraint'] = options['weirdnessConstraint']
            if options.get('audioWeight'):
                data['audioWeight'] = options['audioWeight']
            
            response = requests.post(f'{self.base_url}/generate/add-instrumental', 
                                   headers=self.headers, json=data)
            result = response.json()
            
            if result['code'] != 200:
                raise Exception(f"添加伴奏失败: {result['msg']}")
            
            return result['data']['taskId']
        
        def wait_for_completion(self, task_id, max_wait_time=600):
            start_time = time.time()
            
            while time.time() - start_time < max_wait_time:
                status = self.get_task_status(task_id)
                
                if status['status'] == 'SUCCESS':
                    return status['response']
                elif 'FAILED' in status['status'] or status['status'] == 'SENSITIVE_WORD_ERROR':
                    error_msg = status.get('errorMessage', status['status'])
                    raise Exception(f"生成失败: {error_msg}")
                
                time.sleep(10)  # 等待10秒
            
            raise Exception('生成超时')
        
        def get_task_status(self, task_id):
            response = requests.get(f'{self.base_url}/generate/record-info?taskId={task_id}',
                                  headers={'Authorization': f'Bearer {self.api_key}'})
            return response.json()['data']
        
        def get_remaining_credits(self):
            response = requests.get(f'{self.base_url}/generate/credit',
                                  headers={'Authorization': f'Bearer {self.api_key}'})
            return response.json()['data']['credits']

    # 使用示例
    def main():
        api = SunoAPI('YOUR_API_KEY')
        
        try:
            # 检查剩余积分
            credits = api.get_remaining_credits()
            print(f'剩余积分: {credits}')
            
            # 生成带歌词的音乐
            print('开始生成音乐...')
            task_id = api.generate_music(
                '一首关于童年回忆的怀旧民谣',
                customMode=True,
                instrumental=False,
                model='V4_5',
                style='民谣, 原声吉他, 怀旧',
                title='童年梦想'
            )
            
            # 等待完成
            print(f'任务ID: {task_id}。等待完成...')
            result = api.wait_for_completion(task_id)
            
            print('音乐生成成功！')
            print('生成的曲目：')
            for i, track in enumerate(result['data']):
                print(f"曲目 {i + 1}:")
                print(f"  标题: {track['title']}")
                print(f"  音频URL: {track['audio_url']}")
                print(f"  时长: {track['duration']}秒")
                print(f"  标签: {track['tags']}")
            
            # 延长第一个曲目
            first_track = result['data'][0]
            print('\n延长第一个曲目...')
            extend_task_id = api.extend_music(
                first_track['id'],
                defaultParamFlag=True,
                prompt='继续一个充满希望的副歌',
                style='民谣, 振奋',
                title='童年梦想延长版',
                continueAt=60,
                model='V4_5'
            )
            
            extend_result = api.wait_for_completion(extend_task_id)
            print('音乐延长成功！')
            print(f"延长曲目URL: {extend_result['data'][0]['audio_url']}")
            
        except Exception as error:
            print(f'错误: {error}')

    if __name__ == '__main__':
        main()
    ```
  </Tab>
</Tabs>

## 状态码和任务状态

<ResponseField name="PENDING" type="处理中">
  任务正在等待处理或正在生成中
</ResponseField>

<ResponseField name="TEXT_SUCCESS" type="部分完成">
  歌词/文本生成成功完成
</ResponseField>

<ResponseField name="FIRST_SUCCESS" type="部分完成">
  第一个曲目生成完成
</ResponseField>

<ResponseField name="SUCCESS" type="完成">
  所有曲目生成成功
</ResponseField>

<ResponseField name="CREATE_TASK_FAILED" type="错误">
  创建任务失败
</ResponseField>

<ResponseField name="GENERATE_AUDIO_FAILED" type="错误">
  生成音频失败
</ResponseField>

<ResponseField name="SENSITIVE_WORD_ERROR" type="错误">
  内容因敏感词被过滤
</ResponseField>

## HTTP 状态码

<ResponseField name="200" type="成功">
  请求成功
</ResponseField>

<ResponseField name="400" type="参数错误">
  请求参数错误或缺失
</ResponseField>

<ResponseField name="401" type="未授权">
  没有访问权限，检查API密钥
</ResponseField>

<ResponseField name="404" type="未找到">
  请求方式或路径错误
</ResponseField>

<ResponseField name="405" type="调用限制">
  调用超过限制
</ResponseField>

<ResponseField name="413" type="内容过长">
  提示词或主题过长
</ResponseField>

<ResponseField name="429" type="积分不足">
  账户积分不足
</ResponseField>

<ResponseField name="455" type="维护中">
  网站维护中
</ResponseField>

<ResponseField name="500" type="服务器错误">
  服务器内部错误
</ResponseField>

## 最佳实践

<AccordionGroup>
  <Accordion title="提示词工程">
    * 具体说明流派、情绪和乐器
    * 使用描述性形容词获得更好的风格控制
    * 包含节拍和能量水平描述
    * 参考音乐时代或特定艺术家进行风格指导
  </Accordion>

  <Accordion title="模型选择">
    * V4\_5ALL：最适合需要更长歌词和风格描述的项目
    * V4：当人声质量最重要时选择
    * V4\_5：用于更好的歌曲结构，最长1分钟
    * V4\_5PLUS：选择最高质量和最长的曲目
  </Accordion>

  <Accordion title="性能优化">
    * 使用回调而不是频繁轮询
    * 从非自定义模式开始满足简单需求
    * 实施适当的错误处理以应对生成失败
    * 缓存生成内容，因为文件14-15天后到期
  </Accordion>

  <Accordion title="内容指南">
    * 避免在提示中使用受版权保护的材料
    * 使用原创歌词和音乐描述
    * 注意歌词内容的内容政策
    * 测试提示变化以避免敏感词过滤器
  </Accordion>
</AccordionGroup>

## 错误处理

<AccordionGroup>
  <Accordion title="内容政策违反（代码 400）">
    ```javascript theme={null}
    try {
      const taskId = await api.generateMusic('受版权保护的歌词');
    } catch (error) {
      if (error.data.code === 400) {
        console.log('请仅使用原创内容');
      }
    }
    ```
  </Accordion>

  <Accordion title="积分不足（代码 429）">
    ```javascript theme={null}
    try {
      const taskId = await api.generateMusic('原创作品');
    } catch (error) {
      if (error.data.code === 429) {
        console.log('请为您的账户添加更多积分');
      }
    }
    ```
  </Accordion>

  <Accordion title="速率限制（代码 405）">
    ```javascript theme={null}
    const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));

    async function generateWithRetry(prompt, options, maxRetries = 3) {
      for (let i = 0; i < maxRetries; i++) {
        try {
          return await api.generateMusic(prompt, options);
        } catch (error) {
          if (error.data.code === 405 && i < maxRetries - 1) {
            await delay(Math.pow(2, i) * 1000); // 指数退避
            continue;
          }
          throw error;
        }
      }
    }
    ```
  </Accordion>
</AccordionGroup>

## 支持

<Info>
  需要帮助吗？我们的技术支持团队随时为您提供帮助。

  * **邮箱**: [support@api.box](mailto:support@api.box)
  * **文档**: 查看详细的API文档和示例
  * **API状态**: 查看我们的状态页面了解实时API健康状况
</Info>

***

准备开始创作令人惊叹的AI音乐了吗？[获取您的API密钥](https://api.box/api-key)，立即开始创作！
