Les gens se demandent comment notre moteur multi-plan rend vraiment les vidéos. Réponse courte : c'est du ruban adhésif, puppeteer, et beaucoup d'ingénierie soigneuse. Réponse longue ci-dessous.
Le problème
Lorsque nous avons commencé, aucune API de génération de vidéos n'offrait de fonctionnalité multi-plan dans un seul rendu. Runway l'avait dans son interface web, mais pas dans son API. Chaque autre fournisseur nous obligeait à rendre les plans individuellement et à les assembler — ce qui a cassé la cohérence visuelle et doublé nos coûts.
Le choix pragmatique : l'automatisation du navigateur
Au lieu d'attendre que les API rattrapent leur retard, nous avons construit une couche d'automatisation du navigateur qui pilote directement l'interface web de Runway. Chaque travail lance une instance headless de Chrome, se connecte à un compte pré-autorisé, remplit l'interface de storyboard, clique sur le rendu, et attend.
Client → POST /api/jobs (enregistrement SQLite)
→ startJobWorker(jobId)
→ execFile("node lib/runway-browser.mjs")
→ Puppeteer + plugin de furtivité
→ remplit les scènes dans l'interface de multi-plan de Runway
→ déclenche la génération
→ interroge le DOM pour l'élément <video>
→ télécharge le fichier MP4
→ télécharge vers Cloudflare R2
→ met à jour le statut du travail = terminéLa file d'attente
Les travaux sont stockés dans un fichier SQLite avec des champs de statut : en attente, en traitement, terminé, échoué. Un travailleur en arrière-plan interroge les travaux en attente et les exécute via l'automatisation du navigateur. Puisque SQLite n'est qu'un fichier et que le travailleur est un processus Node à longue durée de vie, nous survivons aux redémarrages — au démarrage, nous remettons en file d'attente tout ce qui est resté en vol.
C'est la raison pour laquelle vous pouvez fermer votre onglet de navigateur pendant un rendu. Le travail est un état côté serveur ; votre onglet n'est qu'un visionneur qui interroge un point de terminaison public pour la progression.
Ce que nous avons appris à la dure
- Headless Chrome est gourmand en mémoire. 1 Go par instance est normal. Hetzner VPS fonctionne ; Vercel serverless ne fonctionne pas.
- Google OAuth déteste l'automatisation. Le plugin de furtivité + le profil persistant ont maintenu notre session active. L'anti-robot a été une course aux armements d'un an.
- Le nettoyage des fichiers est important. Après le téléchargement vers R2, nous supprimons le fichier local. Sans cela, 35 Go de disque se remplissent en une semaine.
- L'interrogation du statut nécessite un recul. La première itération interrogeait toutes les 1 seconde et nous a harcelés. 5 secondes semble correct.
Ce qui arrive ensuite
Nous migrerons vers une véritable file d'attente de messages (BullMQ + Redis) pour gérer la concurrence sur plusieurs pools de travailleurs. Cela ouvre la porte à de véritables niveaux de priorité — et non seulement une « file d'attente plus rapide », mais également un « matériel dédié » pour les clients Studio.
À long terme, nous formons notre propre modèle de multi-plan. L'automatisation du navigateur a été le bon choix pour lancer en 3 semaines. Ce n'est pas le bon choix pour évoluer à un million de vidéos par mois. Lorsque nous basculerons, le changement sera invisible pour les utilisateurs — l'API reste la même, mais plus rapide et moins chère.
“Construire la chose qui fonctionne en quelques jours. Puis remplacer les hacks pendant que les utilisateurs utilisent le produit.”



