Aller au contenu principal

Guide d'intégration AITuberKit × AICU API

Comment brancher la synthèse vocale (TTS) d'AICU sur AITuberKit

Présentation​

AITuberKit est une application web pour converser avec des personnages IA. Pointez-la vers l'endpoint TTS de l'AICU API et vous obtenez une voix japonaise de haute qualité.


Variables d'environnement​

Ajoutez ce qui suit à .env.local :

# Réglages de l'AICU API
AICU_API_KEY=aicu_live_xxxxxxxxxxxxxxxx
AICU_API_URL=https://api.aicu.ai/v1

# Réglages du personnage (utilisez soit slug, soit char_id)
AICU_SLUG=luc4 # Slug du personnage
# AICU_CHAR_ID=0 # ou l'identifiant numérique

Exemples TypeScript​

Client TTS​

// lib/aicu-tts.ts

interface TTSOptions {
text: string;
slug?: string; // Slug du personnage (recommandé)
char_id?: number; // ou l'identifiant numérique
voice?: string;
seed?: number;
instruct?: string;
force?: boolean; // Contourner le cache
}

export async function generateSpeech(options: TTSOptions): Promise<ArrayBuffer> {
const response = await fetch(`${process.env.AICU_API_URL}/tts/generate`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AICU_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text: options.text,
slug: options.slug || process.env.AICU_SLUG,
char_id: options.char_id,
voice: options.voice,
seed: options.seed,
instruct: options.instruct,
force: options.force,
format: 'mp3',
}),
});

if (!response.ok) {
throw new Error(`TTS Error: ${response.status}`);
}

// Journaliser les en-têtes de réponse
const cacheHit = response.headers.get('X-Cache-Hit');
const creditsUsed = response.headers.get('X-Credits-Used');
console.log(`Cache: ${cacheHit}, Credits: ${creditsUsed}`);

return response.arrayBuffer();
}

Hook React​

// hooks/useAicuTTS.ts
import { useState, useCallback } from 'react';

export function useAicuTTS() {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);

const speak = useCallback(async (text: string) => {
setIsLoading(true);
setError(null);

try {
const res = await fetch('/api/tts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text }),
});

if (!res.ok) throw new Error('TTS failed');

const audioBlob = await res.blob();
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);

await audio.play();

// Nettoyage
audio.onended = () => URL.revokeObjectURL(audioUrl);
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error');
} finally {
setIsLoading(false);
}
}, []);

return { speak, isLoading, error };
}

Route d'API (Next.js)​

// app/api/tts/route.ts
import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) {
const { text, slug, char_id, force } = await request.json();

const response = await fetch('https://api.aicu.ai/v1/tts/generate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.AICU_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
text,
slug: slug || process.env.AICU_SLUG || 'luc4',
char_id,
force,
format: 'mp3',
}),
});

if (!response.ok) {
return NextResponse.json(
{ error: 'TTS generation failed' },
{ status: response.status }
);
}

const audioBuffer = await response.arrayBuffer();

return new NextResponse(audioBuffer, {
headers: {
'Content-Type': 'audio/mpeg',
'X-Cache-Hit': response.headers.get('X-Cache-Hit') || 'false',
'X-Slug': response.headers.get('X-Slug') || '',
'X-Credits-Used': response.headers.get('X-Credits-Used') || '0',
},
});
}

Réglages des personnages (CharID)​

char_idslugNomVoixSeedModèleÉtat
0luc4LuC4luc4—eleven_multilingual_v2public
1elenaElena Bloomelena330eleven_multilingual_v2public
2meiMei Soleilmei721eleven_multilingual_v2public
3minaMina Azuremina105eleven_multilingual_v2public
4naoNao Verdenao—eleven_v4public
5sakiSaki Noiresaki1035eleven_multilingual_v2public
6marshaMarsha Aranciamarsha414eleven_multilingual_v2public

Ce tableau est un instantané. GET /v1/char contient toujours la liste à jour, et c'est le seul endroit qui la contient — voir l'API Personnages. Une voix sans seed est fixée à un modèle à la place.

Utilisation :

// Sélection par slug (recommandé)
await generateSpeech({ text: 'こんにちは', slug: 'luc4' });

// Sélection par char_id
await generateSpeech({ text: 'こんにちは', char_id: 0 });

Direction du style vocal (instruct)​

Utilisez le paramètre instruct pour orienter le débit et l'intonation :

// Un salut plein d'entrain
await generateSpeech({
text: 'おはようございます!',
voice: 'mei',
instruct: 'Speak with energy and excitement',
});

// Une explication posée
await generateSpeech({
text: '本日の予定を説明します。',
voice: 'serena',
instruct: 'Speak calmly and clearly like a professional narrator',
});

// Un chuchotement
await generateSpeech({
text: '秘密だよ...',
voice: 'vivian',
instruct: 'Whisper softly',
});

Dépannage​

401 Unauthorized​

→ La clé API n'est pas valide. Émettez-en une nouvelle depuis le tableau de bord.

402 Payment Required​

→ Vous n'avez plus de crédits. Achetez un complément ou passez à une offre supérieure.

429 Too Many Requests​

→ Vous avez atteint la limite de débit. Vérifiez les limites qui s'appliquent à votre offre.


Assistance​

© 2026 AICU Inc.