creative-video-analyzer
Pricing
Pay per usage
creative-video-analyzer
AI-powered video ad analyzer using Google Gemini Flash. Extracts hooks, narrative structure, marketing angles, claims, transcript, scene-by-scene breakdown, and strategic notes from Meta ad videos. Supports batch analysis, 3 model fallbacks, and retry logic. Input: video URL + Gemini API key.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
Jérôme Spiell
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
Creative Video Analyzer
Analyse une publicité vidéo via Gemini et renvoie sa structure narrative — hook verbatim, découpage scène par scène, angle, transcript, notes stratégiques — prête à transposer sur une autre marque.
C'est le pendant de creative-static-analyzer pour la vidéo. Même principe : Apify télécharge le média, Gemini l'analyse, Claude reçoit du texte.
Pourquoi cet actor existe
Claude ne peut pas lire une vidéo hébergée sur un domaine externe. Les URLs TrendTrack (medias.trendtrack.io) et les CDN Meta sont inaccessibles depuis son conteneur comme depuis son outil web.
Les serveurs Apify, eux, n'ont aucune de ces restrictions. Ils téléchargent le .mp4, l'envoient à Gemini, et renvoient une analyse textuelle exploitable.
Paramètres
| Paramètre | Obligatoire | Défaut | À quoi ça sert |
|---|---|---|---|
geminiApiKey | ✅ | — | Clé Google AI Studio. Coffre-fort Notion, entrée « Google AI Studio (Gemini) » |
videoUrl | — | — | URL directe de la vidéo à analyser |
videoUrls | — | — | Plusieurs vidéos, pour une analyse en batch |
brandContext | — | — | Contexte marque, pour orienter l'analyse : "[marque] — [produit] — [positionnement]. Que peut-on transposer ?" |
analysisDepth | — | standard | deep ajoute les claims, les mécaniques de persuasion et le copywriting. Plus lent, plus cher |
⚠️ Il n'y a pas de paramètre model
Le modèle Gemini est écrit dans le code (src/main.js), pas dans l'input. Conséquence directe : aucune skill, aucun prompt, aucun appel ne peut le changer. Le passer dans l'input ne fait rien — et croire qu'on a choisi le modèle est pire que savoir qu'on ne peut pas.
C'est la différence avec creative-static-analyzer, qui expose bien un model. Les skills du Creative OS connaissent cette asymétrie : elles passent model au static, jamais à la vidéo, et si la vidéo échoue sur un modèle arrêté, elles le disent au lieu de faire semblant de réparer.
Le modèle ne se change donc qu'en modifiant la source et en rebuildant. Voir « Améliorations possibles » plus bas pour l'exposer.
Les modèles Gemini
Vérifié le 12/10/2026 sur la page de dépréciation Google.
Toute la famille gemini-2.0-* est arrêtée depuis le 1er juin 2026. Un appel dessus renvoie une 404 définitive.
| Rôle | Modèle | Fallbacks, dans cet ordre |
|---|---|---|
| Analyse vidéo | gemini-3.6-flash (actuel, fonctionnel) | gemini-3.8-flash est le modèle recommandé par Google pour les nouveaux usages |
Noms morts, à ne jamais appeler : gemini-2.0-flash, gemini-2.0-flash-001, gemini-2.0-flash-lite, gemini-1.5-flash, gemini-1.5-pro.
gemini-flash-latest fonctionne comme dernier filet, mais ne pas en faire le défaut : Google déplace cet alias à chaque release, avec deux semaines de préavis. La qualité de l'analyse peut bouger sans qu'on l'ait demandé.
Reconnaître une erreur de modèle
Le message contient is not found, was not found, not supported for generateContent, ou renvoie un 404 depuis generativelanguage.googleapis.com.
→ Ne pas relancer à l'identique. Le retry ne sert qu'aux échecs transitoires — cold start, mid-build, timeout réseau. Un modèle supprimé, lui, le reste : relancer ne fait que brûler du temps.
État vérifié — build du 12/10/2026
L'actor embarque une cascade de trois modèles de secours, et sa première tentative est gemini-3.6-flash, un modèle vivant (aucun arrêt annoncé). Run de contrôle du 12/10/2026 : analyse réussie en 5 secondes, dès la première tentative.
Autrement dit : l'actor fonctionne. L'erreur gemini-2.0-flash remontée par un utilisateur vient d'un build antérieur à celui-ci, pas du code actuel. Avant d'aller plus loin, faire re-tester la personne concernée : si ça passe, le dossier est clos.
Améliorations possibles (pas des correctifs)
Rien d'urgent ci-dessous — l'actor tourne. Ce sont deux points qui le rendent plus durable.
1. Exposer le modèle dans l'input. Aujourd'hui il ne se choisit pas depuis l'appel : les skills ne peuvent ni le forcer, ni le corriger quand un nom meurt. Dans .actor/input_schema.json, après analysisDepth :
"model": {"title": "Modele Gemini","description": "Flash suffit pour une video d'ad. Laisser le defaut sauf besoin precis.","type": "string","editor": "select","enum": ["gemini-3.8-flash", "gemini-3.6-flash", "gemini-3.5-flash-lite", "gemini-3.1-pro-preview", "gemini-2.5-flash"],"default": "gemini-3.8-flash"}
2. Donner un filet à la cascade. Les trois niveaux actuels sont codés en dur : le jour où la génération entière est retirée, ils tombent ensemble. Ce bloc interroge l'API pour trouver un modèle valide quand tous les noms connus sont refusés — à brancher sur la fonction d'appel existante :
const MODEL_FALLBACKS = ['gemini-3.8-flash','gemini-3.6-flash','gemini-3.5-flash-lite','gemini-2.5-flash',];const isModelError = (msg = '') =>/is not found|was not found|not supported for generateContent|NOT_FOUND/i.test(msg);// Interroge l'API pour la liste reelle des modeles autorises par la cle.async function discoverFlashModel(apiKey) {const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`);if (!res.ok) return null;const { models = [] } = await res.json();const hit = models.find((m) => {const id = (m.name || '').replace(/^models\//, '');return id.includes('flash')&& !/-lite|-tts|-image|-live|-embedding|-preview/.test(id)&& (m.supportedGenerationMethods || []).includes('generateContent');});return hit ? hit.name.replace(/^models\//, '') : null;}// callGemini(model) doit faire UN appel generateContent et jeter en cas d'erreur.async function generateWithFallback(callGemini, apiKey, preferred) {const chain = [preferred, ...MODEL_FALLBACKS].filter((m, i, a) => m && a.indexOf(m) === i);let last;for (const model of chain) {try {const out = await callGemini(model);console.log(`Modele utilise : ${model}`);return { out, model };} catch (err) {last = err;if (!isModelError(err.message)) throw err; // vraie panne : on ne masque pasconsole.log(`Modele refuse (${model}), on passe au suivant`);}}const found = await discoverFlashModel(apiKey);if (found && !chain.includes(found)) {console.log(`Modele resolu via l'API : ${found}`);return { out: await callGemini(found), model: found };}throw new Error(`Aucun modele Gemini valide. Essayes : ${chain.join(', ')}. `+ `Derniere erreur : ${last && last.message}`);}
À l'appel :
const { model: requestedModel = 'gemini-3.8-flash' } = input;const { out, model: usedModel } = await generateWithFallback((m) => callGemini(m, videoUrl, prompt), // la fonction d'appel existantegeminiApiKey,requestedModel,);
3. Écrire usedModel dans le dataset. C'est ce qui permettra de voir le jour où le défaut vieillit, au lieu de le découvrir par un bug chez un élève.
4. Build, puis Start sur un input de test.
Si ces points sont faits, supprimer le bloc « Il n'y a pas de paramètre model » plus haut et ajouter model au tableau des paramètres. Un README qui contredit le schéma, c'est le prochain bug.
Appel depuis Claude
call-actor("luteous_freezer/creative-video-analyzer", {videoUrl: "<URL .mp4 de la créa>",geminiApiKey: "<clé du Coffre-fort Notion>",brandContext: "<marque> — <produit> — <positionnement>. Que peut-on transposer ?",analysisDepth: "standard"})
⚠️ Toujours enchaîner avec waitSecs: 5 puis get-dataset-items(run.defaultDatasetId). Une attente longue fait expirer le connecteur MCP et renvoie une erreur alors que le run, lui, aboutit — on croit l'actor cassé pour rien.
Ce que renvoie l'analyse
- Hook — verbatim des 3 premières secondes, type de hook, score
- Structure narrative — le découpage en segments, avec leur fonction
- Scènes — le détail scène par scène
- Angle marketing — l'angle principal
- Éléments créatifs — décor, casting, produit, texte à l'écran, rythme de montage
- Transcript — la voix off et les dialogues
- Notes stratégiques — ce qui porte la performance, et ce qui est transposable
En analysisDepth: "deep", s'ajoutent les claims avancés, les mécaniques de persuasion et l'analyse du copywriting.
Coût
Une vidéo ≈ 0,01 $ en flash. Le compute Apify est négligeable à côté. Le mode deep coûte sensiblement plus — le réserver aux créas qu'on va réellement transposer.
Limites
- L'URL doit être publiquement accessible et pointer vers le fichier vidéo, pas vers une page
- Les URLs de CDN Meta sont signées et expirent : les récupérer juste avant l'appel, pas la veille
- Une créa diffusée en ads n'est pas publiée sur le feed de la Page : son
permalink_urlexiste mais le média n'est pas téléchargeable publiquement. Passer par TrendTrack (scan_ad→ media URL) ou par un token de Page
Messages d'erreur
| Erreur | Cause | Quoi faire |
|---|---|---|
models/... is not found · not supported for generateContent · 404 Gemini | Modèle arrêté ou indisponible sur cette clé | Pas un retry. Vérifier d'abord qu'on est sur le dernier build. Si oui, le nom est à changer dans src/main.js — rien n'est réparable depuis l'appel tant que model n'est pas exposé |
Cle API Gemini invalide | Mauvaise valeur | Vérifier le Coffre-fort Notion, entrée « Google AI Studio (Gemini) » |
Quota Gemini depasse | Limite de débit atteinte | Attendre quelques minutes, ou vérifier le plan Google AI Studio |
Telechargement impossible (403) | URL signée expirée, ou média non public | Récupérer une URL fraîche |
| Échec au 1er essai, sans message de modèle | Cold start, mid-build, timeout réseau | Relancer une fois à l'identique. Deux échecs d'affilée → mode dégradé (transcript TrendTrack + copy) |
| Le connecteur MCP renvoie une erreur mais le run aboutit | Attente trop longue côté MCP | Appeler avec waitSecs: 5, puis lire le dataset |
Redéploiement
Copier les fichiers dans l'éditeur web de la console Apify (ou apify push avec la CLI), puis Build, puis Start sur un input de test.
.actor/actor.json.actor/input_schema.json.actor/dataset_schema.jsonsrc/main.jspackage.jsonDockerfile
⚠️ Vérifier le nom du modèle avant chaque build. C'est la seule ligne de cet actor qui peut casser sans que personne n'ait rien touché.