HUB 已停用(2026/10/02,用戶指示): NinjaBR Hub 配額用盡,且
hub/hubv2/hubts設定檔已被移除(備份於~/.agent-profiles/_removidos-hub-2026-10-02/)。請勿使用 Hub,請勿執行hub-livre.sh(會報錯退出),請勿等待 Hub 設定檔釋放。圖片:ChatGPT — 如果一個帳號的上傳配額用完,請切換帳號:gpt-noelia-7-10*↔gpt-noelia.empt*。影片:Google Flow(flow-video-playwright)。
flow-video-playwright
透過 Google Flow(labs.google/fx/pt/tools/flow)產生圖片+影片的機制。當 Hub 過期時(於 2026/09/21 停止服務,參見 [[feedback-ninjabr-hub-acesso-expirado]])作為 hub-video-playwright 的替代方案。
設定檔
flow-enovalabs-pro(連接埠 9265),已登入 Google。在花費時間之前,先瀏覽並確認登入狀態:
agent-browser --session flow-enovalabs-pro navigate "https://labs.google/fx/pt/tools/flow"
如果出現登入畫面,請停止並通知用戶 — 憑證不在 .credentials.env 中。
模型
Omni 1.1 Flash — 已於 2026/09/30 在生產環境確認。消耗的點數比 Veo 3.1 少。它是多模態的:可直接從純文字提示產生圖片和影片,無需上傳。
在產生之前,開啟設定(tune 按鈕,aria-label "Configurações")並確保:
- 產生前確認 = 永不(預設為「總是」— 會消耗點數,且如果保持「總是」會阻止發送)。
- 預設影片產生模型 = Omni 1.1 Flash。
- 影片比例 = crop_9_16 9:16(radio role="radio",清單中第二個 crop_9_16,在目前對應中索引為 10)。
儲存。
流程(已於 2026/10/01 逐步驗證)
- 建立專案:儀表板 → "Novo projeto" 按鈕 → URL 變成
https://flow.google.com/project/<uuid>。 - 作曲家:
[contenteditable=true]。透過剪貼簿貼上,不要使用innerText— 於 10/01 測量:c.innerText = prompt; c.dispatchEvent(new InputEvent('input'))會貼上文字,但點擊時「Iniciar geração」按鈕不會保持在 disabled 狀態(Material 的「文字已更改」處理程序未觸發)。點擊兩次不會產生任何結果。- 正確方法:
agent-browser的原生clipboard write,然後在作曲家上按Ctrl+A Ctrl+V: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" - 在發送前確認
txtLen === prompt.length。
- 發送:
click button[aria-label='Iniciar geração']。按鈕鎖定為disabled=true= 送出成功。會出現文字 "Na fila",接著是 "Conceptualizing the Video" / "play_circle" + 進度百分比。 - 等待:狀態變為 "Conceptualizing the Video"(Flow)或 "Criando imagem"(ChatGPT)。「停止」按鈕僅在生成期間出現。純提示圖片約需 50 秒,影片則更久。
- 結果:
<img src="blob:https://flow.google.com/...">,當比例為 9:16 時naturalWidth>800。透過 fetch+blob+<a download>(原生 DOM 連結)下載。
必要設定(首次發送前)
開啟 button[aria-label='Configurações'](tune 圖示):
- 產生前確認 = 永不(radio group
mat-radio-group-2,value=2)。預設為「總是」— 會消耗點數並阻止自動發送。 - 預設影片產生模型 = Omni 1.1 Flash(combobox)。
- 影片比例 = crop_9_16 9:16(button role="radio",清單中第二個 crop_9_16,索引 10)。
直接透過 input[type=radio] 設定 radio(點擊 mat-radio-button 不會切換 input):
// 永不
const inputs = Array.from(document.querySelectorAll('input[type=radio]'));
inputs.find(r => r.closest('mat-radio-button')?.innerText.startsWith('Nunca')).click();
// 9:16 影片(第二個 crop_9_16)
const r916 = Array.from(document.querySelectorAll('button[role=radio]'))
.filter(b => b.innerText === 'crop_9_16\n9:16')[1];
r916.click();
// 儲存
Array.from(document.querySelectorAll('button')).find(b => b.innerText?.trim() === 'Salvar').click();
參考上傳 — 已於 2026/09/30 封鎖
「Adicionar elementos」面板中的「Enviar mídia」按鈕會開啟作業系統的原生檔案對話方塊(CDP Page.fileChooserOpened,DOM 中無 <input type=file>)。agent-browser upload 會靜默失敗。
解決方案:僅使用提示詞進行生成。OmniFlash 是多模態的,可以解釋描述性提示。雖然不如上傳參考那麼精確,但避免了檔案對話方塊。如果僅使用提示詞不足夠,可考慮使用 Page.setInterceptFileChooser 擴充 browser-harness — 尚未在生產環境測試。
僅提示詞 — 基礎範本
A <tipo de plano> shot of <composição>. <sujeito> doing <ação única, lenta>.
<cenário>. <luz>. Shot in vertical 9:16 aspect ratio. Photorealistic,
shot on iPhone, no text, no watermark. <anti-morphing>.
必要防變形提示(Flow 沒有單獨的 NEGATIVE 欄位,請將其加入同一字串中):
- "Hand never clips through the fabric"
- "Garment stays flat / never floats unsupported"
- "Single continuous motion, no jumping"
已於 2026/09/30 驗證:場景 1(女性手拉粉色羅紋布料,白色床背景)在 OmniFlash 上約 50 秒生成,輸出為 941x1672,iPhone UGC 風格令人信服。
下載(已於 2026/10/01 驗證)
影片不會在網格中渲染 <video> — 只有在卡片於模態框中開啟後才會出現。流程如下:
- 點擊縮圖(
img[alt="Miniatura do vídeo gerada"])— 開啟包含播放器和標題按鈕的模態框。 - 點擊
button[aria-label="Baixar mídia"](標題中的下載圖示)。 - 開啟品質選單:270p(GIF)、720p(Tamanho original)、1080p(Aprimorada)、4K(Aprimorada)。
- 直接透過 DOM 點擊正確選項:
Array.from(document.querySelectorAll('button')) .find(b => b.innerText.trim() === '720p\nTamanho original').click(); - 檔案會下載到
~/Downloads/,檔名為 Flow 標題 + 時間戳記(Hands_lifting_brown_skirt_fabric_20261001180016.mp4)。移動到專案的暫存區並重新命名。
對於圖片(直接生成,無影片):<img src="blob:https://flow.google.com/..."> 在生成後會出現在網格中。透過 fetch+blob+<a download> 或直接截圖儲存。
下載後色彩閘門
幾乎所有來自 Flow 的媒體都含有 color_range/color_space/color_transfer/color_primaries = unknown — 已於 2026/10/01 在 Flow Omni 1.1 Flash 上確認。feedback-metadado-cor-video-final 閘門會拒絕。在將片段標記為就緒之前,重新編碼為 bt709:
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
使用 ffprobe -show_entries stream=color_* 檢查 — 4 個欄位都必須是 bt709/tv。
取得路徑 — 永遠是第一件事
多個 Claude 實例共用同一個瀏覽器。沒有路徑,所有人都會掉進同一個專案:一個實例的 criar projeto 會覆蓋另一個的,導致生成結果錯亂。
~/.claude/bin/lane.sh take flow <lane> # 例如:lane.sh take flow pov-bella
S=flow-<lane> # 從這裡開始,在所有指令中使用 $S
持久化設定檔 ~/.agent-profiles/flow-enovalabs-pro,連接埠 9265,URL https://labs.google/fx/pt/tools/flow。永遠不要使用 agent-browser open、press Escape(會將分頁導向 about:blank 並破壞路徑)。完成後:~/.claude/bin/lane.sh drop flow <lane>。
Flow 的下載區域是 FLOW,不是 HUB 也不是 PLAYWRIGHT。在一開始匯出一次:
export LANE_AREA=FLOW
檔案從 Flow 輸出時帶有標題 + 時間戳記(例如:Hands_lifting_brown_skirt_fabric_20261001180016.mp4),下載到 ~/Downloads/,然後 lane.sh collect 會將其移動到 ~/Downloads/FLOW/$LANE/ → 專案資料夾。Downloads 中不會留下任何檔案。
發送檢查清單 — 在每次點擊「Iniciar geração」之前執行
Flow 不會在生成之間清除任何內容(與 Hub 相同):作曲家的提示會殘留,模型/比例可能會在發送後的重新渲染中被重置。以下順序之所以存在,是因為任何步驟的錯位都已經消耗了點數(即使生成無效也會扣配額)。
1. 建立新專案(或切換到現有專案) — 每批使用一個專案。 儀表板中的 "Novo projeto" 按鈕。URL 變成 https://flow.google.com/project/<uuid>。重用舊專案會累積垃圾,並混淆下載的 src 差異(見下文)。
2. 清除新專案的作曲家:
agent-browser --session $S click "[contenteditable=true]"
agent-browser --session $S press "Control+a"
agent-browser --session $S press "Delete"
確認:
echo '(()=>document.querySelector("[contenteditable=true]").textContent.length)()' \
| agent-browser --session $S eval --stdin # 必須為 0
3. 檢查設定: 「產生前確認」= 永不,模型 = Omni 1.1 Flash,比例 = crop_9_16 9:16。技能開啟時預設是錯誤的(總是 + Lite 模型 + 16:9)— 參見必要設定區塊。
4. 透過剪貼簿寫入提示(不要用 innerText)並檢查 — 發送前確保 txtLen === prompt.length。詳細資訊請參閱下方流程區塊。
5. 發送並確認作曲家已鎖定為 disabled:
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"?"travao":"livre";})()' \
| agent-browser --session $S eval --stdin
等待:三種狀態,三種應對方式
發送後,頁面上的狀態會經歷三個階段。混淆它們會導致您過早放棄(浪費點數)或等待過久(以為當機但實際上已完成)。
| 狀態 | 螢幕上的文字 | 應對方式 |
|---|---|---|
| 佇列 | "X 已排程並因需求量大而處於佇列中。請隨時在幾分鐘後檢查狀態。" | 等待。 可能需要 1-30 分鐘。請勿重新發送。 |
| 生成中 | "Conceptualizing the Video" + play_circle 圖示 + 進度百分比 | 等待。 可見「停止」按鈕。 |
| 就緒 | 網格中出現帶有 <img alt="Miniatura do vídeo gerada"> 的卡片 | 下載。 參見下載區塊。 |
硬性限制:在佇列中超過 30 分鐘未轉換為「生成中」= 放棄。 已於 2026/10/02 測量:Flow 在 flow-enovalabs-pro 上顯示「高需求量」達 45 分鐘,當狀態實際移動時,工作已消耗了點數但未產出任何內容。症狀:"高需求量" >30 分鐘,且上一個組合的「Iniciar geração」按鈕仍保持 disabled=true 鎖定 — 這不是真正的佇列,而是配額已耗盡。
卡住時的恢復路徑:
# 1. 取消待處理的作業(釋放作曲家以供新發送)
agent-browser --session $S click "button[aria-label='Parar']" 2>/dev/null
sleep 2
# 2. 如果作曲家仍未解鎖,重新載入整個頁面(會遺失當前專案)
agent-browser --session $S navigate "https://labs.google/fx/pt/tools/flow"
# 3. 嘗試平行複製
S=flow-<lane>-2 # 或 -3, -4
如果 flow-enovalabs-pro-2/3/4 也已登入並在佇列中,請平行使用它們(Flow 允許同一帳號的多個設定檔,與 Hub 不同)。確認登入狀態:lane.sh take flow <lane> && agent-browser --session $S navigate "https://labs.google/fx/pt/tools/flow" — 如果直接進入儀表板而無需登入,則表示正常。
短輪詢,寬鬆上限:
T0=$(date +%s)
for i in $(seq 1 360); do # 30 分鐘 × 6 = 360 × 5 秒
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 travado sem estado"; break; }
sleep 5
done
根據內容下載 — 先保存舊的,再選擇新的
Flow 中不存在 vs[vs.length-1](網格中沒有 <video>)。Flow 在網格中渲染一個縮圖(<img alt="Miniatura do vídeo gerada">);實際影片只有在在模態框中開啟卡片並點擊 Baixar mídia 後才會出現。因此,下載路徑與 Hub 不同:
1. 在發送之前,保存現有縮圖的清單:
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. 在 pronto 狀態出現之後,找到新的縮圖:
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))")
如果 NEW 為空,表示卡片尚未出現 — 請再等待 10-30 秒並重試。
3. 開啟新卡片的模態框並下載 720p:
# 點擊新縮圖
python3 -c "
import sys
srcs='$NEW'.split('|')
print('(()=>{const imgs=[...document.querySelectorAll(\"img[alt=\\\"Miniatura do vídeo gerada\\\"]\")];'
'const t=imgs.find(i=>i.src===\\