Developer Guide

Kie AI Integration Guide

Hướng dẫn chi tiết tích hợp provider Kie AI vào OpenStory

Hướng Dẫn Tích Hợp Provider Kie AI (Async Media Gateway)

Tài liệu hướng dẫn chi tiết dành cho kỹ sư phần mềm / team phát triển để triển khai tích hợp dịch vụ Kie AI vào bất kỳ source code / hệ thống nào (Node.js, TypeScript, Python, Go, NestJS, Express, v.v.).


1. Tổng Quan Về Kie AI

Kie AI là một nền tảng Aggregator Gateway cung cấp một API Key duy nhất để truy cập đa dạng các mô hình sinh nội dung đa phương tiện (Generative Media):

  • Image: xAI Grok Imagine, OpenAI GPT Image 2 (Text-to-Image, Image-to-Image).
  • Video: xAI Grok Video 1.5, Video Extend, Google Veo 3.1 (Text-to-Video, Image-to-Video).
  • Music & Audio: Suno V5, Suno V5.5, Suno Extend, Suno Cover/Remix, Suno Lyrics.
  • Text-to-Speech (TTS): ElevenLabs TTS, Google Gemini 3.1 Flash TTS (hỗ trợ đối thoại nhiều nhân vật multi-speaker trong cùng một lượt gọi).

Vòng Đời Tác Vụ Bất Đồng Bộ (Async Task Lifecycle)

Toàn bộ các tác vụ media trên Kie AI đều vận hành theo cơ chế bất đồng bộ:


2. Thông Số Kỹ Thuật Cơ Bản

  • Base URL chính: https://api.kie.ai
  • File Upload Base URL: https://kieai.redpandaai.co (hoặc https://api.kie.ai)
  • Authentication: Bearer Token
    Authorization: Bearer <YOUR_KIE_API_KEY>
    Content-Type: application/json
  • Lấy API Key: Truy cập kie.ai/api-key.
  • Biến môi trường khuyến nghị:
    KIE_API_KEY=your_kie_api_key_here
    KIE_BASE_URL=https://api.kie.ai
    KIE_MAX_POLL_MS=600000            # Timeout tối đa 10 phút (mili-giây)
    KIE_POLL_INTERVAL_MS=3000         # Chu kỳ thăm dò 3 giây
    KIE_CALLBACK_URL=https://...      # URL Webhook (nếu không dùng polling thuần)

3. Danh Mục Mô Hình (Model Catalog) & Wire Names

Nên định nghĩa một bảng ánh xạ nội bộ giữa Model ID của hệ thống bạn và tên Wire Model thực tế của Kie AI:

3.1. Image Models

Internal Model IDWire Model Name (model)Surface / EndpointMô Tả
kie-grok-imagine-textgrok-imagine/text-to-image/api/v1/jobs/createTaskxAI Grok Text-to-Image
kie-grok-imagine-imagegrok-imagine/image-to-image/api/v1/jobs/createTaskxAI Grok Image-to-Image
kie-gpt-image-textgpt-image-2-text-to-image/api/v1/jobs/createTaskOpenAI GPT Image 2 Text-to-Image
kie-gpt-image-imagegpt-image-2-5-flare-image-to-image/api/v1/jobs/createTaskOpenAI GPT Image 2 Image-to-Image

3.2. Video Models

Internal Model IDWire Model Name (model)Surface / EndpointMô Tả
kie-grok-video-textgrok-imagine-video-1-5-preview/api/v1/jobs/createTaskxAI Grok Video 1.5 Text/Image-to-Video
kie-grok-video-extendgrok-imagine/extend/api/v1/jobs/createTaskKéo dài video cũ thông qua taskId
kie-veo-videoveo3_fast/api/v1/veo/generateGoogle Veo 3 Video Generator
kie-gemini-omni-videogoogle/gemini-omni-flash-1-1/api/v1/jobs/createTaskGoogle Gemini Omni Flash 1.1 Video Gen

