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:
- Present tense, active voice
- 8β12 words per line
- One action per sentence
- No filler or meta-commentary
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 exactlycountdistinct 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):
- LLM Key β any OpenAI-compatible endpoint (
sk-β¦from OpenAI/OpenRouter/Groq) for AI story writing. - AI Horde Key β server-side secret for images. Optional (anonymous works, with lower queue priority). Set the val's
AI_HORDE_KEYenv var. - Murf AI Key β paid TTS; leave blank to use the free TTS proxy (
tts-proxy).
main.ts generates one image per panel on AI Horde as same-origin data URLs (so the canvas is never tainted), polling until done with a 2βmin/panel cap. Every panel shows a canvas placeholder instantly, then real art swaps in as each URL resolves.
Notes on the AI Horde integration (these were the bugs that blocked image generation):
- Dimensions must be multiples of 64 β the backend snaps them.
- An
apikeyheader is required on every request β it defaults to the shared anonymous key0000000000. - Anonymous is capped at 850Γ850 β the backend scales the requested size down to fit while preserving aspect ratio. Setting a registered
AI_HORDE_KEYlifts the cap to 2048 (full 720p/1080p quality).