●NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaply●OMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflows●AGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactions●MEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuously●THROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and region●DEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20●NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaply●OMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflows●AGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactions●MEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuously●THROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and region●DEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
How Well Does Omni Flash Hear 'Rotate the Camera 30 Degrees Right'? Measuring Where Conversational Edits Land
Public-preview Gemini Omni Flash lets you re-edit a generated video in plain language. 'Make the lighting evening' lands; 'rotate the camera 30 degrees' often misses. Here is a running log of where instructions land, sorted mechanically by comparing before/after frames.
I was reworking a short promo clip and stopped. I wanted only the lighting of an 8-second clip shifted to an evening tone. In the past that meant rebuilding from source or redoing the grade in a video editor. With the Omni Flash public preview, telling the already-generated video "make the lighting a low evening sun" in plain language swapped the lighting while keeping the cast and framing intact. The original audio track stayed put.
When I tried the same tone with "pan the camera just 30 degrees to the right," it was less obedient than I expected. Sometimes it merely pushed in a little; sometimes it replaced the shot entirely. Some instructions land, some do not. I could feel the difference, but confirming it by eye each time meant running $0.10-per-second edits over and over with no cost visibility.
As an indie developer at Dolice who churns out promo videos for apps, I could not let that slide. So I measured how well each kind of instruction lands, sorting the results mechanically by having Gemini compare the before and after frames. This article is the log of those 42 edit loops.
Conversational editing shifts you from "rebuild" to "restate"
Omni Flash's conversational editing does not rebuild the video from scratch; it layers a diff instruction onto the video you already have. "Make the subject a man with glasses," "stop the rain in the background," "warm the whole thing slightly" — each restatement updates only the part you name. The preview notes say the original audio and video tracks are preserved natively.
That design changes the promo-asset workflow. I covered folding video understanding into a single pass earlier in folding Omni Flash video understanding into one pass; this is the reverse direction — finishing a generated asset through dialogue.
But "you can restate it" and "it changes as intended" are not the same thing. Conflate them and you get charged for misses, and worse, you stack the next instruction without noticing the last one missed. The first thing I needed was a way to judge whether an edit landed without relying on my eyes.
Don't confirm edits by eye — the frame-comparison idea
Whether an edit landed reduces, at bottom, to "did the requested change actually occur between before and after." If so, pull one representative frame from before and one from after, and have Gemini judge whether the instruction is reflected — then you receive the truth mechanically.
Receiving that judgment as prose does not scale into operations. Fix the shape with responseSchema and return only three fields: landed, confidence, and note. Decide up front to treat low-confidence results as "not reflected," and the hesitation disappears.
This is a decision not to hand something you can verify deterministically to a probabilistic mechanism. I wrote about how a SynthID negative is not proof of "not AI-generated" in the asymmetry of SynthID; the reasoning is the same — tip outputs you cannot be confident about to the safe side (not reflected).
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦A verification loop that sorts 'landed' vs 'missed' conversational video edits by having Gemini compare the before and after frames
✦Landing rates by instruction type (lighting and color grade ~90%, precise angle changes ~40%) measured across 42 edits
✦Before/After code that stops the cost of $0.10-per-second edits from ballooning when you iterate by eye
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
First, a thin wrapper that applies one edit. Omni Flash video editing is public preview, and the exact call name may change. I keep the edit itself inside the function and expose the subject of this article — verification and the cost ledger — on the outside.
from dataclasses import dataclass, fieldfrom pathlib import PathOMNI_FLASH_MODEL = "gemini-omni-flash" # public previewPRICE_PER_OUTPUT_SEC_USD = 0.10 # $0.10 per output second@dataclassclass EditResult: instruction: str out_path: Path out_seconds: float landed: bool = False confidence: float = 0.0 note: str = ""def omni_flash_edit(client, base_video: Path, instruction: str, out_dir: Path) -> EditResult: """Apply one conversational edit; return the output path and duration. The exact edit API is public preview and may change, so it is isolated inside this function. """ resp = client.videos.edit( # preview: name may change model=OMNI_FLASH_MODEL, video=str(base_video), instruction=instruction, ) out = out_dir / f"edit_{abs(hash(instruction)) % 10_000}.mp4" out.write_bytes(resp.video_bytes) return EditResult( instruction=instruction, out_path=out, out_seconds=float(resp.duration_seconds), )
Carrying back the duration (out_seconds) is the crux. Billing is proportional to output seconds, so without recording it here you cannot reproduce cost later.
Have Gemini compare the before and after frames
Now the main event: verification. Pull one representative frame from the video, hand the two frames plus the instruction to gemini-3.5-flash, and receive whether it landed as structured JSON.
import json, subprocessfrom pydantic import BaseModelclass EditVerdict(BaseModel): landed: bool confidence: float # 0.0 to 1.0 note: strdef grab_frame(video: Path, at_sec: float, out: Path) -> Path: # Pull a single representative frame (default near the middle) subprocess.run( ["ffmpeg", "-y", "-ss", str(at_sec), "-i", str(video), "-frames:v", "1", str(out)], check=True, capture_output=True, ) return outdef verify_edit(client, before_png: Path, after_png: Path, instruction: str) -> EditVerdict: prompt = ( "These two images are before/after representative frames of a video.\n" f"Requested edit: \"{instruction}\"\n" "Judge whether this edit is actually reflected in the second image.\n" "If you are not confident, lean toward landed=false." ) resp = client.models.generate_content( model="gemini-3.5-flash", contents=[ prompt, {"inline_data": {"mime_type": "image/png", "data": before_png.read_bytes()}}, {"inline_data": {"mime_type": "image/png", "data": after_png.read_bytes()}}, ], config={ "response_mime_type": "application/json", "response_schema": EditVerdict, }, ) return EditVerdict(**json.loads(resp.text))
The single line that tips low-confidence verdicts toward "not reflected" quietly supports every later decision. Counting a miss as a landing is the worst side — it adopts a failed edit as-is — so that is the one place I stay conservative.
Measured — which instructions land, and where they fall off
Against three 8-second promo clips, I applied 42 edit instructions of varying kinds and measured the landing rate with the loop above. Confidence below 0.6 counts as not reflected. These are tendencies for my footage and my prompts; they move as the environment changes.
Edit type
Tries
Landed
Rate
Note
Global lighting / color grade (evening, cool, saturation)
12
11
~92%
Most obedient; grade-equivalent is stable
Mood / weather (stop the rain, etc.)
8
7
~88%
Global changes land easily
Subject swap (specified by attribute)
10
7
~70%
Role phrasing like "man with glasses" works
Precise angle (30 degrees right, etc.)
7
3
~43%
Push-in only / shot replacement mixed in
Prop position/size (logo 20% smaller, lower-left)
5
2
~40%
Spatially precise asks miss easily
A clear tendency emerged. Global appearance changes (lighting, color, weather) land readily, while spatially precise asks (angle, position, size) often miss. Subject swaps sit in between — they land more often when phrased by role or attribute rather than fine identity.
Looking at the misses, precise angle asks split mostly into "pushed in slightly" and "replaced with a completely different shot," and the more I carved the instruction into numbers, the less it hit. Here, stating the intent in words rather than leaning on figures (30 degrees, 20%) gave more stable results.
Before / After — editing by eye vs. editing behind a verification gate
Once you know the landing rate, the shape of the workflow changes. The old way was "stack edits until it looks good," which charges you for misses too and never tells you how many rounds it will take.
# Before: stack until it "looks good" — cost is unreadabledef edit_until_ok(client, base, instructions, out_dir): cur = base for ins in instructions: r = omni_flash_edit(client, cur, ins, out_dir) cur = r.out_path # stack the next one without checking # a human plays the video and judges by eye ... misses billed too return cur
Replace that with a version that verifies each edit, restates a missed instruction up to a retry cap, and declines to adopt it if it still will not land.
# After: keep only edits that landed, and post cost to a ledger@dataclassclass CostLedger: spent_usd: float = 0.0 wasted_usd: float = 0.0 # lost to non-landing edits kept: list = field(default_factory=list) def charge(self, r: EditResult): cost = r.out_seconds * PRICE_PER_OUTPUT_SEC_USD self.spent_usd += cost if r.landed: self.kept.append(r) else: self.wasted_usd += costdef edit_with_gate(client, base, instructions, out_dir, max_retry=1, conf_floor=0.6): cur, ledger = base, CostLedger() for ins in instructions: attempt, landed = 0, False while attempt <= max_retry and not landed: r = omni_flash_edit(client, cur, ins, out_dir) mid = r.out_seconds / 2 before = grab_frame(cur, mid, out_dir / "b.png") after = grab_frame(r.out_path, mid, out_dir / "a.png") v = verify_edit(client, before, after, ins) r.landed = v.landed and v.confidence >= conf_floor r.confidence, r.note = v.confidence, v.note ledger.charge(r) if r.landed: cur, landed = r.out_path, True attempt += 1 if not landed: print(f"Declined: {ins} (final confidence {r.confidence:.2f})") return cur, ledger
Running both across three clips, the by-eye method took 18 edits for 12 keepers, with about 31% of spend lost to misses. The gated method reached the same goals in 14 edits, and because it declined misses early, waste stayed around 12%. In money, at $0.80 per 8-second clip edit, that gap compounds.
Tracks are preserved, but repeated edits loosen the sync
As the preview notes promise, the audio track survived editing. But there is a production gotcha I hit. Stack three or four edits and the video-side duration can drift slightly, and each time, the lip movement and narration drifted a little out of sync. Negligible on a single edit, it becomes noticeable in a promo video once it accumulates.
As a workaround, I cap edits that do not touch audio at three; beyond that I strip the audio, finish the video alone, then lay the narration back on at the end. Sync does not degrade monotonically with edit count, but planning as if more rounds tend to loosen it keeps you safe.
One more thing: I defaulted the verification frame to a single one near the middle, but for videos with cuts, raising it to three frames — head, middle, tail — stabilized the judgment. A single frame occasionally misses the exact interval where the change occurred.
How I use it in indie development — lean toward instructions that land
Having measured it, my operating policy is clear. Design promo-video finishing around the instructions that land (lighting, color, weather, attribute-based subject swaps), and settle spatially precise choices in the framing at generation time, not in the prompt. Trying to fix angle or prop placement afterward with numbers only increases the billed misses.
In my case, promo videos for wallpaper and calming apps settled down on both cost and rework once I locked the framing in the first generation and confined Omni Flash conversational editing to color and mood tweaks. Thinking about the image-side cost alongside Nano Banana 2 Lite cost design makes it clearer where to spend the order-of-magnitude difference between stills and video.
Editing video by conversation genuinely lowers the barrier to production. Just don't overtrust "say it and it changes" — confirm mechanically whether it landed, and move the instructions that miss over to the design side. That plain sorting was the shortest path to putting a preview-stage model to real indie work. I hope it helps your own implementation, and thank you for reading.
Share
Thank You for Reading
Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.