3.3. Audio & Music Models (Suno)

Internal Model IDWire Model Name (model)Endpoint Chuyên BiệtMô Tả
kie-suno-v5V5POST /api/v1/generateTạo nhạc Suno V5 hoàn chỉnh (tối đa 8 phút)
kie-suno-v5-5V5_5POST /api/v1/generateTạo nhạc Suno V5.5 chất lượng cao
kie-suno-extendextendPOST /api/v1/generate/extendNối dài bản nhạc trước đó
kie-suno-covercoverPOST /api/v1/suno/cover/generateTạo bản remix/cover phong cách mới
kie-suno-lyricslyricsPOST /api/v1/lyricsSinh lời bài hát theo chủ đề

3.4. Text-To-Speech (TTS)

Internal Model IDWire Model Name (model)Surface / EndpointMô Tả
kie-elevenlabs-ttselevenlabs/tts/api/v1/jobs/createTaskGiọng đọc ElevenLabs chuẩn quốc tế
kie-gemini-3-1-flash-ttsgoogle/gemini-3-1-flash-tts/api/v1/jobs/createTaskGemini 3.1 Flash TTS đa giọng, hỗ trợ đối thoại nhiều nhân vật

4. Chi Tiết API Endpoints & Request Payloads

4.1. File Base64 Upload API

Dùng để tải ảnh nguồn dạng base64 lên lấy URL công khai trước khi gọi Image-to-Image hoặc Video.

  • Endpoint: POST https://kieai.redpandaai.co/api/file-base64-upload
  • Headers: Bearer Auth + JSON
  • Body:
    {
      "base64Data": "data:image/png;base64,iVBORw0KGgo...",
      "uploadPath": "images/base64",
      "fileName": "reference.png"
    }
  • Response:
    {
      "code": 200,
      "success": true,
      "data": {
        "downloadUrl": "https://cdn.redpandaai.co/files/.../reference.png"
      }
    }

4.2. Image Generation

  • Endpoint: POST https://api.kie.ai/api/v1/jobs/createTask
  • Aspect Ratios được chấp nhận: 1:1, 16:9, 9:16, 3:2, 2:3, auto.

Text-to-Image:

{
  "model": "grok-imagine/text-to-image",
  "input": {
    "prompt": "A futuristic city in mist at sunrise, highly detailed, architectural rendering",
    "aspect_ratio": "16:9"
  }
}

Image-to-Image:

{
  "model": "gpt-image-2-5-flare-image-to-image",
  "input": {
    "prompt": "Transform into anime watercolor style, soft pastel palette",
    "aspect_ratio": "1:1",
    "input_urls": ["https://cdn.redpandaai.co/files/.../reference.png"]
  }
}

4.3. Video Generation

  • Endpoint: POST https://api.kie.ai/api/v1/jobs/createTask
  • Thời lượng: 6 đến 30 giây (mặc định khuyến nghị: 8s).
  • Độ phân giải: 480p, 720p, 1080p.

Text / Image to Video (Grok Video):

{
  "model": "grok-imagine-video-1-5-preview",
  "callBackUrl": "https://api.kie.ai/callback",
  "input": {
    "prompt": "Cinematic camera orbiting an astronaut floating over Earth",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration": 8,
    "mode": "normal",
    "image_urls": ["https://cdn.redpandaai.co/files/.../start_frame.png"]
  }
}

Video Extend (Nối dài video cũ):

{
  "model": "grok-imagine/extend",
  "input": {
    "task_id": "tsk_original_video_task_id",
    "extend_at": 2,
    "extend_times": "6",
    "prompt": "Continue the slow pan upwards into the starfield"
  }
}

4.4. Audio & Music Generation (Suno)

Tạo nhạc mới (/api/v1/generate):

Lưu ý: Endpoint này bắt buộc phải có customMode: true, instrumental: boolean, và callBackUrl.

{
  "model": "V5",
  "prompt": "An upbeat 80s synthwave pop track with energetic drums and retro synths",
  "customMode": true,
  "instrumental": true,
  "callBackUrl": "https://api.kie.ai/callback"
}

