Skip to content

Latest commit

 

History

History
353 lines (270 loc) · 10 KB

File metadata and controls

353 lines (270 loc) · 10 KB

FunkLab × Suno API — Design Técnico de Integração

Referência: Módulo "Reference Lab" — ideação e referência, não engine principal.


1. Princípios

  • Opcional: FunkLab funciona sem Suno. A integração é um módulo adicional.
  • Isolado: Toda comunicação com Suno passa por uma camada interna.
  • Referência: Áudio Suno → input para análise FunkLab → extração de grooves/BPM.
  • Não substitui: Engine local continua sendo o core do produto.

2. Arquitetura

UI (Next.js)
    │
    ▼
FunkLab API (FastAPI)
    │
    ├──► Engine local (sketch, bassline, analyze)
    │
    └──► Suno Integration Layer
              │
              ├── suno_client.py    # HTTP client
              ├── idea_service.py   # orquestração
              └── references/       # armazenamento

Fluxo Reference Lab:

prompt → Suno gera áudio → download → analyze → salvar em references/

3. Estrutura de Arquivos

funklab/
├── api/
│   ├── integrations/
│   │   __init__.py
│   │   suno_client.py      # Cliente HTTP para api.sunoapi.org
│   │
│   ├── idea_service.py     # Orquestra generate + analyze + save
│   ├── routes_idea.py      # POST /idea/generate, GET /idea/{id}, POST /idea/{id}/analyze
│   └── schemas.py          # + IdeaGenerateRequest, IdeaStatusResponse, etc.
│
├── projects/
│   └── references/         # Ideias geradas pelo Suno
│       └── {idea_id}/
│           ├── manifest.json
│           ├── audio_0.mp3
│           ├── audio_1.mp3
│           └── analysis_0.json
│
└── .env.example
    SUNO_API_KEY=
    SUNO_API_BASE=https://api.sunoapi.org

4. Suno Client (api/integrations/suno_client.py)

Responsabilidades

  • Chamar POST /api/v1/generate (geração de música)
  • Chamar GET /api/v1/generate/record-info?taskId=... (polling)
  • Baixar áudio de audioUrl ou streamAudioUrl

Configuração para Reference Lab

  • customMode: false — mais simples, só prompt obrigatório
  • instrumental: true — referências instrumentais para análise de groove
  • model: V4_5 ou V4_5ALL — bom custo/qualidade, até 8 min
  • callBackUrl — opcional; preferir polling para controle

Interface

# api/integrations/suno_client.py

class SunoClient:
    def __init__(self, api_key: str, base_url: str = "https://api.sunoapi.org"):
        ...

    async def generate(
        self,
        prompt: str,
        instrumental: bool = True,
        model: str = "V4_5",
        custom_mode: bool = False,
    ) -> str:
        """Envia geração. Retorna task_id."""

    async def get_status(self, task_id: str) -> SunoTaskStatus:
        """Poll status. Retorna status, suno_data quando SUCCESS."""

    async def download_audio(self, url: str, dest: Path) -> Path:
        """Baixa MP3 e salva em dest."""

Suno API — Request de exemplo (Non-custom, instrumental)

{
  "prompt": "Brazilian funk groove, 130 BPM, deep bass, minimal drums",
  "customMode": false,
  "instrumental": true,
  "model": "V4_5",
  "callBackUrl": ""
}

Response: { "code": 200, "data": { "taskId": "5c79****be8e" } }

Polling até SUCCESS

  • Chamar GET /api/v1/generate/record-info?taskId=... a cada 5–10 s
  • Status: PENDINGTEXT_SUCCESSFIRST_SUCCESSSUCCESS
  • Em SUCCESS, data.response.sunoData é array de tracks (até 2)
  • Cada track: id, audioUrl, streamAudioUrl, duration, title, etc.

5. Idea Service (api/idea_service.py)

Fluxo

  1. run_idea_generate(prompt, model?)

    • Chama SunoClient.generate()
    • Cria pasta projects/references/{idea_id}
    • Salva manifest.json com task_id, prompt, status: pending
    • Retorna idea_id (UUID) e task_id
  2. get_idea_status(idea_id)

    • Lê manifest
    • Se status == pending, faz polling no Suno
    • Atualiza manifest
    • Retorna status + tracks quando pronto
  3. run_idea_analyze(idea_id, track_index=0)

    • Garante que áudio já foi baixado (se não, baixa)
    • Chama run_analyze(audio_path) (engine existente)
    • Salva analysis_{track_index}.json
    • Atualiza manifest com resultado
    • Retorna AnalyzeResponse

Manifest

{
  "idea_id": "uuid",
  "task_id": "suno_task_id",
  "prompt": "...",
  "model": "V4_5",
  "status": "complete",
  "created_at": "ISO8601",
  "tracks": [
    {
      "id": "suno_audio_id",
      "audio_url": "https://...",
      "local_path": "audio_0.mp3",
      "duration": 120.5,
      "analysis": { "bpm": 130, "pattern": "...", ... }
    }
  ]
}

6. Rotas da API (api/routes_idea.py)

