Turn a one-line premise into a complete AI manhwa recap video: original story narration β AI Horde images β TTS voice β Ken Burns motion MP4.
Live: https://manhwa-recap-robot.val.run/
| File | Purpose |
|---|---|
main.ts | HTTP server. Serves index.html/app.js (via staticHTTPServer) and the POST /api/generate AI Horde image backend. |
index.html | The app UI. |
app.js | All client logic β story writing, strict scripting engine, image/voice/video compilation. |
Instead of recapping real manhwa pages, the tool writes an original story from a premise and enforces a hard line-level style:
How it's enforced in app.js:
validateLine(line) β heuristic validator that returns { ok, words, issues[] }. It flags violations (past-tense verbs, passive β¦byβ¦, chained actions, filler phrases) rather than silently rewriting text, since programmatic grammar conversion is unreliable.renderValidation(lines) β paints each line in the storyboard green/red with its word count and the exact issue, plus a summary note.writeStory β after an LLM call, if more than ~30% of lines fail validation, it retries the LLM up to 2Γ, feeding back the precise list of failing lines ("Line 2 (14w): 14 wordsβ¦") so the model corrects itself. One or fewer bad lines is tolerated.defaultStory() β the no-key offline fallback. Fixed bug: the original returned a hard-coded 5 lines regardless of the panel count, so narration repeated verbatim. It now builds exactly count distinct lines via combinatorial slot-filling (NARR_OPEN Γ NARR_WHERE Γ NARR_THREAT), validated in place, so 12 panels never repeat.All keyed services are optional (click π Keys in the app and save β stored in your browser's localStorage):
sk-β¦ from OpenAI/OpenRouter/Groq) for AI story writing.tts-proxy).Server-side env vars (set on the val's Environment Variables page β these are what drive image quality):
| Env var | Purpose |
|---|---|
GEMINI_API_KEY | (recommended) Google AI Studio key β uses top-tier Gemini Nano Banana (gemini-2.5-flash-image, free-tier friendly; override with GEMINI_IMG_MODEL to try gemini-3.1-flash-image if your plan covers it), with automatic character-consistency (panel 1 is reused as the reference for every later panel). |
POLLINATIONS_KEY | Optional. Enables Pollinations flux-anime (manhwa-tuned Flux) + removes its logo. |
IMG_ENGINE | Force the engine: gemini | pollinations | horde. Auto-picks by whichever key is set. |
GEMINI_IMG_MODEL | Default gemini-3.1-flash-image; override to any Gemini image model. |
AI_HORDE_KEY | Last-resort fallback only. Anonymous works but is the low-end path. |
main.ts generates one image per panel server-side and returns same-origin data URLs (so the canvas is never tainted), churning a few panels per status poll so each request stays inside the free-tier 1-minute timeout.
Engine order ("no low-end models"): Gemini Nano Banana (primary) β Pollinations flux-anime (secondary) β AI Horde Stable Diffusion (last-resort fallback so the app works with zero keys).
apikey header, 850Γ850 anonymous cap, model fallback) are preserved on that fallback path only.