Generate lip sync mouth shape sprites from any face image using AI
Project description
Blabberer
AI-powered lip sync sprite generator
Turn any face photo into 9 production-ready mouth shape sprites — and animate them in real time.
https://github.com/user-attachments/assets/af47b852-281a-47c5-84c8-afd69edd79e9
Highlights
- One command, nine sprites — feed in a portrait, get back 9 mouth shapes based on the Preston Blair phoneme system
- Auto face detection — MediaPipe finds the face automatically; no manual cropping needed
- AI-generated — Gemini (via OpenRouter) generates each mouth shape from reference artwork
- Production-ready output — transparent backgrounds, soft-edge feathering, WebP format
- Real-time lip sync engine — vanilla TypeScript engine syncs audio energy + text phonemes to shapes at 60fps
- Claude Code plugin — install the skill and let Claude run the full pipeline for you
- Zero frameworks — Python stdlib for HTTP, vanilla TS for the demo — minimal dependencies
How It Works
Portrait → Face Detection → Gemini AI → 9 Mouth Shapes → Post-Processing → Sprites
(photo) (MediaPipe) (OpenRouter) (Preston Blair) (rembg + soft edges) (WebP)
The 9 Shapes
| Shape | Phonemes | Visual |
|---|---|---|
| A | M, B, P | Lips pressed together |
| B | S, T, D, K, N | Teeth visible, slightly open |
| C | A, I | Open mouth (speaking vowels) |
| D | E | Wide horizontal stretch |
| E | O | Rounded mouth |
| F | U, W, Q | Puckered lips |
| G | F, V | Upper teeth on lower lip |
| H | L, T, D | Barely parted lips |
| X | (idle) | Resting / closed mouth |
Quick Start
Install
# Clone
git clone https://github.com/historacle-ai/blabberer.git
cd blabberer
# Install (pick one)
uv pip install -e .
# or: pip install -e .
Generate sprites
export OPENROUTER_API_KEY=sk-or-... # https://openrouter.ai/keys
blabberer generate photo.jpg --output-dir ./sprites --verbose
Output:
sprites/
├── soft/ # Production-ready (transparent bg + soft edges)
│ ├── shape_A.webp
│ ├── shape_B.webp
│ ├── ...
│ └── shape_X.webp
├── shape_A.webp # Transparent background (no soft edges)
├── ...
└── shape_X.webp
CLI Reference
blabberer generate <image> [options]
Options:
--api-key KEY OpenRouter API key (or set OPENROUTER_API_KEY env var)
--output-dir, -o DIR Output directory (default: ./sprites)
--crop-box L,T,R,B Manual face crop box (auto-detects if omitted)
--model MODEL Gemini model (default: google/gemini-3.1-flash-image-preview)
--workers N Concurrent API calls (default: 3)
--skip-postprocess Skip background removal and soft edges
--verbose, -v Detailed output
Python API
from blabberer import generate_sprites, full_postprocess
# Generate sprites
results = generate_sprites(
image_path="photo.jpg",
output_dir="./sprites",
api_key="sk-or-...",
)
# Post-process (background removal + soft edges)
final = full_postprocess("./sprites")
Face Detection
from blabberer import detect_face_crop
from PIL import Image
image = Image.open("photo.jpg")
crop_box = detect_face_crop(image) # → (left, top, right, bottom)
# Custom expansion ratios
crop_box = detect_face_crop(
image,
expand_top=0.3, # 30% above face
expand_bottom=0.5, # 50% below face
expand_sides=0.25, # 25% each side
)
Interactive Demo
A browser demo lets you see lip sync in action — audio analysis drives mouth shapes in real time.
cd demo && npm install && npm run dev
# → http://localhost:5173
Two modes:
| Mode | Entry | What it does |
|---|---|---|
| Canvas (default) | simple.html |
Draws shapes on a <canvas> overlay — no sprites needed |
| Sprite | index.html |
Dual-layer crossfade with generated sprite images |
Lip Sync Algorithm
The LipSyncEngine uses a 3-tier energy model with text-informed shape selection:
- Audio analysis — Web Audio
AnalyserNodeextracts frequency data (first 30 bins) - Energy smoothing — exponential moving average (rise=0.28, decay=0.18)
- Hysteresis state machine — LOW / MID / HIGH with asymmetric thresholds to prevent flicker
- Text-to-shape mapping — 28 letter + 12 digraph preferences per energy level
- Min hold time — 100ms per shape prevents "chewing" artifacts
- Crossfade rendering — two stacked
<img>elements with 60ms CSS transitions
Use the Engine in Your Project
The demo's src/ files are standalone vanilla TypeScript — zero framework dependencies. Copy them into any project:
import { AudioAnalyser } from './audioAnalyser';
import { LipSyncEngine } from './lipSync';
const audio = document.querySelector('audio')!;
const analyser = new AudioAnalyser();
const node = analyser.connect(audio);
const engine = new LipSyncEngine(node!);
engine.loadText('Hello world');
audio.play();
function animate() {
requestAnimationFrame(animate);
const shape = engine.update(performance.now());
// shape: 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'X'
}
requestAnimationFrame(animate);
Claude Code Plugin
Blabberer ships as a Claude Code plugin with a /lip-sync-pipeline skill that automates the entire workflow.
Install
/plugin install historacle-ai/blabberer
Run
/blabberer:lip-sync-pipeline photo.jpg
Claude handles face detection, sprite generation, post-processing, demo setup, and troubleshooting — end to end.
Requirements
| Component | Requirement |
|---|---|
| Python | >= 3.10 |
| API key | OpenRouter with Gemini model access |
| Disk | ~170 MB for rembg U2Net model (downloaded on first run) |
| Node.js | >= 18 (demo only) |
Project Structure
blabberer/
├── blabberer/ # Python package
│ ├── cli.py # CLI entry point
│ ├── generator.py # Face detect → Gemini → sprites
│ ├── face_detect.py # MediaPipe face detection
│ ├── shapes.py # 9 Preston Blair shape definitions
│ ├── postprocess.py # Background removal + soft edges
│ └── reference/ # 12 bundled reference images
├── demo/ # Browser lip sync demo
│ ├── simple.html # Canvas mode (default)
│ ├── index.html # Sprite mode
│ └── src/ # Vanilla TypeScript
│ ├── lipSync.ts # Audio + text → shape engine
│ ├── audioAnalyser.ts # Web Audio API bridge
│ ├── mouthRenderer.ts # Dual-layer crossfade
│ ├── simple.ts # Canvas demo
│ └── main.ts # Sprite demo
├── skills/ # Claude Code plugin
│ └── lip-sync-pipeline/
├── .claude-plugin/ # Plugin manifest
└── pyproject.toml
Contributing
Contributions are welcome! Feel free to open an issue or submit a pull request.
- Fork the repo
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes
- Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
About HistOracle
Blabberer was extracted from the production lip sync pipeline at HistOracle — an AI platform that brings historical figures to life through interactive conversations. HistOracle uses AI-generated visemes, real-time audio analysis, and natural language understanding to create lifelike talking portraits of figures from history.
We open-sourced the lip sync sprite generation and animation engine so developers, educators, and creators can build their own talking-face experiences.
License
MIT License — see LICENSE.
Copyright (c) 2026 Editlingo Solutions LLC
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file blabberer-0.1.0.tar.gz.
File metadata
- Download URL: blabberer-0.1.0.tar.gz
- Upload date:
- Size: 323.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea7abd1ea42d6f067adc94c7e2829034b9bc24cceb411ef5d3f606e2bdb4f1d4
|
|
| MD5 |
6eb6ae00d480ebfc5e6124d5b3e32c11
|
|
| BLAKE2b-256 |
dfd04066e110303c60ff3c581037fc65f62aa2db8f5edc293af93c7a8a3bcf46
|
File details
Details for the file blabberer-0.1.0-py3-none-any.whl.
File metadata
- Download URL: blabberer-0.1.0-py3-none-any.whl
- Upload date:
- Size: 326.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51dce4de1f6f4a04c9e9c0f775c5e32b8300e6b0a4002046a8c929748ddfb5d4
|
|
| MD5 |
0e2a74d751513cf6f64a5473418a18a1
|
|
| BLAKE2b-256 |
af3cb9a8f1e09efda0e50714e256eafd23a56baa178e7907f86c51a0bb6bfcb5
|