◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — The old Deep Research agent shut down on 10/23. If calls fail, move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — The old Deep Research agent shut down on 10/23. If calls fail, move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/Updates
◎ Updates/2026-10-25Intermediate

Counting the Audio Preview Names That Stop on November 17 in Your Own Folders

Five TTS and Live preview models are scheduled to stop on November 17. Here is a short Python script that lists which file and line in your project still names them, plus the order I would fix what it finds.

gemini-api290deprecationsTTS5Live APIgemini-3.8-livepython113

On Sunday morning I reopened the deprecations page and my eyes stopped halfway down the table. In the version updated on October 22, November 17 appeared in a whole cluster of rows: three TTS models and two Live models, every one with preview in its name.

The page calls those dates the earliest possible shutdown dates. Nothing stops sooner, but nothing promises it slips later either. That leaves 23 days from today. If you have ever added voice output to a side project, can you say right now which file holds those names? As an indie developer I couldn't, which is why I wrote a counter before touching anything.

What I'd say first: finish counting the names before you replace any of them. Once you have a number, the order of work and whether it fits into this week both become visible.

The names affected

The October 22 table lists these five with a November 17 date:

  • gemini-3.1-flash-tts-preview, with gemini-3.8-flash-tts or gemini-3.8-flash-lite-tts as the suggested replacement
  • gemini-2.5-flash-preview-tts, same replacement
  • gemini-2.5-pro-preview-tts, same replacement
  • gemini-3.1-flash-live-preview, replaced by gemini-3.8-live
  • gemini-2.5-flash-native-audio-preview-12-2025, also replaced by gemini-3.8-live

The same page also shows the Omni models that stopped on October 22 and the old Deep Research agent that stopped on October 23. Those are already behind us, so I leave them out. For how I inventoried an earlier deadline, see the September 30 Omni preview inventory.

A script that counts the names

Searching by hand, I would forget to open .env.local or some YAML file. So this script walks the whole folder and prints file and line number, nothing more.

#!/usr/bin/env python3
"""List which file and line still names a model that is scheduled to stop."""
import re
import sys
from pathlib import Path
 
# Copied from the deprecations page updated 2026-10-22 (dates are "earliest possible")
RETIRING = {
    "gemini-3.1-flash-tts-preview": ("2026-11-17", "gemini-3.8-flash-tts / gemini-3.8-flash-lite-tts"),
    "gemini-2.5-flash-preview-tts": ("2026-11-17", "gemini-3.8-flash-tts / gemini-3.8-flash-lite-tts"),
    "gemini-2.5-pro-preview-tts": ("2026-11-17", "gemini-3.8-flash-tts / gemini-3.8-flash-lite-tts"),
    "gemini-3.1-flash-live-preview": ("2026-11-17", "gemini-3.8-live"),
    "gemini-2.5-flash-native-audio-preview-12-2025": ("2026-11-17", "gemini-3.8-live"),
}
SKIP_DIRS = {".git", "node_modules", ".next", "dist", "build", "__pycache__", ".venv"}
TEXT_EXT = {".py", ".js", ".ts", ".tsx", ".json", ".yaml", ".yml", ".toml",
            ".env", ".md", ".txt", ".sh", ".swift", ".kt", ".dart", ".cfg", ".ini"}
 
 
def candidates(root: Path):
    for p in root.rglob("*"):
        if any(part in SKIP_DIRS for part in p.parts) or not p.is_file():
            continue
        # Names like .env.local have a different suffix, so check the prefix too
        if p.suffix in TEXT_EXT or p.name.startswith(".env"):
            yield p
 
 
def main(root_arg: str) -> int:
    root = Path(root_arg)
    # Longest names first so a long name is never matched as a shorter fragment
    pattern = re.compile("|".join(re.escape(k) for k in sorted(RETIRING, key=len, reverse=True)))
    hits = 0
    for path in candidates(root):
        try:
            lines = path.read_text(encoding="utf-8").splitlines()
        except (UnicodeDecodeError, OSError):
            continue  # skip binaries and unreadable files
        for no, line in enumerate(lines, 1):
            for m in pattern.finditer(line):
                date, to = RETIRING[m.group(0)]
                print(f"{path.relative_to(root)}:{no}\t{m.group(0)}\t{date}\t-> {to}")
                hits += 1
    print(f"-- {hits} hits", file=sys.stderr)
    return 1 if hits else 0
 
 
