GEMINI LABJP
PRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration windowPRO35 — July 17, the date reports had pointed to, has passed without an official Gemini 3.5 Pro announcement or model card. July 24 is being cited as the fallbackNB2LITE — Nano Banana 2 Lite, otherwise known as Gemini 3.1 Flash-Lite Image, arrives as the fastest of the family: roughly four seconds per image at $0.034 per thousandOMNI — Gemini Omni Flash enters public preview, generating video up to ten seconds long at $0.10 per second of outputEDIT — Omni Flash is built around conversational editing. Swap a character, relight a scene, or change the angle in plain language, and the original audio and video tracks stay intactSYNTHID — Both new models carry SynthID watermarking, so anything they produce can be checked for provenance from inside the Gemini appSHUTDOWN — The older image generation models are deprecated and switch off on August 17. Worth checking your migration window
Articles/API / SDK
API / SDK/2026-07-05Advanced

Collapsing Video Understanding into One Native Call with Omni Flash

How I replaced an ffmpeg frame-extraction pipeline (7-9 calls per clip) with a single native Omni Flash call, the measured differences, and the boundaries where keeping frame sampling still wins.

Gemini Omni Flashvideo understanding2multimodal43Files API4cost design4

Premium Article

Once I started handling a handful of short promo clips as an indie developer, "making the model understand the video" became the heaviest step in the whole flow. I would cut one frame per second with ffmpeg, send each image to the model for a description, then summarize everything in one more call. It worked, but a single clip took 7-9 API calls to process, and it threw away the audio track entirely.

With Omni Flash entering public preview, passing a video in as-is and letting the model understand it natively became practical. This article walks through the minimal code I used when I moved from a frame-extraction setup to a single pass, the relative measurements, and the boundary where keeping frame sampling is still the better call.

The debt in a three-stage frame-extraction pipeline

The setup I had been running was three stages: extract, describe, summarize. Written out as code, the debt shows up clearly.

import subprocess, os
from google import genai
 
client = genai.Client()
 
def extract_frames(video_path: str, fps: float = 1.0, out_dir: str = "frames") -> list[str]:
    os.makedirs(out_dir, exist_ok=True)
    subprocess.run([
        "ffmpeg", "-i", video_path,
        "-vf", f"fps={fps}", f"{out_dir}/f_%04d.jpg",
    ], check=True)
    return sorted(os.path.join(out_dir, f) for f in os.listdir(out_dir))
 
def describe_video(video_path: str) -> str:
    frames = extract_frames(video_path, fps=1.0)
    notes = []
    for i, path in enumerate(frames):            # calls grow with frame count
        img = client.files.upload(file=path)
        r = client.models.generate_content(
            model="gemini-3.5-flash",
            contents=[img, f"Frame near second {i}. Describe what's shown in one line."],
        )
        notes.append(f"[{i}s] {r.text.strip()}")
    summary = client.models.generate_content(     # one more call to summarize
        model="gemini-3.5-flash",
        contents=["Below are per-second frame notes. Summarize the whole video in 3 lines.\n" + "\n".join(notes)],
    )
    return summary.text

There are three problems. First, call count grows in proportion to video length. Second, since the audio track is never looked at, anything that depends on narration or sound effects gets dropped. Third, frames are only lined up by a time index, so the model cannot reason about motion and treats the clip as a stack of stills. In my use case, that third point was the ceiling on accuracy.

The minimal setup: hand the video straight to Omni Flash

Because Omni Flash handles video natively, you upload the clip through the Files API and pass it to a single generate_content call. Combined with structured output, the downstream parsing disappears too.

import time
from google import genai
from pydantic import BaseModel
 
client = genai.Client()
 
class VideoReport(BaseModel):
    summary: str
    spoken_language: str
    has_music: bool
    safe_for_all_ages: bool
    key_moments: list[str]
 
def understand_video(video_path: str) -> VideoReport:
    f = client.files.upload(file=video_path)
    # Right after upload the file is PROCESSING. Using it before ACTIVE returns 400.
    while f.state.name == "PROCESSING":
        time.sleep(2)
        f = client.files.get(name=f.name)
    if f.state.name != "ACTIVE":
        raise RuntimeError(f"upload failed: {f.state.name}")
 
    r = client.models.generate_content(
        model="gemini-omni-flash-preview",   # public preview; match the exact ID in the changelog
        contents=[f, "Understand this video end to end and return it in the given schema."],
        config={
            "response_mime_type": "application/json",
            "response_schema": VideoReport,
        },
    )
    return r.parsed

It is one call. Because the model sees visuals, audio, and the passage of time in a single context, axes like has_music and spoken_language come back at once, which the frame-extraction version could never recover. I first mirrored the old output and only took a text summary, but passing response_schema and naming the axes I actually needed made the downstream branching trivial to write.

The Before/After gap is less about lines of code and more about what you're discarding. Before pays call count to throw away audio and motion; After picks both up in a single call.

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 minimal setup that folds ffmpeg frame extraction plus per-frame calls (7-9 per clip) into one native Omni Flash call
The three boundaries where single-pass breaks down (long videos, frame-precise detection, cheap yes/no checks) and when to keep frame sampling
A hybrid design that runs a coarse single pass first and only escalates to frame inspection when needed, plus the upload-state and token-budget traps I hit
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.

or
Unlock all articles with Membership →
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.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API / SDK2026-06-28
Read Video with Timestamps in the Gemini API: Pull Just the Scene You Need
Hunting for 'where was that step?' in a screen recording or app demo is a chore. Here is how to use Gemini API video understanding to pull just the right scene with timestamps, plus a design that keeps tokens down with FPS and resolution.
API / SDK2026-07-17
A Gemini stream drops halfway — restart it, or have the model continue?
Most apps silently restart a dropped stream. Here is the arithmetic behind continuing from the partial output instead, and where to put the threshold.
API / SDK2026-07-07
Extract Social Media Promo Metadata From Short Videos in One Omni Flash Pass
Hand a short clip to the public preview of Gemini Omni Flash once and get captions, chapters, and highlight timestamps back as structured JSON. Covers how this differs from a frame-extraction multi-call setup, where fps and media_resolution actually matter, and a per-clip cost estimate — from the angle of keeping an indie promo workflow moving.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →