/** * native-flow-r2v.ts — first-class Google Flow Reference-to-Video (R2V) scene * render via saved **Flow Characters**, the proven character-ad workflow. * * Unlike the produce/execute path (which routes through the bun `vclaw-cli` * flow.ts and a full readiness/storyboard ceremony), this is a lightweight, * pure-Node fetch transport — the same shape as {@link ./native-runway} / * {@link ./native-dreamina} — for rendering ONE scene directly from character * references: * * POST {BASE}/google-flow/videos { email, prompt, model, aspectRatio, * duration, async, character_1..7 } → { jobid } * GET {BASE}/google-flow/jobs/{jobid} (jobid VERBATIM — encoding → 400) * → { status: started|completed|failed, ... videoUrl } * * R2V constraints (vclaw-cli/src/backends/types.ts, live-proven 2026-06-11): * - model MUST be `veo-3.1-fast` (veo-3.1-quality rejects character_*). * - character refs only (character_1..7) — NO startImage (can't mix R2V + I2V). * - duration is 8s ONLY (Veo R2V has no other length) — see FLOW_R2V_DURATIONS. * - Veo generates the character's voice + lip-sync NATIVELY from the prompt. * - Flow burst-throttles with a 403 reCAPTCHA (PUBLIC_ERROR_UNUSUAL_ACTIVITY); * this transport cools down and retries the SUBMIT for that case only. * * Transports (fetch + sleep) are injectable so the whole module is unit-testable * offline with no network and no real waiting. */ import { type FlowUpscaleFinishResult } from './flow-upscale-finish.js'; import type { GoogleFlowUpscaleResolution } from './providers/google-flow.js'; export declare const FLOW_BASE = "https://api.useapi.net/v1"; export declare const FLOW_R2V_MODEL = "veo-3.1-fast"; /** * Models this route accepts. `veo-3.1-fast` is the live-proven default (2026-06-11); * `veo-3.1-quality` rejects `character_*` and is deliberately absent. The two lite * rows are Google's own price table for this account (`veo_3_1_r2v_lite` 5 credits, * `veo_3_1_r2v_lite_low_priority` 0 credits, both 720p / 8 s) — the low-priority one * is the free lane, and whether Flow honours character refs on it is what the live * acceptance harness certifies, not something this constant asserts. */ export declare const FLOW_R2V_MODELS: readonly ["veo-3.1-fast", "veo-3.1-lite", "veo-3.1-lite-low-priority"]; export type FlowR2vModel = (typeof FLOW_R2V_MODELS)[number]; /** * Durations this route can actually generate. **8 seconds only.** * * The API's duration table (spec 2026-08-28, POST /videos › Model Capabilities) * gives Veo T2V/I2V `4|6|8` but Veo **R2V `8` only** — and character refs, which * are what makes this an R2V request, are likewise 8-s-only on Veo. We advertised * `4|6|8|10` and forwarded them, so a `--duration 4` here was a request the * provider was always going to refuse. Narrowed rather than silently coerced: an * operator who asked for 4 s should be told the route cannot do it, not handed a * clip twice the length they planned the edit around. * * (`10` was never Veo's at all — it is an omni-flash duration, and omni-flash * does not take `character_*` on this route.) */ export declare const FLOW_R2V_DURATIONS: Set; export interface FlowFetchResponse { ok: boolean; status: number; text(): Promise; arrayBuffer(): Promise; /** Optional so test fakes can omit it; real fetch always provides it. */ headers?: { get(name: string): string | null; }; } /** * Server-stated throttle cooldown in ms, or null. Prefers the `Retry-After` * header (seconds or an HTTP/ISO date), then the response body's `retryAfter` * field (legacy seconds, or — current useapi shape since 2026-06-15 — an ISO * timestamp string). Honoring this waits the REAL window the load balancer * reports instead of a fixed guess. */ export declare function flowRetryAfterMs(res: { headers?: { get(name: string): string | null; }; }, parsedBody: Record): number | null; export type FlowFetchLike = (input: string, init?: { method?: string; headers?: Record; body?: string; }) => Promise; export interface FlowR2vOptions { /** Scene prompt (dialogue goes inline; prompt hygiene is applied by the caller). */ prompt: string; /** Resolved character refs → character_1..7 (1–7; the person + optional product). */ characterRefs: string[]; outputPath: string; /** 8 seconds — the only length Veo reference-to-video generates (default 8). */ durationSeconds?: number; /** 'landscape' | 'portrait' (default 'landscape'). */ aspectRatio?: 'landscape' | 'portrait'; /** One of {@link FLOW_R2V_MODELS} (default {@link FLOW_R2V_MODEL}, `veo-3.1-fast`). */ model?: FlowR2vModel; env?: NodeJS.ProcessEnv; fetchImpl?: FlowFetchLike; sleepImpl?: (ms: number) => Promise; /** * Captcha-retry count sent on the submit (`captchaRetry`, auto-solve). Omit to * resolve from VCLAW_FLOW_CAPTCHA_RETRY (default 5); 0 opts out. This rides * through the intermittent 403 reCAPTCHA inline rather than relying solely on * the cooldown-resubmit fallback below. */ captchaRetry?: number; /** * Run the free Google Flow 1080p upscale on the finished clip. Omit to resolve * from VCLAW_FLOW_UPSCALE (ON unless explicitly disabled). A failed upscale is * never fatal — the generated clip stands. */ upscale?: boolean; /** Upscale target (default 1080p, free). '4K' costs 50 credits and needs Ultra. */ upscaleResolution?: GoogleFlowUpscaleResolution; /** Cooldown-retries for a 403 reCAPTCHA / 429 throttle on SUBMIT (default 2). */ maxRecaptchaRetries?: number; /** Cooldown between throttle retries, ms, when the server states no window (default 5 min). */ recaptchaCooldownMs?: number; /** * Max in-process wait for a server-stated Retry-After window (default 10 min). * A longer quarantine (e.g. the ~30-min USER_QUOTA window) fails fast with the * real wait instead of blocking the process for it. */ maxThrottleWaitMs?: number; pollIntervalMs?: number; maxPolls?: number; /** * Ceiling on waiting for a missing download link to resolve after the render * COMPLETED (default 3 min). Deliberately its own budget, separate from the * generation poll budget above: a Google link block can last hours, and the * `?raw=true` route works throughout, so there is no reason to sit on it. */ urlRecoveryMaxWaitMs?: number; } export interface FlowR2vResult { jobId: string; outputPath: string; videoUrl: string; characterCount: number; model: string; durationSeconds: number; aspectRatio: string; /** * What the free Flow finish did. `upscaled: false` with a `skippedReason` is a * normal, non-failing outcome — read it rather than assuming every clip rose * to 1080p, or a stitch will silently mix resolutions. */ upscale: FlowUpscaleFinishResult; } /** * Render one R2V scene from saved Flow character refs and download it to * `outputPath`. Throws a clear error on a non-throttle failure; cools down and * retries the submit on a 403 reCAPTCHA throttle. */ export declare function submitFlowR2vNative(options: FlowR2vOptions & { workspaceRoot?: string; }): Promise; /** * `response.media[].mediaGenerationId` — always present on a completed job, and * the only handle on the clip when `videoUrl` was withheld. * * Returns '' for a media item whose own status reports a FAILED generation: that * item never had a URL and never will, so sending it down the recovery path * would burn the whole wait budget before failing anyway. */ export declare function extractMediaGenerationId(parsed: Record): string; export interface R2vPromptHygieneOptions { /** Keep Veo's generated music in the clip (default false → suppress it). */ keepMusic?: boolean; /** Allow room reverb on the voice (default false → dry close-mic). */ allowReverb?: boolean; } /** * Append the standing character-ad audio directives to a scene prompt, unless * opted out. Suppressing Veo-generated music keeps the clip audio voice-only so * a post bed can sit under it without clashing; the dry close-mic directive * fixes Veo's default echoey delivery. Idempotent-ish (only appends when not * already present). Pure. */ export declare function applyR2vPromptHygiene(prompt: string, options?: R2vPromptHygieneOptions): string; //# sourceMappingURL=native-flow-r2v.d.ts.map