- Python 99%
- Dockerfile 1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| localdream-custom-models.md | ||
| localdream-skill.md | ||
| localdream.ico | ||
| localdream_bridge.py | ||
| localdream_client.py | ||
| localdream_mcp.py | ||
| README.md | ||
| testgit.txt | ||
🎨 Local Dream Bridge
Generazione immagini AI dal ROG Phone 7, esposta come servizio per il tuo homeserver — e per tutto il resto.
Il telefono (Local Dream in host mode, NPU Snapdragon) diventa un'API di generazione immagini raggiungibile da qualsiasi nodo della tua Tailnet:
- 🖥️ Web UI standalone per generare dal browser
- 🟣 API OpenAI-compatibile (
/v1/images/generations) → funziona con Open WebUI e qualunque client OpenAI - 🤖 Server MCP → qualunque agente (Hermes, Claude, Cursor…) può generare immagini
- 🐍 CLI Python per script e cron
Testato dal vivo: 512×512 in 3,8–5,5s (SD1.5 su NPU Snapdragon).
📋 Requisiti
| Cosa | Dettaglio |
|---|---|
| Telefono | ROG Phone 7 (o qualunque Android) con Local Dream in host mode |
| Rete | Tailscale su telefono e server (es. 100.71.138.50 = telefono) |
| Server | Windows/Linux con Python 3.11+ oppure Docker |
⚠️ L'API del Local Dream non ha autenticazione: tieni tutto su Tailscale, non esporre mai le porte su Internet.
📁 Struttura del progetto
localdream/
├── README.md ← questo file
├── localdream-skill.md ← come collegare l'MCP a un'altra AI (Hermes, Claude, Cursor…)
├── localdream-custom-models.md ← guida modelli custom (Hugging Face + Termux + import in-app)
├── localdream_client.py ← CLI (zero dipendenze, solo stdlib)
├── localdream_bridge.py ← Web UI + API OpenAI (Flask)
├── localdream.ico ← favicon della web UI (tab del browser)
├── localdream_mcp.py ← Server MCP per agenti (mcp SDK 1.x/2.x)
├── Dockerfile ← immagine del bridge
├── docker-compose.yml ← avvio del bridge in container
└── localdream_out/ ← immagini generate (creata automaticamente)
🚀 Avvio rapido
1. CLI (test più veloce)
python localdream_client.py --host 100.71.138.50 info # identità host
python localdream_client.py --host 100.71.138.50 models # catalogo modelli
python localdream_client.py --host 100.71.138.50 generate-all \
--model anythingv5 --prompt "a cute corgi astronaut in space" --steps 12 --out corgi.png
2. Bridge — Python diretto
pip install flask requests
python localdream_bridge.py --host 100.71.138.50 --port 8095
# → Web UI: http://127.0.0.1:8095/
# → OpenAI: http://127.0.0.1:8095/v1
3. Bridge — Docker Compose
docker compose up -d --build
# → Web UI: http://<server-ip>:8095/
Configurabile via environment nel compose (vedi sotto).
🧩 Endpoint del bridge
| Endpoint | Descrizione |
|---|---|
GET / |
Web UI (stile EzTTS): modello, prompt, negative, steps, CFG, scheduler, denoise, aspect ratio, seed, formato |
POST /api/generate |
Genera: {model, prompt, negative_prompt, steps, cfg, scheduler, denoise_strength, size, aspect_ratio, seed, output_format, image, ultrafix, tile_size} |
GET /api/models · GET /api/status · POST /api/stop |
Catalogo / stato backend / stop |
GET /api/gallery |
Ultime 20 immagini con i parametri usati (sidecar JSON) |
DELETE /api/gallery/<file> |
Elimina un'immagine dal server (e il suo sidecar) — la ✕ nella web UI |
POST /api/upscale |
Upscala un'immagine della galleria: `{file, upscaler_id, scale: 2 |
GET /img/<file> |
File immagine (download / visualizzazione) |
POST /v1/images/generations |
OpenAI-compatible: {model, prompt, size, n, response_format, scheduler, denoise_strength, aspect_ratio} → {data:[{b64_json|url}]} |
GET /v1/models · GET /health |
Lista modelli stile OpenAI / healthcheck |
Salvataggio locale: ogni immagine generata viene salvata sul server in localdream_out/ (nome ld_<modello>_<timestamp>.<ext>), con link di download nella web UI e galleria delle ultime 20 (GET /api/gallery).
Log parametri (sidecar JSON): accanto a ogni immagine viene salvato un file .json con i parametri usati (modello, prompt, negative, steps, cfg, scheduler, seed, denoise, aspect ratio, risoluzione, tempo). La web UI li mostra come chips nelle card della galleria — così puoi replicare lo stile di un'immagine che ti piace. Le immagini generate prima di questo aggiornamento non hanno il sidecar (la card mostra "parametri non salvati").
Parametri (protocollo v2.8.1, reversato dal sorgente xororz/local-dream):
| Parametro | Default | Note |
|---|---|---|
scheduler |
dpm |
dpm, dpm_karras, dpm_sde, dpm_sde_karras, euler, euler_karras, euler_a, euler_a_karras, lcm |
denoise_strength |
0.6 |
0–1, forza del renoise (img2img) |
aspect_ratio |
1:1 |
4:3, 3:4, 16:9, 9:16 — usato solo da SDXL/Anima (canvas fisso 1024 + crop) |
image |
— | base64 di un'immagine → img2img (il backend la ridimensiona alla size scelta) |
ultrafix + tile_size |
false / 512 |
UltraFix: img2img a tile (richiede image; tile 512 SD1.5, 1024 SDXL; no mask) |
seed |
random | fisso per riproducibilità |
steps / cfg |
12 / 7 |
1–50 / 1–20 |
Upscale (2x/3x/4x): POST /api/upscale con {"file": <nome in localdream_out>, "scale": 2|3|4} usa l'upscaler NPU del telefono (il backend emette sempre 4x nativo; 2x/3x = downscale del risultato). Nella web UI: bottoni ⬆2x/3x/4x su ogni card della galleria (visibili solo se il telefono ha un upscaler nel catalogo). L'immagine upscalata viene salvata in localdream_out/ con sidecar {type: upscale, source, scale, ...}. Richiede pillow sul bridge (già nel Dockerfile).
Privacy: la ✕ in alto a destra su ogni card della galleria elimina l'immagine dal server (immagine + sidecar) — se qualcuno non vuole essere visto, via in un click. Endpoint: DELETE /api/gallery/<file>. Le immagini eliminate NON vengono recuperate dallo storage cap (rimozione definitiva).
Limite di archiviazione: localdream_out/ non supera mai LOCAL_DREAM_MAX_STORAGE_GB GB (default 10, configurabile via environment nel compose; 0 = nessun limite). Al raggiungimento del tetto le immagini più vecchie vengono eliminate automaticamente per fare spazio alle nuove — il disco non si riempie mai.
Auto-riparazione: se il backend nativo (8081) è morto — succede quando il telefono si blocca e Android lo uccide, mentre la control API (8808) continua a dire "running" — il bridge fa stop + select da solo e ritenta. Stessa logica nel client CLI e nel server MCP.
Esempio OpenAI:
curl -X POST http://localhost:8095/v1/images/generations \
-H 'Content-Type: application/json' \
-d '{"model":"anythingv5","prompt":"cyberpunk city street at night, neon lights","size":"512x512"}'
Il bridge fa automaticamente /select + attesa backend + /generate: nessun passaggio manuale.
🟣 Open WebUI
In Settings > Admin > Experience > Images:
- Image Generation: ON
- Engine: Default (Open AI)
- API Base URL:
http://host.docker.internal:8095/v1(se il bridge è sull'host) oppurehttp://<ip-del-server>:8095/v1 - API Key: qualsiasi (es.
local-dream) - Model ID:
anythingv5(o uno dei modelli sotto) - Image Size:
512x512
Oppure via variabili d'ambiente del container Open WebUI:
ENABLE_IMAGE_GENERATION: "true"
IMAGE_GENERATION_ENGINE: "openai"
IMAGE_GENERATION_MODEL: "anythingv5"
IMAGE_SIZE: "512x512"
IMAGES_OPENAI_API_BASE_URL: "http://host.docker.internal:8095/v1"
IMAGES_OPENAI_API_KEY: "local-dream"
In chat: attiva il toggle Image nel menu Integrations del campo messaggio.
🤖 Agenti (MCP)
pip install "mcp" requests
python localdream_mcp.py # stdio — compatibile mcp SDK 1.x (FastMCP) e 2.x (MCPServer)
| Tool | Descrizione |
|---|---|
localdream_info |
identità host |
localdream_models |
catalogo modelli |
localdream_status |
stato backend |
localdream_generate |
genera immagine → base64 + file salvato (parametri v2.8.1 completi: scheduler, denoise_strength, aspect_ratio) |
localdream_stop |
ferma il backend (risparmia batteria) |
Registrazione in Hermes (config.yaml):
mcp_servers:
localdream:
command: python
args: ["C:/localdream/localdream_mcp.py"]
📦 Modelli (catalogo del telefono)
| ID | Nome | Stile |
|---|---|---|
anythingv5 |
Anything V5.0 | Anime |
qteamix |
QteaMix | Chibi anime |
absolutereality |
Absolute Reality | Realistico |
cuteyukimix |
CuteYukiMix | Anime carino |
chilloutmix |
ChilloutMix | Realistico |
Risoluzioni: 512×512 → 1024×1024 (multipli di 8).
📚 Guide correlate (nella stessa cartella)
localdream-skill.md— collegare l'MCP a un'altra AI (Hermes, Claude Desktop, Cursor, client MCP generici) + alternativa API OpenAIlocaldream-custom-models.md— modelli custom: scaricare da Hugging Face con Termux, importare safetensors SD1.5 (conversione in-app) o zip NPU_8gen2dal repo ufficialexororz/sd-qnn
🔒 Sicurezza
- Nessuna autenticazione tra bridge e telefono: solo Tailscale.
- Se vuoi proteggere il bridge: mettilo dietro un reverse proxy con basic auth, o limita il bind a
127.0.0.1. - Il telefono deve restare in host mode; a riposo il backend caricato consuma poca batteria, fermalo con
POST /api/stop(olocaldream_stop) quando non serve.
🩺 Troubleshooting
| Problema | Causa / Fix |
|---|---|
8081: connection refused |
Il backend parte solo dopo /select — usa il client/bridge che lo fa da solo, oppure select manuale |
Errore "8081 non raggiungibile" mentre /health dice running |
Telefono bloccato: Android uccide il backend nativo ma la control API resta "running" — sblocca il telefono; i tool ora riavviano da soli con stop+select |
/info non risponde |
Host mode spento o Tailscale giù sul telefono |
| Generazione lenta | Primo avvio dopo il boot: caricamento modello in RAM (~10-60s) |
| Open WebUI non genera | Toggle Image nelle Integrations della chat + capability Image Generation sul modello (Workspace > Models > Edit) |
Progetto personale di F0X1Y — protocollo Local Dream reversato dal sorgente (xororz/local-dream v2.8.x), non documentato ufficialmente. Guida estesa nel vault Obsidian: Notes-Server/LOCAL_DREAM_API.md.