Método Endpoint Descrição
POST /api/v1/idea/generate Inicia geração Suno, retorna idea_id
GET /api/v1/idea/{idea_id} Status da ideia + tracks (com polling se pendente)
POST /api/v1/idea/{idea_id}/analyze Analisa track no FunkLab, retorna BPM/groove
GET /api/v1/idea/{idea_id}/files/{path} Serve áudio ou JSON (proxy para projeto)

Schemas

# api/schemas.py (adicionar)

class IdeaGenerateRequest(BaseModel):
    prompt: str = Field(..., max_length=500)
    model: str = Field(default="V4_5")
    instrumental: bool = Field(default=True)

class IdeaGenerateResponse(BaseModel):
    idea_id: str
    task_id: str
    status: str = "pending"
    message: str = "Geração iniciada. Use GET /idea/{id} para acompanhar."

class IdeaTrackInfo(BaseModel):
    id: str
    audio_url: str | None
    local_path: str | None
    duration: float | None
    analysis: dict | None = None

class IdeaStatusResponse(BaseModel):
    idea_id: str
    status: str  # pending, complete, failed
    prompt: str
    tracks: list[IdeaTrackInfo]
    error: str | None = None

Comportamento

  • POST /idea/generate

    • Se SUNO_API_KEY não estiver configurado → 503 Service Unavailable
    • Retorna idea_id imediatamente
    • Geração é assíncrona
  • GET /idea/{idea_id}

    • Se status == pending, faz até 1 poll no Suno
    • Se SUCCESS, baixa áudios para projects/references/{idea_id}/
    • Retorna status + tracks
  • POST /idea/{idea_id}/analyze

    • Body opcional: { "track_index": 0 }
    • Usa run_analyze existente
    • Persiste análise no manifest e retorna AnalyzeResponse

7. Variáveis de Ambiente

# .env ou .env.local
SUNO_API_KEY=              # Obrigatório para o módulo Idea
SUNO_API_BASE=https://api.sunoapi.org
  • Se SUNO_API_KEY vazio: rotas /idea/* retornam 503 com mensagem clara.

8. Prompts para Referência

Sugestões de prompt para geração instrumental focada em groove:

Brazilian funk groove, 130 BPM, deep bass, minimal drums, swing feel
Phonk style, 140 BPM, heavy 808, dark atmosphere, instrumental
Tech house loop, 125 BPM, rolling bassline, percussion, no vocals
Mandelão groove, 128 BPM, brasileiro, instrumental

9. Tratamento de Erros

Código Suno Ação
401 Log + 503 "Suno API: credenciais inválidas"
429 503 "Créditos insuficientes na Suno API"
430 503 "Rate limit. Tente em alguns segundos"
500 503 "Suno API temporariamente indisponível"
SENSITIVE_WORD_ERROR 400 "Prompt contém termos bloqueados"
GENERATE_AUDIO_FAILED 500 "Falha na geração. Tente outro prompt"

10. Checklist Fase 1 (Implementação)

  • Criar api/integrations/__init__.py
  • Criar api/integrations/suno_client.py (generate, get_status, download_audio)
  • Criar api/idea_service.py (run_idea_generate, get_idea_status, run_idea_analyze)
  • Adicionar schemas em api/schemas.py
  • Criar api/routes_idea.py
  • Registrar router em api/server.py
  • Criar projects/references/.gitkeep
  • Adicionar SUNO_API_KEY em .env.example
  • Tratar ausência de API key (503)
  • Testar fluxo: generate → poll → analyze

11. Fase 2 — UI /idea-generator (futuro)

  • Form: prompt, model (select), instrumental (checkbox)
  • Botão "Gerar referência"
  • Área de status (polling ou SSE)
  • Quando pronto: player de áudio, botão "Analisar no FunkLab"
  • Exibir resultado da análise (BPM, pattern, etc.)

12. Fase 3 — Biblioteca de Referências (futuro)

  • Listar ideias em projects/references/
  • Endpoint GET /api/v1/references (opcional)
  • Filtrar por prompt, BPM, data

13. Prompt para Cursor Pro (Fase 1)

Cole o bloco abaixo para implementar a Fase 1:

Implementar a integração Suno conforme docs/SUNO_INTEGRATION_DESIGN.md.

Tarefas:
1. Criar api/integrations/suno_client.py com SunoClient (generate, get_status, download_audio).
   - Usar httpx para requests assíncronos.
   - generate: POST /api/v1/generate com customMode=false, instrumental=true.
   - get_status: GET /api/v1/generate/record-info?taskId=...
   - download_audio: GET na URL do áudio, salvar em Path.

2. Criar api/idea_service.py com run_idea_generate, get_idea_status, run_idea_analyze.
   - idea_id = uuid4().hex
   - Persistir manifest.json em projects/references/{idea_id}/
   - Integrar com engine_service.run_analyze para análise.

3. Adicionar schemas IdeaGenerateRequest, IdeaGenerateResponse, IdeaStatusResponse, IdeaTrackInfo em api/schemas.py.

4. Criar api/routes_idea.py com POST /generate, GET /{idea_id}, POST /{idea_id}/analyze.
   - Retornar 503 se SUNO_API_KEY não configurado.
   - Incluir router em api/server.py com prefix /api/v1/idea e tags ["idea"].

5. Criar projects/references/.gitkeep e atualizar .env.example com SUNO_API_KEY.

6. Garantir que httpx esteja em requirements/dependencies se necessário.

Referências