if __name__ == "__main__":
    sys.exit(main(sys.argv[1] if len(sys.argv) > 1 else "."))

It exits with 1 when anything is found, so you can drop it into a shell script or CI later.

What I confirmed by running it

I made a throwaway folder with three files (.env.local, one Python file, one YAML file) and planted four retiring names. All four came back:

.env.local:1	gemini-2.5-flash-preview-tts	2026-11-17	-> gemini-3.8-flash-tts / gemini-3.8-flash-lite-tts
src/voice.py:1	gemini-2.5-flash-native-audio-preview-12-2025	2026-11-17	-> gemini-3.8-live
config/app.yaml:1	gemini-3.1-flash-tts-preview	2026-11-17	-> gemini-3.8-flash-tts / gemini-3.8-flash-lite-tts
config/app.yaml:2	gemini-2.5-pro-preview-tts	2026-11-17	-> gemini-3.8-flash-tts / gemini-3.8-flash-lite-tts

The second YAML hit sits inside a comment. I want that one, because an outdated name left in a note tends to get copied by the next person.

Three things I watched for while writing it

Filtering by extension alone drops .env.local. Path.suffix returns .local there, so the .env entry never matches. The script checks whether the filename starts with .env as a separate condition.

Match longest names first. A long name such as gemini-2.5-flash-native-audio-preview-12-2025 can overlap shorter ones, and without ordering you may get a truncated match.

It cannot see everything. Model names built from pieces like "gemini-" + version + "-flash-tts", settings saved in a database or a cloud console, and the inside of no-code tools are all invisible to a text search. Read "0 hits" as "0 in this folder", never as "0 anywhere".

Fixing what it finds

I order fixes by how bad it is if the name stops, not by how easy the swap is:

  1. Settings the production server reads (environment variables, config files)
  2. Constants bundled into the app
  3. Tests, samples, and READMEs

The direction is TTS to TTS and Live to Live, as the table says. Renaming alone does not guarantee the same voice quality or response timing, though. For gemini-3.8-live, the session thinking in designing sessions for a Live API interpreter app carries over directly. I keep listening tests as a separate step after the rename, which makes problems easier to isolate.

After the swap, I also log the model name that comes back in the response, so an automatic reroute does not slip past. The method is in what to check the morning Flash answers differently.

What to do today

Count today, fix after counting. Keeping just that line lets you judge whether 23 days is long or short using the number in your own folder.

Run the script once on your largest project and write the count in a note. If it returns zero, open one saved setting in a console and check it for the same names before you relax.

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 →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

◎ Updates2026-10-17
The Morning Flash Started Answering Differently, Your Prompt Is Not the First Thing to Check
When output length or format shifts although you never touched the model ID, compare the model you requested with the model that actually answered. A small three-prompt script logs modelVersion on every run, followed by the order I use to narrow down the cause.
◎ Updates2026-09-26
Swapping a Preview TTS Model for 3.8 Flash-Lite TTS, Then Re-choosing a Voice From 150+ Candidates
On September 22, gemini-3.8-flash-lite-tts went GA as the replacement for the 3.1 Flash TTS preview. Here is what I did over one week: replacing the preview model name behind my healing app's guidance audio and re-choosing a voice from the new /v1beta/voices endpoint.
⬡ Advanced2026-10-23
A 23-Second Video Fails With a 500: What to Question Before You Wait. Three Forks to Decide Ahead for Gemini's Agentic Video Understanding
A forum report says Gemini API's agentic video understanding fails with a 'high demand' 500. Here is how I would decide between waiting, splitting and dropping to static mode before it happens, checked against the official guidance, with a small Python helper.