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가 만료되었을 때 hub-video-playwright의 대안 (2026-09-21 만료, [[feedback-ninjabr-hub-acesso-expirado]] 참조).
프로필
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보다 크레딧 소모 적음. 멀티모달: 업로드 없이 순수 프롬프트로 이미지와 영상 생성 가능.
생성 전 settings 버튼 (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>로 변경. - Composer:
[contenteditable=true].innerText가 아닌 클립보드로 붙여넣기 — 01/10 측정:c.innerText = prompt; c.dispatchEvent(new InputEvent('input'))텍스트는 붙여넣어지지만 "Iniciar geração" 버튼이 클릭 시 비활성화되지 않음 (Material의 "text changed" 핸들러 미작동). 2번 클릭해도 아무 일 안 일어남.- 올바른 방법:
agent-browser네이티브clipboard write, 그 다음 composer에서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)로 변경. 생성 중에만 "Parar" 버튼 표시. 이미지 프롬프트 전용 약 50초, 영상은 더 소요.
- 결과:
<img src="blob:https://flow.google.com/...">9:16일 때naturalWidth>800. fetch+blob+<a download>(네이티브 DOM 링크)로 다운로드.
필수 설정 (첫 전송 전)
button[aria-label='Configurações'] (튠 아이콘) 열기:
- 생성 전 확인 = 안 함 (radio group
mat-radio-group-2,value=2). 기본값 "항상" — 크레딧 소모 및 자동 전송 차단. - 기본 영상 생성 모델 = Omni 1.1 Flash (콤보박스).
- 영상 비율 = crop_9_16 9:16 (button role="radio", 목록의 두 번째 crop_9_16, 인덱스 10).
라디오 직접 input[type=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" 버튼은 OS 네이티브 파일 다이얼로그를 엽니다 (CDP Page.fileChooserOpened, <input type=file> DOM 아님). agent-browser upload 조용히 실패합니다.
해결 방법: 프롬프트 전용 생성. OmniFlash는 멀티모달이며 설명 프롬프트를 해석합니다. 업로드가 제공하는 것만큼 참조에 충실하지는 않지만 파일 다이얼로그를 피합니다. 프롬프트 전용으로 충분하지 않은 경우 browser-harness를 Page.setInterceptFileChooser로 확장 — 프로덕션에서 테스트되지 않음.
프롬프트 전용 — 기본 템플릿
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(); - 파일이 Flow 제목 + 타임스탬프 이름으로
~/Downloads/에 저장됨 (Hands_lifting_brown_skirt_fabric_20261001180016.mp4). 프로젝트 스테이징으로 이동하고 이름 변경.
이미지 (직접 생성, 영상 없음)의 경우: 생성 후 <img src="blob:https://flow.google.com/...">가 그리드에 나타남. fetch+blob+<a download> OR 직접 스크린샷으로 저장.
다운로드 후 색상 게이트
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가 동일한 브라우저를 사용합니다. 레인이 없으면 모두 동일한 프로젝트에 들어가서 한 Claude의 '프로젝트 생성'이 다른 Claude의 것을 덮어쓰고 생성이 뒤섞입니다.
~/.claude/bin/lane.sh take flow <lane> # ex.: 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/ → 프로젝트 폴더로 이동합니다. 다운로드 폴더에 아무것도 남지 않습니다.
전송 체크리스트 — "Iniciar geração" 클릭 전에 실행
Flow는 생성 간에 아무것도 지우지 않습니다 (Hub와 동일): composer의 프롬프트가 붙어 있고, 모델/비율이 전송 후 리렌더링에 의해 재설정될 수 있습니다. 아래 순서는 각 단계가 순서를 벗어나면 이미 크레딧이 소모되었기 때문에 존재합니다 (잘못된 생성에서도 크레딧이 청구됨).
1. 새 프로젝트 생성 (또는 기존 프로젝트로 전환) — 각 배치는 새 프로젝트 사용. 대시보드의 "Novo projeto" 버튼. URL이 https://flow.google.com/project/<uuid>로 변경. 오래된 프로젝트를 재사용하면 쓰레기가 쌓이고 다운로드의 src diff를 혼동시킵니다.
2. 새 프로젝트의 composer 지우기:
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. 전송 및 composer가 비활성화되었는지 확인:
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 foi agendado e está na fila devido à alta demanda. Sinta-se à vontade para verificar o status daqui a alguns minutos." | 대기. 1-30분 소요 가능. 재전송 금지. |
| 생성 중 | "Conceptualizing the Video" + play_circle 아이콘 + 퍼센트 | 대기. "Parar" 버튼 표시됨. |
| 완료 | <img alt="Miniatura do vídeo gerada"> 카드가 그리드에 나타남 | 다운로드. 다운로드 블록 참조. |
하드 리미트: 큐에서 30분 동안 "생성 중"으로 전환되지 않으면 중단. 2026-10-02 측정: Flow가 flow-enovalabs-pro에서 45분 동안 "alta demanda"를 표시했고, 실제로 상태가 변경되었을 때 작업은 이미 크레딧을 소모하고 아무것도 반환하지 않았습니다. 증상: "alta demanda" >30분 AND 이전 composition의 "Iniciar geração" 버튼이 계속 disabled=true로 고정됨 — 실제 큐가 아닌 손실된 할당량입니다.
중단 시 복구 경로:
# 1. 대기 중인 작업 취소 (composer를 새 전송에 해제)
agent-browser --session $S click "button[aria-label='Parar']" 2>/dev/null
sleep 2
# 2. composer가 해제되지 않으면 페이지 전체 새로고침 (현재 프로젝트 손실)
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" — 대시보드가 로그인 없이 열리면 OK.
짧은 폴링, 넉넉한 상한:
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 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=\\\\\\\