Nối dài bài nhạc (/api/v1/generate/extend):

{
  "model": "V5",
  "audioId": "suno_audio_id_from_previous_task",
  "defaultParamFlag": true,
  "prompt": "Add an epic electric guitar solo"
}

4.5. Text-To-Speech (TTS)

ElevenLabs TTS:

{
  "model": "elevenlabs/tts",
  "input": {
    "prompt": "Welcome to our latest technology podcast episode.",
    "voice": "Rachel"
  }
}

Gemini 3.1 Flash TTS (Đối thoại đa nhân vật Multi-turn Dialogue):

Hỗ trợ kịch bản đối thoại nhiều nhân vật với các thẻ phong cách/cảm xúc (style, accent, pace):

{
  "model": "google/gemini-3-1-flash-tts",
  "callBackUrl": "https://api.kie.ai/callback",
  "input": {
    "temperature": 1,
    "speakers": [
      {
        "speaker_id": "Speaker 1",
        "voice_name": "Kore",
        "accent": "Neutral",
        "style": "Natural",
        "pace": "Natural"
      },
      {
        "speaker_id": "Speaker 2",
        "voice_name": "Fenrir",
        "accent": "Neutral",
        "style": "Thoughtful",
        "pace": "Natural"
      }
    ],
    "dialogue_turns": [
      {
        "speaker_id": "Speaker 1",
        "text": "[warm] Chào buổi sáng mọi người, hôm nay chúng ta sẽ bàn về AI."
      },
      {
        "speaker_id": "Speaker 2",
        "text": "[thoughtful] Đúng vậy, một chủ đề rất đáng suy ngẫm trong năm nay."
      }
    ]
  }
}

5. Cơ Chế Polling & Bóc Tách Kết Quả (Result Extraction)

Sau khi gửi request thành công, bạn nhận được:

{
  "code": 200,
  "data": {
    "taskId": "tsk_01jk47abc99xyz123"
  }
}

5.1. Thăm dò trạng thái

Gửi request GET:

GET https://api.kie.ai/api/v1/jobs/recordInfo?taskId={taskId}
Authorization: Bearer <YOUR_KIE_API_KEY>

5.2. Các trạng thái của Task (state)

  • pending: Đang xếp hàng chờ tài nguyên.
  • processing: Đang trong tiến trình tính toán / sinh media.
  • success: Hoàn thành thành công.
  • fail / failed / error / cancelled: Thất bại (Lấy thông báo lỗi tại failMsg, failCode hoặc msg).

5.3. Bóc tách kết quả (3 biến thể quan trọng)

Kie AI trả về URL kết quả ở các dạng khác nhau tùy theo endpoint:

  1. Unified Tasks (Image, Video, TTS):
    • Dữ liệu nằm trong chuỗi JSON string: task.resultJson.
    • Cần parse:
      const parsed = JSON.parse(task.resultJson);
      const resultUrl = parsed.resultUrls?.[0] || parsed.data?.[0]?.audio_url;
  2. Direct Suno Endpoints (Music):
    • Dữ liệu nằm trong object:
      const resultUrl =
        task.response?.sunoData?.[0]?.audioUrl ||
        task.response?.sunoData?.[0]?.streamAudioUrl;
  3. Lyrics Endpoint:
    • Dữ liệu văn bản thuần:
      const lyrics = task.response?.text;

6. Code Triển Khai Mẫu Hoàn Chỉnh (TypeScript / Node.js)

Dưới đây là một module triển khai độc lập, có thể copy trực tiếp vào dự án mới:

// kie-service.ts
import fs from 'node:fs';
import path from 'node:path';

export interface KieConfig {
  apiKey: string;
  baseUrl?: string;
  maxPollMs?: number;
  pollIntervalMs?: number;
}

export class KieAIService {
  private apiKey: string;
  private baseUrl: string;
  private maxPollMs: number;
  private pollIntervalMs: number;

