Intégrer les Caractères (GWM-1 Avatars)
PRÉREQUIS:
+rw-check-compatibility— Le projet doit avoir un composant côté serveur (la clé API ne doit JAMAIS être exposée au client)+rw-fetch-api-reference— Charger la dernière référence API depuis https://docs.dev.runwayml.com/api/ avant l'intégration+rw-setup-api-key— Les identifiants API doivent être configurésDÉPENDANCES OPTIONNELLES:
+rw-integrate-documents— Ajouter une base de connaissances à votre caractère+rw-integrate-character-embed— Utiliser le SDK React pour intégrer l'interface d'appel avatar
Aider les utilisateurs à créer des Runway Characters — des avatars d'IA conversationnelle en temps réel alimentés par GWM-1.
À utiliser uniquement lors de la modification de la base de code d'un utilisateur. Pour la gestion directe des avatars ou d'autres actions ponctuelles de compte Runway depuis l'agent, utilisez plutôt +use-runway-api.
Les Characters sont générés à partir d'une image unique (n'importe quel style visuel — photoréaliste, animé, non-humain) avec contrôle total sur la voix, la personnalité, les connaissances et les actions. Aucun fine-tuning ni entraînement requis.
Concepts clés
Avatars vs Sessions
| Concept | Description |
|---|---|
| Avatar | Une persona persistante avec une apparence, une voix et une personnalité définies. Créée une fois, utilisée plusieurs fois. |
| Session | Une connexion WebRTC en direct pour une conversation en temps réel. Connecte un utilisateur à un avatar. Durée maximale: 5 minutes. |
Cycle de vie de la Session
┌───────────┐
┌──────────┤ NOT_READY ├──────────┐
│ └─────┬─────┘ │
│ │ │
▼ ▼ ▼
CANCELLED READY FAILED
┌──┴──┐
│ │
▼ ▼
RUNNING FAILED
┌──┴──┐
│ │
▼ ▼
COMPLETED CANCELLED
| Statut | Description |
|---|---|
NOT_READY |
La session est en cours de provisionnement. Interroger jusqu'à ce qu'elle soit prête. |
READY |
La session est prête. La sessionKey est disponible. |
RUNNING |
La connexion WebRTC est active. Conversation en cours. |
COMPLETED |
La session s'est terminée normalement. |
FAILED |
Une erreur s'est produite. Vérifier le champ failure. |
CANCELLED |
Explicitement annulée avant la fin. |
Important: Les identifiants de session ne peuvent être consommés qu'une seule fois. Si la connexion WebRTC échoue après la consommation des identifiants, vous devez créer une nouvelle Session.
Architecture
La clé API doit rester côté serveur. Le flux est:
Client (React) → Votre Serveur → Runway API
↓
Client (React) ←─── WebRTC ───← Runway (realtime)
- Le client demande une session auprès de votre serveur
- Votre serveur appelle l'API Runway pour créer une session (
POST /v1/realtime_sessions) - Votre serveur interroge jusqu'à ce que la session soit
READY(GET /v1/realtime_sessions/:id) - Votre serveur consomme les identifiants (
POST /v1/realtime_sessions/:id/consume) - Votre serveur retourne les identifiants au client
- Le client établit une connexion WebRTC directe à Runway
Étape 1: Installer les dépendances
npm install @runwayml/sdk @runwayml/avatars-react
@runwayml/sdk— SDK côté serveur (création de session, gestion des avatars)@runwayml/avatars-react— Composants React côté client (WebRTC, UI)
Étape 2: Créer un Avatar
Les avatars peuvent être créés via le Developer Portal (UI) ou l'API (par programmation).
Option A: Developer Portal (Recommandé la première fois)
- Aller à https://dev.runwayml.com/ → onglet Characters
- Cliquer sur Create a Character
- Télécharger une image de référence (conseils ci-dessous)
- Choisir un préset de voix
- Rédiger les instructions de personnalité (p. ex., "You are a helpful customer support agent for Acme Corp...")
- Optionnellement ajouter un script de démarrage (ce que le character dit en premier)
- Optionnellement télécharger des documents de connaissances (fichiers
.txt) - Cliquer sur Create Character
- Copier l'Avatar ID (un UUID comme
8be4df61-93ca-11d2-aa0d-00e098032b8c)
Option B: API (Par programmation)
// Node.js
import RunwayML from '@runwayml/sdk';
const client = new RunwayML();
const avatar = await client.avatars.create({
name: 'Support Agent',
referenceImage: 'https://example.com/avatar.png',
voice: {
type: 'runway-live-preset',
presetId: 'clara',
},
personality: 'You are a helpful customer support agent for Acme Corp. You help users with billing questions and technical issues.',
});
console.log('Avatar ID:', avatar.id);
# Python
from runwayml import RunwayML
client = RunwayML()
avatar = client.avatars.create(
name='Support Agent',
reference_image='https://example.com/avatar.png',
voice={
'type': 'runway-live-preset',
'preset_id': 'clara',
},
personality='You are a helpful customer support agent for Acme Corp.',
)
print('Avatar ID:', avatar.id)
Si l'image de référence est un fichier local, téléchargez-la d'abord avec +rw-integrate-uploads:
import fs from 'fs';
const upload = await client.uploads.createEphemeral(
fs.createReadStream('/path/to/avatar-image.png')
);
const avatar = await client.avatars.create({
name: 'Support Agent',
referenceImage: upload.runwayUri,
voice: { type: 'runway-live-preset', presetId: 'clara' },
personality: 'You are a helpful customer support agent...',
});
Image de référence (Obligatoire)
referenceImage est obligatoire lors de la création d'un avatar. Elle accepte trois formats:
| Format | Limite | Quand l'utiliser |
|---|---|---|
https://… URL |
2048 caractères | Image déjà hébergée publiquement |
data:image/…;base64,… |
5 MB (caractères) | Fichiers locaux petits à moyens (~3,5 MB brut max) |
runway://… URI |
5000 caractères | Fichiers volumineux téléchargés d'abord via /v1/uploads |
Pour les fichiers locaux de plus de ~3,5 MB, utiliser le flux de téléchargement (+rw-integrate-uploads) pour obtenir un URI runway:// au lieu d'un URI de données.
Directives pour l'image de référence
- N'importe quel style visuel fonctionne: humains photoréalistes, mascotes animées, caractères de marque stylisés
- Utiliser des images de haute qualité avec un bon éclairage
- Le visage doit être clairement visible et centré — les images sans visage reconnaissable échoueront le traitement
- Éviter les images avec plusieurs personnes ou obstructions
- Rapport d'aspect recommandé: 1088×704
Présets de voix
| ID de préset | Nom | Style |
|---|---|---|
clara |
Clara | Doux, accessible |
victoria |
Victoria | Ferme, professionnel |
vincent |
Vincent | Instruit, autoritaire |
Prévisualiser toutes les voix dans le Developer Portal.
Étape 3: Créer une Session (Côté serveur)
C'est la route API côté serveur que votre client appellera. Elle crée une session, interroge jusqu'à ce qu'elle soit prête, consomme les identifiants et les retourne.
Next.js App Router
// app/api/avatar/session/route.ts
import RunwayML from '@runwayml/sdk';
const client = new RunwayML();
export async function POST(request: Request) {
const { avatarId } = await request.json();
// 1. Create session
const { id: sessionId } = await client.realtimeSessions.create({
model: 'gwm1_avatars',
avatar: { type: 'custom', avatarId },
});
// 2. Poll until ready
let sessionKey: string | undefined;
for (let i = 0; i < 60; i++) {
const session = await client.realtimeSessions.retrieve(sessionId);
if (session.status === 'READY') {
sessionKey = session.sessionKey;
break;
}
if (session.status === 'FAILED') {
return Response.json({ error: session.failure }, { status: 500 });
}
await new Promise(r => setTimeout(r, 1000));
}
if (!sessionKey) {
return Response.json({ error: 'Session timed out' }, { status: 504 });
}
// 3. Consume session to get WebRTC credentials
const consumeResponse = await fetch(
`${client.baseURL}/v1/realtime_sessions/${sessionId}/consume`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${sessionKey}`,
'X-Runway-Version': '2024-11-06',
},
}
);
const credentials = await consumeResponse.json();
return Response.json({
sessionId,
serverUrl: credentials.url,
token: credentials.token,
roomName: credentials.roomName,
});
}
Express.js
import RunwayML from '@runwayml/sdk';
import express from 'express';
const client = new RunwayML();
const app = express();
app.use(express.json());
app.post('/api/avatar/session', async (req, res) => {
const { avatarId } = req.body;
try {
// 1. Create session
const { id: sessionId } = await client.realtimeSessions.create({
model: 'gwm1_avatars',
avatar: { type: 'custom', avatarId },
});
// 2. Poll until ready
let sessionKey: string | undefined;
for (let i = 0; i < 60; i++) {
const session = await client.realtimeSessions.retrieve(sessionId);
if (session.status === 'READY') {
sessionKey = session.sessionKey;
break;
}
if (session.status === 'FAILED') {
return res.status(500).json({ error: session.failure });
}
await new Promise(r => setTimeout(r, 1000));
}
if (!sessionKey) {
return res.status(504).json({ error: 'Session timed out' });
}
// 3. Consume credentials
const consumeResponse = await fetch(
`${client.baseURL}/v1/realtime_sessions/${sessionId}/consume`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${sessionKey}`,
'X-Runway-Version': '2024-11-06',
},
}
);
const credentials = await consumeResponse.json();
res.json({
sessionId,
serverUrl: credentials.url,
token: credentials.token,
roomName: credentials.roomName,
});
} catch (error) {
console.error('Session creation failed:', error);
res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
}
});
FastAPI (Python)
import time
import httpx
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from runwayml import RunwayML
app = FastAPI()
client = RunwayML()
class SessionRequest(BaseModel):
avatar_id: str
@app.post("/api/avatar/session")
async def create_session(req: SessionRequest):
# 1. Create session
result = client.realtime_sessions.create(
model='gwm1_avatars',
avatar={'type': 'custom', 'avatar_id': req.avatar_id},
)
session_id = result.id
# 2. Poll until ready
session_key = None
for _ in range(60):
session = client.realtime_sessions.retrieve(session_id)
if session.status == 'READY':
session_key = session.session_key
break
if session.status == 'FAILED':
raise HTTPException(status_code=500, detail=str(session.failure))
time.sleep(1)
if not session_key:
raise HTTPException(status_code=504, detail='Session timed out')
# 3. Consume credentials
async with httpx.AsyncClient() as http:
resp = await http.post(
f"{client.base_url}/v1/realtime_sessions/{session_id}/consume",
headers={
"Authorization": f"Bearer {session_key}",
"X-Runway-Version": "2024-11-06",
},
)
credentials = resp.json()
return {
"session_id": session_id,
"server_url": credentials["url"],
"token": credentials["token"],
"room_name": credentials["roomName"],
}
Étape 4: Se connecter depuis le Client
Voir +rw-integrate-character-embed pour les composants SDK React qui gèrent la connexion WebRTC et le rendu. L'approche la plus simple:
'use client';
import { AvatarCall } from '@runwayml/avatars-react';
import '@runwayml/avatars-react/styles.css';
export default function CharacterPage() {
return (
<AvatarCall
avatarId="your-avatar-id"
connectUrl="/api/avatar/session"
onEnd={() => console.log('Call ended')}
onError={(error) => console.error('Error:', error)}
/>
);
}
Dépannage
- Erreurs de clé API: La clé commence par
key_suivi de 128 caractères hexadécimaux. S'assurer qu'elle est active. - Pas de crédits: Le compte doit disposer de crédits prépayés avant de démarrer un appel.
- Expiration de session: La boucle de polling de 60 itérations attend ~60 secondes. Si les sessions expirent régulièrement, vérifier les limites de concurrence de votre tier.
- Identifiants déjà consommés: Les identifiants de session s'utilisent une seule fois. Si WebRTC échoue après la consommation, créer une nouvelle session.
Journalisation de débogage
<AvatarCall
avatarId="your-avatar-id"
connectUrl="/api/avatar/session"
onError={(error) => {
console.error('Avatar error:', error);
console.error('Error name:', error.name);
console.error('Error message:', error.message);
if (error.cause) console.error('Cause:', error.cause);
}}
/>
Surveiller l'état de la session
import { useAvatarSession } from '@runwayml/avatars-react';
function DebugInfo() {
const { state, sessionId, error } = useAvatarSession();
return (
<pre>
{JSON.stringify({ state, sessionId, error: error?.message }, null, 2)}
</pre>
);
}
Tester avec une configuration minimale
npx degit runwayml/avatars-sdk-react/examples/nextjs-simple test-app
cd test-app
npm install
# Ajouter votre clé API à .env.local
npm run dev
Support des navigateurs
| Navigateur | Version minimale |
|---|---|
| Chrome | 74+ |
| Firefox | 78+ |
| Safari | 14.1+ |
| Edge | 79+ |
Les utilisateurs doivent accorder les permissions de microphone. Les permissions de caméra sont nécessaires si la vidéo utilisateur est activée.
Obtenir de l'aide
| Ressource | Description |
|---|---|
| Developer Portal | Gérer les avatars, consulter les journaux, accéder au tableau de bord |
| SDK Repository | Signaler des bugs, consulter des exemples, vérifier les versions |
En signalant des problèmes, inclure: navigateur/version, version du SDK (npm list @runwayml/avatars-react), messages d'erreur, ID de session et étapes à reproduire.