Gemini web-app toolkit
A local CLI wrapper around the unofficial gemini_webapi library
(github.com/HanaokaYuzu/Gemini-API) that drives gemini.google.com via the user's
Google cookies (not an official API key). Installed at:
C:\Users\user\Desktop\video-ad\tools\gemini\
Full docs: C:\Users\user\Desktop\video-ad\tools\gemini\README.md.
Upstream source/examples: ...\tools\gemini\repo\ (README.md, cli.py, src/).
The venv python (always use this, never global python)
C:\Users\user\Desktop\video-ad\tools\gemini\venv\Scripts\python.exe
What it does
- ✅ text/documents/scripts/copy, ✅ AI images (Nano Banana), ✅ short video +
avatar (Gemini Omni, paid plan), ✅ audio/music beds.
Image models ("Nano Banana")
Image gen runs on the chat model. --model gemini-3-pro → Nano Banana Pro
(best, hero shots); --model gemini-3-flash → Nano Banana 2 (fast, default
for image). The account default (3.1 Flash-Lite) has a tight image cap — the
image/video commands already avoid it. Images carry a Gemini watermark.
Video + Avatar (Gemini Omni) — GENERATE, THEN PULL
- Account is on a PAID plan; default for avatar video is Gemini Omni.
- Avatar handle:
@ai844579 — pass --avatar @ai844579 (or put it in the prompt).
- Each generation is ~10 seconds. Voiceover cap: ≤ ~22–24 words per 10s clip
(≈140 wpm) — user's rule. Keep each clip's narration within that.
- ⚠️ The live video stream almost always aborts before returning the file
(error 1155 / "stream suspended / no CID to recover"). This is NOT failure —
the video still renders server-side and lands in Gemini history. Retrieve it
with
pull, do not keep re-generating (that just burns the daily video cap):
PY gemini.py video "..." --avatar @ai844579 → submit (may end in a stream error, fine)
PY gemini.py pull --match video -o <dir> → downloads finished videos from history
PY gemini.py list → see recent chats; pull --cid c_xxxx targets one.
- The user can also generate videos in the Gemini APP directly, then just
pull.
- Daily video cap exists even on paid plans ("come back tomorrow").
pull still
works to download already-made videos.
- Longer ad (~22–24s): pull 2–3 clips and concat with
tools\ffmpeg.exe.
- HeyGen MCP (talking avatar + real voiceover) remains a reliable alternative if
Gemini's daily cap is hit or a specific avatar/lipsync is needed.
Editing AI video clips — ALWAYS edit, never blindly concat
AI clips (Gemini Omni etc.) have morphing/warping, weak first/last beats, garbled
on-screen text/logos, and per-clip audio that clashes when joined. Act like a
video editor with a timeline, not a concat script. Workflow (uses tools\ffmpeg.exe):
- Look at every clip's frames DENSELY. 1 fps hides sub-second glitches — use
4 fps and split each 10s clip into readable windows so frames are big enough
to actually see (per 5s window = 20 frames in a 5x4 grid):
ffmpeg -i clip.mp4 -ss 0 -t 5 -vf "fps=4,scale=440:-1,tile=5x4" -frames:v 1 w0.png
ffmpeg -i clip.mp4 -ss 5 -t 5 -vf "fps=4,scale=440:-1,tile=5x4" -frames:v 1 w5.png
READ every window. Frames are 0.25s apart, left→right, top→bottom, so you can name
the exact second an artifact starts. Watch for: morphing faces, warped/garbled
on-screen TEXT or fake LOGOS (a real example: one clip rendered a bogus "Ucire to
HFT" logo at 8.5–9.75s — cut before it), empty/wide/tiny shots, ugly first/last
frames. It's normal to keep only 2–4s of a 10s clip. (drawtext timestamps need a
fontfile on Windows — skip it, use frame position instead.)
- Look at the audio too. Waveform + stats per clip:
ffmpeg -i clip.mp4 -filter_complex "showwavespic=s=1000x140" -frames:v 1 wave.png
ffmpeg -i clip.mp4 -af volumedetect -f null - and silencedetect=noise=-38dB:d=0.3.
Flag silent stretches and dead-air. Video-good-but-audio-bad and vice versa are common.
- Cut to the good parts (frame-accurate = re-encode each segment, don't
-c copy
at arbitrary times).
3b. SEQUENCE — this is half the edit, not an afterthought. Cutting out bad frames
is only step one. Then lay ALL the clean pieces on the board and decide the ORDER
like a creative director, because AI clips come out scattered. Ask: what is the
end goal of this video, and of each shot? Then order for story, not for the order
the clips happened to generate in:
- Hook (first 1–2s) = your single most scroll-stopping shot — motion, a light-up
"moment," or the most striking beauty frame. Never open on a slow/empty/dark hold
just because it feels like an "intro." Get to something arresting immediately.
- Hero right after the hook = the money beauty shot of the product.
- Feature beats in the middle (display, charging, etc.).
- Detail (macro/craft) as a texture beat.
- Breath (one calm elegant shot) before the finish.
- Close = a strong final hero/standing shot that leaves the product in mind.
Drive the order from the AUDIO / voiceover / transcript when there is one (picture
follows the words); with no VO, drive it from the visuals and the ad's goal. Then
re-watch (re-mosaic the assembled cut) and re-order again if the flow is off — a
reveal-structure (dark→ignite→hero) and a hook-first structure (ignite→hero→…) are
both valid; pick the one that serves the goal, don't just keep generation order.
- Unify the audio. Don't keep 5 disjoint per-clip beds. Drop them and lay ONE
continuous bed under the whole edit, with
afade in/out. If a clip's audio is
"just a sound," replace/overlay a better track (generate via gemini.py media,
or HeyGen search_audio_sounds / a music bed). Align audio hits to visual cuts.
- Target length = the user's spec (default a tight ~22–24s ad; ~140 wpm VO ⇒
≤22–24 words per 10s of picture).
- QC the result: mosaic the final cut and confirm no artifacts slipped in.
A worked example lives at tools\gemini\out\videos\build_edit.sh (curated segment
list + silent montage + unified faded bed + mux). Reuse/adapt its structure.
Parallelize with subagents (faster + more professional)
Don't do a multi-clip edit serially in one context. Fan the work out with the Agent
tool (or a Workflow) so the slow parts run concurrently and each agent stays focused:
- Frame-analysis agents — one PER clip (fan out): each generates its clip's dense
4fps mosaics, reads them, and returns structured clean/bad sub-ranges + one-line notes
(e.g. "logo artifact 8.5–9.75"). N clips → N agents at once.
- Audio-analysis agent: waveform + silencedetect + volumedetect per clip; flags dead
air, and whether each clip's audio is musical or just ambient.
- Sequencing/director agent: takes all findings, decides the goal + hook, and returns
the ordered segment list (the §3b decision). This is the creative brain.
- Salvage agents: for beats where the AUDIO/VO is good but the VISUAL is weak, don't
drop the beat — see below.
- QC agent: re-mosaics the assembled cut and flags anything that slipped through.
Then the main context just assembles the approved segment list with ffmpeg. Result: the
per-clip inspection (the slow part) happens in parallel, and the edit is more consistent.
Salvage weak visuals (good audio, bad picture)
When you must keep a beat for timing/VO but its footage is ugly (morphy, empty, dull):
blur/darken it and put graphics on top to carry it — a real editor's move:
- Blur / darken bg:
-vf "gblur=sigma=20,eq=brightness=-0.1"
- Overlay kinetic TEXT / lower-third:
drawtext (needs a fontfile on Windows, e.g.
fontfile=C\:/Windows/Fonts/arialbd.ttf), or render a transparent PNG and overlay.
- Add an emoji / sticker / logo PNG with
overlay=x:y (optionally animated via expressions).
- Then the good audio/VO plays over a clean graphic beat instead of bad footage.
Use sparingly — blur-and-text is a patch for a weak second, not a substitute for real shots.
Voiceover audio (spoken)
The COOKIE web app (gemini.py) cannot do TTS — it only makes music + Omni-video
native VO. For a standalone spoken voiceover FILE there are two routes:
- Gemini 2.5 TTS via the official API —
tts.py (needs a free API KEY, separate
from cookies). Accent/style is set by the PROMPT, so a Nigerian accent works:
PY tts.py "Meet Series 11..." --accent "Nigerian English" --voice Charon -o vo.wav
PY tts.py --list (list TTS models + prebuilt voices)
Key setup (once): free key at https://aistudio.google.com/apikey →
tools\gemini\gemini_api_key.txt (git-ignored) or env GEMINI_API_KEY.
These 2.5 TTS models are API-only; they never appear in the web app's model list.
- HeyGen MCP:
create_speech (needs a starfish-engine voice — designed voices
aren't starfish, so pick a starfish voice or clone_voice the user's own voice for
a true Nigerian accent), or the avatar @ai844579's own voice via an Omni video.
Write the script first with doc (≤~22–24 words per 10s of picture), then TTS it.
Quick usage
Run from tools\gemini. PY = the venv python above.
| Goal |
Command |
| Verify auth + list models |
PY gemini.py check |
| Ad copy / taglines / Q&A |
PY gemini.py ask "..." |
| Ad/VO script → markdown file |
PY gemini.py doc "Write a 30s VO script for ..." -o <path>.md |
| Analyse an image/pdf (vision) |
PY gemini.py ask "..." --file <path> |
| Generate images |
PY gemini.py image "sleek smartwatch, 9:16, studio" -o <dir> -n watch -c 3 |
| Generate video |
PY gemini.py video "5s clip: ..." -o <dir> |
| Generate music bed |
PY gemini.py media "upbeat 15s tech bed" --type audio -o <dir> |
Model choice: --model gemini-3-pro | gemini-3-flash | gemini-3-flash-thinking
(default = account default). Images: the CLI auto-prepends "Generate" so you get
AI images, not web images.
Auth (do first / when it breaks)
- Preferred:
tools\gemini\cookies.json with __Secure-1PSID (+ optional
__Secure-1PSIDTS) copied from gemini.google.com DevTools → Cookies.
- Or, if logged into gemini.google.com in the browser and no cookies.json, the
[browser] extra auto-imports cookies.
- Never read, extract, print, or paste the user's cookies yourself. If auth
fails (status 1016 UNAUTHENTICATED), tell the user to refresh
cookies.json
per README.md §2. Cookies expire regularly.
For anything beyond the CLI (chat sessions, gems, deep research)
Write a short async script against the venv using gemini_webapi.GeminiClient.
The pattern and full API are in README.md §4 and repo\README.md.
Ad-workflow recipe (typical)
doc → generate the ad script + voiceover script (markdown).
image → generate hero shots / storyboard frames into the project's folder.
- HeyGen
create_speech → turn the VO script into spoken audio.
- (optional)
media → music bed; video → motion clips.
- Assemble with
tools\ffmpeg.exe (see project memories / existing workflow).
1---2name: gemini-webapi3description: Use Google Gemini (via the local tools/gemini toolkit) to generate ad scripts, voiceover scripts, documents, marketing copy, AI images for ads/storyboards, short video clips, and audio/music beds. Trigger when the user wants to "use Gemini" to write, narrate, generate images, generate video, generate documents, or draft ad copy/scripts inside the video-ad workspace (any project under C:\Users\user\Desktop\video-ad).4---56# Gemini web-app toolkit78A local CLI wrapper around the **unofficial** `gemini_webapi` library9(github.com/HanaokaYuzu/Gemini-API) that drives gemini.google.com via the user's10Google **cookies** (not an official API key). Installed at:1112```13C:\Users\user\Desktop\video-ad\tools\gemini\14```1516Full docs: `C:\Users\user\Desktop\video-ad\tools\gemini\README.md`.17Upstream source/examples: `...\tools\gemini\repo\` (README.md, cli.py, src/).1819## The venv python (always use this, never global python)20```21C:\Users\user\Desktop\video-ad\tools\gemini\venv\Scripts\python.exe22```2324## What it does25- ✅ text/documents/scripts/copy, ✅ AI images (Nano Banana), ✅ short video +26 avatar (Gemini Omni, paid plan), ✅ audio/music beds.2728## Image models ("Nano Banana")29Image gen runs on the chat model. `--model gemini-3-pro` → **Nano Banana Pro**30(best, hero shots); `--model gemini-3-flash` → **Nano Banana 2** (fast, default31for `image`). The account default (3.1 Flash-Lite) has a tight image cap — the32`image`/`video` commands already avoid it. Images carry a Gemini watermark.3334## Video + Avatar (Gemini Omni) — GENERATE, THEN PULL35- Account is on a **PAID plan**; default for avatar video is **Gemini Omni**.36- **Avatar handle: `@ai844579`** — pass `--avatar @ai844579` (or put it in the prompt).37- Each generation is ~**10 seconds**. **Voiceover cap: ≤ ~22–24 words per 10s clip**38 (≈140 wpm) — user's rule. Keep each clip's narration within that.39- ⚠️ **The live video stream almost always aborts** before returning the file40 (error 1155 / "stream suspended / no CID to recover"). This is NOT failure —41 the video still renders server-side and lands in Gemini history. **Retrieve it42 with `pull`, do not keep re-generating** (that just burns the daily video cap):43 - `PY gemini.py video "..." --avatar @ai844579` → submit (may end in a stream error, fine)44 - `PY gemini.py pull --match video -o <dir>` → downloads finished videos from history45 - `PY gemini.py list` → see recent chats; `pull --cid c_xxxx` targets one.46 - The user can also generate videos in the Gemini APP directly, then just `pull`.47- **Daily video cap** exists even on paid plans ("come back tomorrow"). `pull` still48 works to download already-made videos.49- Longer ad (~22–24s): pull 2–3 clips and concat with `tools\ffmpeg.exe`.50- HeyGen MCP (talking avatar + real voiceover) remains a reliable alternative if51 Gemini's daily cap is hit or a specific avatar/lipsync is needed.5253## Editing AI video clips — ALWAYS edit, never blindly concat54AI clips (Gemini Omni etc.) have morphing/warping, weak first/last beats, garbled55on-screen text/logos, and per-clip audio that clashes when joined. Act like a56video editor with a timeline, not a `concat` script. Workflow (uses `tools\ffmpeg.exe`):57581. **Look at every clip's frames DENSELY.** 1 fps hides sub-second glitches — use59 **4 fps** and split each 10s clip into readable windows so frames are big enough60 to actually see (per 5s window = 20 frames in a 5x4 grid):61 `ffmpeg -i clip.mp4 -ss 0 -t 5 -vf "fps=4,scale=440:-1,tile=5x4" -frames:v 1 w0.png`62 `ffmpeg -i clip.mp4 -ss 5 -t 5 -vf "fps=4,scale=440:-1,tile=5x4" -frames:v 1 w5.png`63 READ every window. Frames are 0.25s apart, left→right, top→bottom, so you can name64 the exact second an artifact starts. Watch for: morphing faces, warped/garbled65 on-screen TEXT or fake LOGOS (a real example: one clip rendered a bogus "Ucire to66 HFT" logo at 8.5–9.75s — cut before it), empty/wide/tiny shots, ugly first/last67 frames. It's normal to keep only 2–4s of a 10s clip. (drawtext timestamps need a68 fontfile on Windows — skip it, use frame position instead.)692. **Look at the audio too.** Waveform + stats per clip:70 `ffmpeg -i clip.mp4 -filter_complex "showwavespic=s=1000x140" -frames:v 1 wave.png`71 `ffmpeg -i clip.mp4 -af volumedetect -f null -` and `silencedetect=noise=-38dB:d=0.3`.72 Flag silent stretches and dead-air. Video-good-but-audio-bad and vice versa are common.733. **Cut to the good parts** (frame-accurate = re-encode each segment, don't `-c copy`74 at arbitrary times).753b. **SEQUENCE — this is half the edit, not an afterthought.** Cutting out bad frames76 is only step one. Then lay ALL the clean pieces on the board and decide the ORDER77 like a creative director, because AI clips come out scattered. Ask: *what is the78 end goal of this video, and of each shot?* Then order for story, not for the order79 the clips happened to generate in:80 - **Hook (first 1–2s)** = your single most scroll-stopping shot — motion, a light-up81 "moment," or the most striking beauty frame. Never open on a slow/empty/dark hold82 just because it feels like an "intro." Get to something arresting immediately.83 - **Hero** right after the hook = the money beauty shot of the product.84 - **Feature beats** in the middle (display, charging, etc.).85 - **Detail** (macro/craft) as a texture beat.86 - **Breath** (one calm elegant shot) before the finish.87 - **Close** = a strong final hero/standing shot that leaves the product in mind.88 Drive the order from the AUDIO / voiceover / transcript when there is one (picture89 follows the words); with no VO, drive it from the visuals and the ad's goal. Then90 re-watch (re-mosaic the assembled cut) and re-order again if the flow is off — a91 reveal-structure (dark→ignite→hero) and a hook-first structure (ignite→hero→…) are92 both valid; pick the one that serves the goal, don't just keep generation order.934. **Unify the audio.** Don't keep 5 disjoint per-clip beds. Drop them and lay ONE94 continuous bed under the whole edit, with `afade` in/out. If a clip's audio is95 "just a sound," replace/overlay a better track (generate via `gemini.py media`,96 or HeyGen `search_audio_sounds` / a music bed). Align audio hits to visual cuts.975. **Target length** = the user's spec (default a tight ~22–24s ad; ~140 wpm VO ⇒98 ≤22–24 words per 10s of picture).996. **QC the result**: mosaic the final cut and confirm no artifacts slipped in.100101A worked example lives at `tools\gemini\out\videos\build_edit.sh` (curated segment102list + silent montage + unified faded bed + mux). Reuse/adapt its structure.103104### Parallelize with subagents (faster + more professional)105Don't do a multi-clip edit serially in one context. Fan the work out with the Agent106tool (or a Workflow) so the slow parts run concurrently and each agent stays focused:107- **Frame-analysis agents — one PER clip (fan out):** each generates its clip's dense108 4fps mosaics, reads them, and returns structured clean/bad sub-ranges + one-line notes109 (e.g. "logo artifact 8.5–9.75"). N clips → N agents at once.110- **Audio-analysis agent:** waveform + silencedetect + volumedetect per clip; flags dead111 air, and whether each clip's audio is musical or just ambient.112- **Sequencing/director agent:** takes all findings, decides the goal + hook, and returns113 the ordered segment list (the §3b decision). This is the creative brain.114- **Salvage agents:** for beats where the AUDIO/VO is good but the VISUAL is weak, don't115 drop the beat — see below.116- **QC agent:** re-mosaics the assembled cut and flags anything that slipped through.117Then the main context just assembles the approved segment list with ffmpeg. Result: the118per-clip inspection (the slow part) happens in parallel, and the edit is more consistent.119120### Salvage weak visuals (good audio, bad picture)121When you must keep a beat for timing/VO but its footage is ugly (morphy, empty, dull):122blur/darken it and put graphics on top to carry it — a real editor's move:123- Blur / darken bg: `-vf "gblur=sigma=20,eq=brightness=-0.1"`124- Overlay kinetic TEXT / lower-third: `drawtext` (needs a fontfile on Windows, e.g.125 `fontfile=C\:/Windows/Fonts/arialbd.ttf`), or render a transparent PNG and `overlay`.126- Add an emoji / sticker / logo PNG with `overlay=x:y` (optionally animated via expressions).127- Then the good audio/VO plays over a clean graphic beat instead of bad footage.128Use sparingly — blur-and-text is a patch for a weak second, not a substitute for real shots.129130## Voiceover audio (spoken)131The COOKIE web app (gemini.py) cannot do TTS — it only makes music + Omni-video132native VO. For a standalone spoken voiceover FILE there are two routes:1331341. **Gemini 2.5 TTS via the official API — `tts.py`** (needs a free API KEY, separate135 from cookies). Accent/style is set by the PROMPT, so a Nigerian accent works:136 `PY tts.py "Meet Series 11..." --accent "Nigerian English" --voice Charon -o vo.wav`137 `PY tts.py --list` (list TTS models + prebuilt voices)138 Key setup (once): free key at https://aistudio.google.com/apikey →139 `tools\gemini\gemini_api_key.txt` (git-ignored) or env `GEMINI_API_KEY`.140 These 2.5 TTS models are API-only; they never appear in the web app's model list.1412. **HeyGen** MCP: `create_speech` (needs a starfish-engine voice — designed voices142 aren't starfish, so pick a starfish voice or `clone_voice` the user's own voice for143 a true Nigerian accent), or the avatar @ai844579's own voice via an Omni video.144145Write the script first with `doc` (≤~22–24 words per 10s of picture), then TTS it.146147## Quick usage148Run from `tools\gemini`. `PY` = the venv python above.149150| Goal | Command |151|---|---|152| Verify auth + list models | `PY gemini.py check` |153| Ad copy / taglines / Q&A | `PY gemini.py ask "..."` |154| Ad/VO script → markdown file | `PY gemini.py doc "Write a 30s VO script for ..." -o <path>.md` |155| Analyse an image/pdf (vision) | `PY gemini.py ask "..." --file <path>` |156| Generate images | `PY gemini.py image "sleek smartwatch, 9:16, studio" -o <dir> -n watch -c 3` |157| Generate video | `PY gemini.py video "5s clip: ..." -o <dir>` |158| Generate music bed | `PY gemini.py media "upbeat 15s tech bed" --type audio -o <dir>` |159160Model choice: `--model gemini-3-pro | gemini-3-flash | gemini-3-flash-thinking`161(default = account default). Images: the CLI auto-prepends "Generate" so you get162AI images, not web images.163164## Auth (do first / when it breaks)1651. Preferred: `tools\gemini\cookies.json` with `__Secure-1PSID` (+ optional166 `__Secure-1PSIDTS`) copied from gemini.google.com DevTools → Cookies.1672. Or, if logged into gemini.google.com in the browser and no cookies.json, the168 `[browser]` extra auto-imports cookies.169- **Never read, extract, print, or paste the user's cookies yourself.** If auth170 fails (status 1016 UNAUTHENTICATED), tell the user to refresh `cookies.json`171 per `README.md §2`. Cookies expire regularly.172173## For anything beyond the CLI (chat sessions, gems, deep research)174Write a short async script against the venv using `gemini_webapi.GeminiClient`.175The pattern and full API are in `README.md §4` and `repo\README.md`.176177## Ad-workflow recipe (typical)1781. `doc` → generate the ad script + voiceover script (markdown).1792. `image` → generate hero shots / storyboard frames into the project's folder.1803. HeyGen `create_speech` → turn the VO script into spoken audio.1814. (optional) `media` → music bed; `video` → motion clips.1825. Assemble with `tools\ffmpeg.exe` (see project memories / existing workflow).