  constructor(config: KieConfig) {
    this.apiKey = config.apiKey;
    this.baseUrl = (config.baseUrl || 'https://api.kie.ai').replace(/\/$/, '');
    this.maxPollMs = config.maxPollMs || 10 * 60 * 1000; // 10 phút
    this.pollIntervalMs = config.pollIntervalMs || 3000; // 3 giây
  }

  private headers(): Record<string, string> {
    return {
      Authorization: `Bearer ${this.apiKey}`,
      'Content-Type': 'application/json',
    };
  }

  /**
   * Upload ảnh local dạng base64 lên CDN Kie AI
   */
  async uploadImageBase64(
    base64DataUrl: string,
    fileName = 'input.png'
  ): Promise<string> {
    const uploadUrl = 'https://kieai.redpandaai.co/api/file-base64-upload';
    const res = await fetch(uploadUrl, {
      method: 'POST',
      headers: this.headers(),
      body: JSON.stringify({
        base64Data: base64DataUrl,
        uploadPath: 'images/base64',
        fileName,
      }),
    });

    if (!res.ok) {
      throw new Error(`Kie upload failed with status ${res.status}`);
    }

    const data = await res.json();
    const url =
      data?.data?.downloadUrl ||
      data?.data?.fileUrl ||
      data?.downloadUrl ||
      data?.url;
    if (!url) {
      throw new Error('Kie upload response did not return a valid downloadUrl');
    }
    return url;
  }

  /**
   * Tạo Image (Grok Imagine / GPT Image 2)
   */
  async generateImage(params: {
    prompt: string;
    model?: string; // 'grok-imagine/text-to-image' | 'gpt-image-2-text-to-image' | ...
    aspectRatio?: '1:1' | '16:9' | '9:16' | '3:2' | '2:3';
    inputUrls?: string[];
  }): Promise<Buffer> {
    const body = {
      model: params.model || 'grok-imagine/text-to-image',
      input: {
        prompt: params.prompt,
        aspect_ratio: params.aspectRatio || '1:1',
        ...(params.inputUrls ? { input_urls: params.inputUrls } : {}),
      },
    };

    const taskId = await this.submitTask('/api/v1/jobs/createTask', body);
    return this.pollTask(taskId);
  }

  /**
   * Tạo Video (Grok Video 1.5)
   */
  async generateVideo(params: {
    prompt: string;
    duration?: number; // 6 - 30
    aspectRatio?: '16:9' | '9:16' | '1:1';
    resolution?: '480p' | '720p' | '1080p';
    imageUrl?: string;
  }): Promise<Buffer> {
    const body = {
      model: 'grok-imagine-video-1-5-preview',
      callBackUrl: 'https://api.kie.ai/callback',
      input: {
        prompt: params.prompt,
        aspect_ratio: params.aspectRatio || '16:9',
        resolution: params.resolution || '720p',
        duration: Math.min(Math.max(params.duration || 8, 6), 30),
        mode: 'normal',
        ...(params.imageUrl ? { image_urls: [params.imageUrl] } : {}),
      },
    };

    const taskId = await this.submitTask('/api/v1/jobs/createTask', body);
    return this.pollTask(taskId);
  }

  /**
   * Tạo Nhạc Suno V5
   */
  async generateMusic(params: {
    prompt: string;
    instrumental?: boolean;
  }): Promise<Buffer> {
    const body = {
      model: 'V5',
      prompt: params.prompt,
      customMode: true,
      instrumental: params.instrumental !== false,
      callBackUrl: 'https://api.kie.ai/callback',
    };

    const taskId = await this.submitTask('/api/v1/generate', body);
    return this.pollTask(taskId);
  }

