HUB DÉSACTIVÉ (02/10/2026, ordre de l'utilisatrice) : NinjaBR Hub est SANS QUOTA et les profils
hub/hubv2/hubtsont été supprimés (sauvegarde dans~/.agent-profiles/_removidos-hub-2026-10-02/). N'utilisez PAS Hub, N'EXÉCUTEZ PAShub-libre.sh(se termine avec une erreur), N'ATTENDEZ PAS que le profil Hub se libère. Image : ChatGPT — si le quota de téléchargement d'un compte est épuisé, changez de COMPTE :gpt-noelia-7-10*↔gpt-noelia.empt*. Vidéo : Google Flow (flow-video-playwright).
Que fait flow-video-playwright ?
Mécanique de génération d'image+vidéo via Google Flow (labs.google/fx/pt/tools/flow). Alternative à hub-video-playwright lorsque le Hub est expiré (mort le 21/09/2026, voir [[feedback-ninjabr-hub-acesso-expirado]]).
Profil
flow-enovalabs-pro (port 9265), déjà connecté à Google. Avant de perdre du temps, naviguez et confirmez la connexion :
agent-browser --session flow-enovalabs-pro navigate "https://labs.google/fx/pt/tools/flow"
Si une page de connexion apparaît, arrêtez et informez l'utilisateur — les identifiants ne sont pas dans .credentials.env.
Modèle
Omni 1.1 Flash — confirmé en production le 30/09/2026. Coûte moins de crédit que Veo 3.1. Il est multimodal : génère image ET vidéo à partir du prompt pur, sans téléchargement.
Avant la génération, ouvrez les paramètres (bouton tune, aria-label "Configurações") et assurez-vous :
- Confirmer avant de générer = Jamais (le défaut est "Toujours" — cela consomme du crédit et bloque l'envoi si laissé sur Toujours).
- Modèle par défaut de génération vidéo = Omni 1.1 Flash.
- Proportion vidéo = crop_9_16 9:16 (radio role="radio", le DEUXIÈME crop_9_16 de la liste, index 10 dans le mappage actuel).
Enregistrez.
Flux (pas à pas vérifié le 01/10/2026)
- Créer un projet : tableau de bord → bouton "Nouveau projet" → l'URL devient
https://flow.google.com/project/<uuid>. - Composer :
[contenteditable=true]. Collez via le presse-papiers, PASinnerText— mesuré le 01/10 :c.innerText = prompt; c.dispatchEvent(new InputEvent('input'))colle le texte mais le bouton "Lancer la génération" NE reste PAS désactivé au clic (le handler de "changement de texte" de Material ne se déclenche pas). 2 clics ne génèrent rien.- Bonne méthode :
clipboard writenatif d'agent-browser, puisCtrl+A Ctrl+Vdans le composer :agent-browser --session flow-enovalabs-pro clipboard write "$PROMPT" agent-browser --session flow-enovalabs-pro click "[contenteditable=true]" agent-browser --session flow-enovalabs-pro press "Control+a" agent-browser --session flow-enovalabs-pro press "Control+v" - Confirmez
txtLen === prompt.lengthavant d'envoyer.
- Envoyer :
click button[aria-label='Iniciar geração']. Le bouton se verrouille avecdisabled=true= envoi accepté. Le texte "Na fila" apparaît, puis "Conceptualizing the Video" / "play_circle" + pourcentage. - Attendre : le statut passe à "Conceptualizing the Video" (Flow) ou "Criando imagem" (ChatGPT). Le bouton "Arrêter" n'apparaît que pendant la génération. ~50s pour image prompt-only, plus pour la vidéo.
- Résultat :
<img src="blob:https://flow.google.com/...">avecnaturalWidth>800en 9:16. Téléchargez via fetch+blob+<a download>(lien DOM natif).
Paramètres obligatoires (avant le premier envoi)
Ouvrez button[aria-label='Configurações'] (icône tune) :
- Confirmer avant de générer = Jamais (groupe radio
mat-radio-group-2,value=2). Le défaut est "Toujours" — cela consomme le crédit ET bloque l'envoi automatique. - Modèle par défaut de génération vidéo = Omni 1.1 Flash (combobox).
- Proportion vidéo = crop_9_16 9:16 (button role="radio", DEUXIÈME crop_9_16 de la liste, index 10).
Définissez les radios via input[type=radio] directement (cliquer sur mat-radio-button n'active pas l'input) :
// Jamais
const inputs = Array.from(document.querySelectorAll('input[type=radio]'));
inputs.find(r => r.closest('mat-radio-button')?.innerText.startsWith('Nunca')).click();
// 9:16 vidéo (deuxième crop_9_16)
const r916 = Array.from(document.querySelectorAll('button[role=radio]'))
.filter(b => b.innerText === 'crop_9_16\n9:16')[1];
r916.click();
// Enregistrer
Array.from(document.querySelectorAll('button')).find(b => b.innerText?.trim() === 'Salvar').click();
Téléchargement de référence — bloqué le 30/09/2026
Le bouton "Envoyer un média" du panneau "Ajouter des éléments" ouvre la boîte de dialogue de fichier native du système d'exploitation (CDP Page.fileChooserOpened, pas de <input type=file> dans le DOM). agent-browser upload échoue silencieusement.
Solution de contournement : générez prompt-only. OmniFlash est multimodal et interprète le prompt descriptif. Ce n'est pas aussi fidèle à la référence qu'un téléchargement le serait, mais cela évite la boîte de dialogue de fichier. Envisagez d'escalader vers browser-harness avec Page.setInterceptFileChooser si le prompt-only ne suffit pas — non testé en production.
Template de base prompt-only
A <type de plan> shot of <composition>. <sujet> doing <action unique, lente>.
<scène>. <lumière>. Shot in vertical 9:16 aspect ratio. Photorealistic,
shot on iPhone, no text, no watermark. <anti-morphing>.
Anti-morphing obligatoire (Flow n'a pas de champ NEGATIVE séparé, insérez-le dans la même chaîne) :
- "Hand never clips through the fabric"
- "Garment stays flat / never floats unsupported"
- "Single continuous motion, no jumping"
Validé le 30/09/2026 : scène 1 (main féminine tirant un tissu côtelé rose, fond lit blanc) générée en ~50s sur OmniFlash, sortie 941x1672, aspect iPhone UGC convaincant.
Téléchargement (vérifié le 01/10/2026)
La vidéo ne rend pas <video> dans la grille — seulement après avoir ouvert la carte dans la modale. Flux :
- Cliquez sur la vignette (
img[alt="Miniatura do vídeo gerada"]) — ouvre la modale avec le lecteur + boutons d'en-tête. - Cliquez sur
button[aria-label="Baixar mídia"](icône de téléchargement dans l'en-tête). - Un menu de qualité s'ouvre : 270p (GIF), 720p (Tamanho original), 1080p (Aprimorada), 4K (Aprimorada).
- Cliquez sur la bonne option via le DOM direct :
Array.from(document.querySelectorAll('button')) .find(b => b.innerText.trim() === '720p\nTamanho original').click(); - Le fichier tombe dans
~/Downloads/avec le nom du titre Flow + timestamp (Hands_lifting_brown_skirt_fabric_20261001180016.mp4). Déplacez-le vers le staging du projet et renommez-le.
Pour une image (générée directement, sans vidéo) : <img src="blob:https://flow.google.com/..."> apparaît dans la grille après la génération. Sauvegardez via fetch+blob+<a download> OU capture d'écran directe.
Gate de couleur après téléchargement
Presque tous les médias de Flow sortent avec color_range/color_space/color_transfer/color_primaries = unknown — confirmé le 01/10/2026 sur Flow Omni 1.1 Flash. Le gate feedback-metadado-cor-video-final rejette. Re-encodez vers bt709 AVANT de marquer le clip comme prêt :
ffmpeg -nostdin -i cena-1.mp4 \
-c:v libx264 -crf 18 -preset veryfast -pix_fmt yuv420p \
-x264-params "colorprim=bt709:transfer=bt709:colormatrix=bt709:fullrange=off" \
-color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range tv \
-c:a copy cena-1-fixed.mp4
mv cena-1-fixed.mp4 cena-1.mp4
Vérifiez avec ffprobe -show_entries stream=color_* — les 4 champs doivent être bt709/tv.
Prendre la lane — EN PREMIER, TOUJOURS
Plusieurs Claude utilisent ce même navigateur. Sans lane, tous tombent dans le même projet : le créer un projet de l'un écrase celui de l'autre, et les générations sont mélangées.
~/.claude/bin/lane.sh take flow <lane> # ex.: lane.sh take flow pov-bella
S=flow-<lane> # utilisez $S dans TOUTE commande à partir d'ici
Profil persistant ~/.agent-profiles/flow-enovalabs-pro, port 9265, URL https://labs.google/fx/pt/tools/flow. N'utilisez jamais agent-browser open, press Escape (envoie l'onglet vers about:blank et casse la lane). À la fin : ~/.claude/bin/lane.sh drop flow <lane>.
La zone de téléchargement de Flow est FLOW, pas HUB ni PLAYWRIGHT. Exportez-la une fois au début :
export LANE_AREA=FLOW
Le fichier sort de Flow avec le nom du titre + timestamp (ex. : Hands_lifting_brown_skirt_fabric_20261001180016.mp4), tombe dans ~/Downloads/, et lane.sh collect le déplace vers ~/Downloads/FLOW/$LANE/ → dossier du projet. Rien ne traîne dans Downloads.
LISTE DE VÉRIFICATION D'ENVOI — exécutez AVANT chaque clic sur "Lancer la génération"
Flow ne nettoie rien entre les générations (comme Hub) : le prompt du composer reste collé, le modèle/la proportion peuvent être réinitialisés par le re-rendu après l'envoi. L'ordre ci-dessous existe parce que chaque étape déplacée a déjà coûté du crédit (quota facturé même pour une génération invalide).
1. CRÉER un nouveau projet (ou passer à un existant) — chaque lot utilise un projet. Bouton "Nouveau projet" dans le tableau de bord. L'URL devient https://flow.google.com/project/<uuid>. Réutiliser un vieux projet accumule des déchets et confond le diff de src du téléchargement (voir plus loin).
2. NETTOYER le composer du nouveau projet :
agent-browser --session $S click "[contenteditable=true]"
agent-browser --session $S press "Control+a"
agent-browser --session $S press "Delete"
Confirmez :
echo '(()=>document.querySelector("[contenteditable=true]").textContent.length)()' \
| agent-browser --session $S eval --stdin # doit donner 0
3. VÉRIFIER les paramètres : "Confirmer avant de générer" = Jamais, modèle = Omni 1.1 Flash, proportion = crop_9_16 9:16. La skill s'ouvre avec les mauvais défauts (Toujours + modèle Lite + 16:9) — voir le bloc Paramètres obligatoires.
4. ÉCRIRE le prompt via le presse-papiers (pas innerText) et VÉRIFIER — txtLen === prompt.length avant d'envoyer. Détails dans le bloc Flux ci-dessous.
5. ENVOYER et confirmer que le composer est verrouillé en désactivé :
agent-browser --session $S click "button[aria-label='Iniciar geração']"
sleep 2
echo '(()=>{const c=document.querySelector("[contenteditable=true]");return c.contentEditable==="false"||c.getAttribute("aria-disabled")==="true"?"verrouillé":"libre";})()' \
| agent-browser --session $S eval --stdin
ATTENTE : trois états, trois comportements
Après l'envoi, le statut sur la page passe par trois phases. Les confondre vous fait abandonner trop tôt (perdre du crédit) ou attendre trop longtemps (penser que c'est bloqué alors que c'est déjà prêt).
| État | Texte à l'écran | Comportement |
|---|---|---|
| File d'attente | "X a été programmé et est dans la file d'attente en raison d'une forte demande. N'hésitez pas à vérifier le statut dans quelques minutes." | Attendre. Peut prendre 1-30min. NE RENVOYEZ PAS. |
| Génération | "Conceptualizing the Video" + icône play_circle + pourcentage | Attendre. Bouton "Arrêter" visible. |
| Prêt | Carte avec <img alt="Miniatura do vídeo gerada"> apparaît dans la grille | Télécharger. Voir le bloc de téléchargement. |
Limite dure : 30 minutes en file d'attente sans transition vers "Génération" = abandonner. Mesuré le 02/10/2026 : Flow a affiché "forte demande" pendant 45min sur flow-enovalabs-pro, et quand le statut a bougé, le job avait déjà consommé le crédit sans rien livrer. Symptôme : "forte demande" >30min ET le bouton "Lancer la génération" de la composition précédente reste verrouillé disabled=true — ce n'est pas une vraie file d'attente, c'est un quota perdu.
Chemin de récupération si bloqué :
# 1. Annuler le job en attente (libère le composer pour un nouvel envoi)
agent-browser --session $S click "button[aria-label='Parar']" 2>/dev/null
sleep 2
# 2. Si le composer ne se déverrouille pas, recharger la page entière (perd le projet actuel)
agent-browser --session $S navigate "https://labs.google/fx/pt/tools/flow"
# 3. Essayer un clone parallèle
S=flow-<lane>-2 # ou -3, -4
Si le flow-enovalabs-pro-2/3/4 est également connecté et en file d'attente, utilisez-le en parallèle (Flow permet plusieurs profils avec le même login, contrairement à Hub). Confirmez la connexion : lane.sh take flow <lane> && agent-browser --session $S navigate "https://labs.google/fx/pt/tools/flow" — si vous arrivez sur le tableau de bord sans demande de connexion, tout va bien.
Polling court, limite généreuse :
T0=$(date +%s)
for i in $(seq 1 360); do # 30min × 6 = 360 × 5s
STATE=$(echo '(()=>{const txt=document.body.innerText;
if(/alta demanda/i.test(txt)) return "fila";
if(/Conceptualizing|Criando/i.test(txt)) return "gerando";
const imgs=document.querySelectorAll("img[alt=\\"Miniatura do vídeo gerada\\"]").length;
if(imgs>0) return "pronto";
return "?")()' \
| agent-browser --session $S eval --stdin | tr -d '"' | tail -1)
echo " [$(( $(date +%s)-T0 ))s] $STATE"
[ "$STATE" = "pronto" ] && break
[ "$STATE" = "?" ] && [ $i -gt 6 ] && { echo "abort: composer bloqué sans état"; break; }
sleep 5
done
TÉLÉCHARGEMENT par le CONTENU — gardez l'ancien, choisissez le nouveau
vs[vs.length-1] n'existe pas dans Flow (il n'y a pas de <video> dans la grille). Flow rend une vignette (<img alt="Miniatura do vídeo gerada">) dans la grille ; la vraie vidéo n'apparaît qu'après avoir ouvert la carte dans la modale et cliqué sur "Baixar mídia". Donc, le chemin de téléchargement est différent de Hub :
1. AVANT l'envoi, gardez la liste des vignettes existantes :
BEFORE=$(echo '(()=>[...document.querySelectorAll("img[alt=\\"Miniatura do vídeo gerada\\"]")].map(i=>i.src).join("|"))()' \
| agent-browser --session $S eval --stdin | tr -d '"')
2. APRÈS que pronto soit sorti, trouvez la vignette nouvelle :
AFTER=$(echo '(()=>[...document.querySelectorAll("img[alt=\\"Miniatura do vídeo gerada\\"]")].map(i=>i.src).join("|"))()' \
| agent-browser --session $S eval --stdin | tr -d '"')
NEW=$(python3 -c "import sys;a=set('$AFTER'.split('|'));b=set('$BEFORE'.split('|'));print('|'.join(a-b))")
Si NEW est vide, la carte n'est pas encore apparue — attendez 10-30s supplémentaires et réessayez.
3. Ouvrir la modale de la nouvelle carte et télécharger en 720p :
# clic sur la nouvelle vignette
python3 -c "
import sys
srcs='$NEW'.split('|')
print('(()=>{const imgs=[...document.querySelectorAll(\"img[alt=\\\\