Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from bundle
Generate face-consistent images with Nano Banana 2 via fal.ai. Use when the user wants to generate photos of themselves or someone else in different poses, expr
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: nano-banana-fal3description: "Generate face-consistent images with Nano Banana 2 via fal.ai. Use when the user wants to generate photos of themselves or someone else in different poses, expressions, or scenes while preserving face identity. Triggers: nano banana, face consistent, generate photo of me, face reference image, identity-preserving image generation, fal.ai image edit"4---56# Nano Banana 2 — Face-Consistent Image Generation (fal.ai)78Generate images that preserve a person's face identity using the Nano Banana 2 edit model on fal.ai.910## Quick Start1112```bash13uv run --with fal-client {baseDir}/scripts/nano_banana_edit.py \14--face ./my_face.png \15--prompt "A young man sitting at a desk, thoughtful expression, studio lighting" \16--output ./generated/scene.png17```1819## Credential Resolution2021The script resolves fal.ai credentials in this order:221. `--api-key` CLI flag232. `FAL_KEY` env var (official primary)243. `FAL_API_KEY` env var254. `FAL_AI_KEY` env var265. `~/.secrets/fal.env` file (lines like `FAL_KEY=xxx`)2728## Parameters2930| Flag | Default | Description |31|------|---------|-------------|32| `--face` | required | Face reference image — a portrait, a rotation grid, or any image showing the character |33| `--prompt` | required | Scene/expression description |34| `--output` | required | Output image path (.png) |35| `--aspect-ratio` | `9:16` | `1:1`, `16:9`, `9:16`, `4:3`, `3:4` |36| `--resolution` | `2K` | `1K`, `2K`, `4K` |37| `--seed` | random | For reproducibility |38| `--model` | `fal-ai/nano-banana-2/edit` | fal.ai model endpoint. Fallback: `fal-ai/nano-banana/edit` (v1, Gemini 3 Pro) |3940## Using Rotation Grids as Face Reference4142A rotation grid (multi-angle body shots in one image) is the strongest reference for character identity. It carries face, body proportions, and style all at once. Pass it directly as `--face`.4344```bash45# Rotation grid as face reference — strongest identity preservation46uv run --with fal-client {baseDir}/scripts/nano_banana_edit.py \47--face ./rotation_grid.png \48--prompt "The girl from the reference, wearing a leather jacket, talking to camera in a dark room" \49--output ./scene.png50```5152If no rotation grid exists yet, generate one first from a face portrait:53```bash54uv run --with fal-client {baseDir}/scripts/nano_banana_edit.py \55--face ./face_portrait.png \56--prompt "8-panel rotation grid showing the character from front, 3/4 left, side left, 3/4 back, back, 3/4 right, side right, 3/4 front. Full body, consistent outfit, neutral pose, studio lighting, white background" \57--aspect-ratio 16:9 \58--output ./rotation_grid.png59```6061Then use the generated grid as `--face` for all subsequent scene generation.6263### What does NOT work for in-place replacement64- Passing the **source frame** (the image you want to replace the character in) as an `image_url` dilutes face identity — the model blends both faces and produces a generic result65- Instead, describe the source scene's environment in the **prompt** while using the grid or portrait as `--face`6667## Prompt Tips for Face-Consistent Generation6869### Strict in-place character replacement (from source video frames)7071When replacing a character in an existing video frame:721. Extract the first frame from the source video732. Use face portrait + rotation grid as `image_urls` (NOT the source frame)743. Describe the source frame's exact environment, lighting, pose, and camera angle in the prompt754. Include specific details: monitor colors, neon lighting direction, room layout, character pose/gesture7677**Prompt template for scene replacement:**78```79"The [character description] from the reference images, wearing [outfit matching original], [exact pose/gesture from original frame], [expression], [exact environment description from original frame], [lighting description], photorealistic, vertical portrait photo, clean photo no text overlays no UI elements"80```8182### What works well83- Describe the **scene, pose, and expression** — the model handles face consistency automatically84- Include background/environment details matching the source frame for best results85- Neutral or thoughtful expressions work best with most face references86- Always end with "photorealistic, vertical portrait photo, clean photo no text overlays no UI elements"8788### What may fail (422 errors)89- Prompts asking for extreme expressions (big smiles, wide eyes) that differ greatly from the reference face's natural expression90- The model sometimes rejects prompts it can't reconcile with the input face91- If you get `invalid_request` errors, simplify the expression and retry9293### Example prompts that work94```95"The blonde girl with black hair bow from the reference images, wearing a dark leather jacket open over a black top showing cleavage, excitedly talking to camera with both hands gesturing expressively, mouth open mid-speech, standing in a dark futuristic tech room with multiple large glowing green code terminal monitors behind her, a bright horizontal fluorescent light bar above, dark ceiling with cables, purple-blue ambient neon lighting, photorealistic, vertical portrait photo, clean photo no text overlays no UI elements"9697"The blonde girl with black hair bow from the reference images, wearing a dark studded leather jacket, enthusiastically raising both fists in an excited celebration gesture, big smile, standing in a dark hacker room surrounded by multiple glowing green code terminal monitors, bright neon pink rectangular light panel glowing behind her head, photorealistic, vertical portrait photo, clean photo no text overlays no UI elements"98```99100### Example prompts that may fail101```102"A young man with excited expression, eyes wide open, big smile, eureka moment"103→ Often rejected if reference face is neutral/serious104```105106**Workaround**: Use milder expressions like "looking confident", "leaning forward with interest" instead of extreme emotions.107108## Batch Generation109110For multiple scenes, upload the face and grid once and reuse the URLs:111112```python113import fal_client114115face_url = fal_client.upload_file("./face.png") # upload once116grid_url = fal_client.upload_file("./rotation_grid.png") # upload once117118for scene in scenes:119result = fal_client.subscribe("fal-ai/nano-banana-2/edit", arguments={120"prompt": scene["prompt"],121"image_urls": [face_url, grid_url],122"aspect_ratio": "9:16",123"resolution": "2K",124})125```126127## Cost128129~$0.15 per image at 2K resolution.130131## Fallback: Nano Banana v1132133When Nano Banana 2 (`fal-ai/nano-banana-2/edit`) is down (504 / downstream_service_unavailable),134use v1 which runs on a different backend (Gemini 3 Pro):135136```bash137uv run --with fal-client {baseDir}/scripts/nano_banana_edit.py \138--face ./face.png \139--prompt "..." \140--model fal-ai/nano-banana/edit \141--output ./scene.png142```143144Both models accept the same `image_urls` + `prompt` API. v1 may produce slightly different style but face consistency is comparable.145146## Troubleshooting147148| Error | Cause | Fix |149|-------|-------|-----|150| `downstream_service_unavailable` | fal.ai GPU pool overloaded | Auto-fallback to v1; or wait 1-2 min, retry |151| `invalid_request` / 422 | Prompt incompatible with face | Simplify expression, remove extreme emotions |152| `file_too_large` (>5MB) | OmniHuman/Kling rejects large images | Resize: `ffmpeg -i big.png -vf "scale=1080:-1" small.png` |153| `ModuleNotFoundError: fal_client` | Missing dependency | `pip install fal-client` or use `uv run --with fal-client` |154155## Important: Image Size for Downstream Pipeline156157OmniHuman and Kling reject images >5MB. When generating at 2K resolution, always resize before passing to lipsync/motion:158159```bash160# Check and resize if needed161size=$(stat -c%s image.png)162if [ "$size" -gt 5000000 ]; then163ffmpeg -y -i image.png -vf "scale=1080:1920:force_original_aspect_ratio=decrease" image.png164fi165```166