  /**
   * Gửi lệnh submit task và lấy về taskId
   */
  private async submitTask(
    endpoint: string,
    payload: unknown
  ): Promise<string> {
    const url = `${this.baseUrl}${endpoint}`;
    const res = await fetch(url, {
      method: 'POST',
      headers: this.headers(),
      body: JSON.stringify(payload),
    });

    const text = await res.text();
    if (!res.ok) {
      throw new Error(`Kie submit failed (${res.status}): ${text}`);
    }

    const data = JSON.parse(text);
    const taskId = data?.data?.taskId || data?.taskId;
    if (!taskId) {
      throw new Error(`Kie response missing taskId: ${text}`);
    }
    return taskId;
  }

  /**
   * Vòng lặp Polling kiểm tra trạng thái và download bytes
   */
  private async pollTask(taskId: string): Promise<Buffer> {
    const start = Date.now();
    const pollUrl = `${this.baseUrl}/api/v1/jobs/recordInfo?taskId=${encodeURIComponent(taskId)}`;

    while (Date.now() - start < this.maxPollMs) {
      await new Promise((resolve) => setTimeout(resolve, this.pollIntervalMs));

      const res = await fetch(pollUrl, {
        method: 'GET',
        headers: { Authorization: `Bearer ${this.apiKey}` },
      });

      if (!res.ok) {
        throw new Error(`Polling request failed with status ${res.status}`);
      }

      const pollData = await res.json();
      const task = pollData.data || pollData;
      const state = task.state;

      if (state === 'success') {
        let resultUrl: string | null = null;

        // 1. Kiểm tra Suno Data format
        if (task.response?.sunoData?.length > 0) {
          resultUrl =
            task.response.sunoData[0].audioUrl ||
            task.response.sunoData[0].streamAudioUrl;
        }

        // 2. Kiểm tra Unified Task format (resultJson)
        if (!resultUrl && typeof task.resultJson === 'string') {
          try {
            const parsed = JSON.parse(task.resultJson);
            resultUrl =
              parsed.resultUrls?.[0] || parsed.data?.[0]?.audio_url || null;
          } catch {
            // bỏ qua lỗi parse json
          }
        }

        // 3. Kiểm tra Lyrics format
        if (!resultUrl && typeof task.response?.text === 'string') {
          return Buffer.from(task.response.text, 'utf-8');
        }

        if (!resultUrl) {
          throw new Error(
            `Task completed successfully but no result URL found: ${JSON.stringify(pollData)}`
          );
        }

        // Tải media bytes từ CDN URL
        const downloadRes = await fetch(resultUrl);
        if (!downloadRes.ok) {
          throw new Error(
            `Failed to download result file: ${downloadRes.status}`
          );
        }
        return Buffer.from(await downloadRes.arrayBuffer());
      }

      if (['fail', 'failed', 'error', 'cancelled'].includes(state)) {
        const errorMsg =
          task.failMsg || task.failCode || pollData.msg || 'Unknown error';
        throw new Error(
          `Kie task failed (${state}): ${JSON.stringify(errorMsg)}`
        );
      }
    }

    throw new Error(
      `Kie task ${taskId} timed out after ${this.maxPollMs / 1000}s`
    );
  }
}

7. Các Lưu Ý Vận Hành Thực Tế (Production Best Practices)

  1. Idempotency & Lưu trữ State:
    • Luôn lưu taskId, status, và thời gian tạo vào Database của bạn.
    • Khi nhận callback webhook hoặc người dùng reload trang, kiểm tra theo taskId để tránh submit trùng lặp tốn credit.
  2. Exponential Backoff:
    • Đối với các tác vụ tạo video (thường mất 30s – 120s), có thể tăng thời gian thăm dò từ 3s ban đầu lên 5s hoặc 10s để giảm tải network request.
  3. Bảo mật CDN URL:
    • URL do Kie CDN trả về có thể có hạn sử dụng. Hãy tải binary về và lưu trực tiếp lên Cloud Storage nội bộ (S3, Cloudflare R2, Google Cloud Storage, v.v.).
  4. Giới hạn tham số (Clamping):
    • Video duration luôn phải nằm trong khoảng 6 – 30s.
    • Audio duration tối đa 480s (8 phút).