victor's picture
victor HF Staff
Upload folder using huggingface_hub
aa7348e verified
Raw History Blame Contribute Delete
12.3 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>The Making of THE ODYSSEY (ASCII)</title>
<style>
:root{ --ink:#e8e6df; --bg:#0b0c0f; --card:#141519; --line:#26282e; --gold:#c9a24b; --mut:#8b8d95; }
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font-family:-apple-system,system-ui,"Helvetica Neue",sans-serif;line-height:1.5}
.wrap{max-width:1040px;margin:0 auto;padding:0 20px}
header.hero{padding:90px 20px 50px;text-align:center;background:radial-gradient(80% 60% at 50% 0%, #1a1d24, var(--bg));}
header.hero h1{font-size:clamp(30px,5.5vw,58px);margin:0 0 10px;letter-spacing:.01em}
header.hero .sub{color:var(--gold);letter-spacing:.28em;text-transform:uppercase;font-size:12px;font-weight:600}
header.hero p{color:var(--mut);max-width:640px;margin:22px auto 0;font-size:16px}
.stack{display:flex;flex-direction:column;gap:64px;padding:10px 0 90px}
.frame{border:1px solid var(--line);border-radius:8px;overflow:hidden;background:#000}
.frame img,.frame video{display:block;width:100%;height:auto}
h2{font-size:22px;margin:0 0 4px;display:flex;align-items:baseline;gap:10px}
h2 .n{color:var(--gold);font-size:14px;font-weight:700;letter-spacing:.1em}
.lede{color:var(--mut);margin:0 0 18px;font-size:15px;max-width:640px}
.stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:14px;margin:26px 0}
.stat{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:16px 14px;text-align:center}
.stat b{display:block;font-size:26px;color:var(--gold)}
.stat span{font-size:12px;color:var(--mut);text-transform:uppercase;letter-spacing:.06em}
.quote{border-left:3px solid var(--gold);padding:2px 0 2px 16px;margin:16px 0;color:#cfd0d6;font-size:14.5px}
.quote::before{content:"β€œ ";color:var(--gold)}
.quote small{display:block;margin-top:4px;color:var(--mut);font-size:11.5px;letter-spacing:.04em;text-transform:uppercase}
.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.gallery figure{margin:0;border:1px solid var(--line);border-radius:6px;overflow:hidden;background:#000}
.gallery img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}
.gallery figcaption{padding:8px 10px;font-size:12px;color:var(--mut)}
.two-col{display:grid;grid-template-columns:1fr 1fr;gap:16px}
.pill{display:inline-block;background:var(--card);border:1px solid var(--line);border-radius:20px;padding:4px 12px;font-size:12px;color:var(--gold);margin:2px 6px 2px 0}
.fx-table{width:100%;border-collapse:collapse;font-size:13.5px;margin-top:14px}
.fx-table td{padding:7px 8px;border-top:1px solid var(--line);color:#cfd0d6}
.fx-table td:first-child{color:var(--gold);white-space:nowrap;font-weight:600}
.fx-table td:nth-child(2){color:var(--mut);white-space:nowrap}
footer{text-align:center;color:var(--mut);font-size:12px;padding:40px 20px 60px;border-top:1px solid var(--line)}
footer a{color:var(--gold);text-decoration:none}
@media(max-width:700px){ .gallery{grid-template-columns:repeat(2,1fr)} .two-col{grid-template-columns:1fr} }
</style>
</head>
<body>
<header class="hero">
<div class="sub">Behind the scenes</div>
<h1>The Making of<br/><em>THE ODYSSEY</em></h1>
<p>A 90-second film, cast entirely in ASCII text, built and directed end-to-end by <b>Kimi K3</b> running inside Claude Code β€” no stock footage, no templates, no human touching a single pixel. Here's how it actually happened.</p>
</header>
<div class="wrap stack">
<section>
<div class="frame"><img src="img/title.png" alt="Title card"/></div>
</section>
<section>
<h2><span class="n">01</span> One paragraph, one film</h2>
<p class="lede">The entire brief was a single sentence: build the most realistic Boeing 747 in three.js β€” wait, wrong file. For this one, the ask was even shorter: <em>write an ASCII adaptation of Homer's Odyssey and direct it like a real film.</em> Everything below β€” the renderer, the ten scenes, the camera moves, the score β€” Kimi invented on its own.</p>
<div class="stat-row">
<div class="stat"><b>0</b><span>assets used</span></div>
<div class="stat"><b>12</b><span>scenes</span></div>
<div class="stat"><b>2,172</b><span>frames hand-drawn</span></div>
<div class="stat"><b>90.5s</b><span>runtime</span></div>
</div>
</section>
<section>
<h2><span class="n">02</span> It built its own camera before it built the story</h2>
<p class="lede">Before writing a single scene, Kimi wrote itself a tiny film studio: a character-grid renderer, a rasterizer to turn text into pixels, and β€” critically β€” a way to look at what it had drawn. Every scene got checked against a real render before moving on.</p>
<div class="quote">I'll build this as a real production: a Python ASCII render engine, scene-by-scene direction, a Pillow rasterizer, visual self-inspection loops, then ffmpeg encode.<small>Kimi K3, turn 1</small></div>
</section>
<section>
<h2><span class="n">03</span> The blooper reel it never showed you</h2>
<p class="lede">This is the fun part. Kimi rendered a frame, looked at it, hated it, and fixed it β€” over and over. Real quotes, no cleanup:</p>
<div class="two-col">
<div>
<div class="quote">The title text is uniform blobs β€” no internal texture… <small>after render #1</small></div>
<div class="quote">Title still fails β€” the vignette multiplies the text down to mid-density glyphs. I need to draw text <em>after</em> vignetting.<small>after render #2</small></div>
<div class="quote">My "silhouette + rim" double-draw in Cyclops cancels itself (the max undoes the min).<small>debugging the cave scene</small></div>
</div>
<div>
<div class="quote">Storm is a wall of dense glyphs that swallows the ship β€” the sea needs a gamma to suppress mid-tones, plus a hull shadow to silhouette the ship against foam.<small>fixing the storm</small></div>
<div class="quote">Sea and moon now work. Remaining fixes: title text needs near-uniform dense glyphs, stars should be tiny dots not bright letters…<small>the punch-list kept growing</small></div>
<div class="quote">Common diseases: backgrounds are dot-fields instead of black, vignette dims the text… time for a comprehensive revision pass.<small>the moment it stopped patching and rewrote</small></div>
</div>
</div>
</section>
<section>
<h2><span class="n">04</span> Old tricks, done in a text file</h2>
<p class="lede">No shaders, no GPU β€” every "cinematic" effect is arithmetic on a grid of characters.</p>
<div style="margin:10px 0 4px">
<span class="pill">film grain β€” random brightness jitter, Β±3%</span>
<span class="pill">vignette β€” darken toward the frame edge</span>
<span class="pill">bloom on fire &amp; torches</span>
<span class="pill">gate weave β€” vintage-projector wobble</span>
<span class="pill">dither, to kill banding in the glows</span>
</div>
<p class="lede" style="margin-top:14px">(The gate weave got cut in the final pass β€” at character-grid resolution a one-row shift is a visible jump, not a wobble, so it was removed for a steadier image. Real film-restoration problem, solved the same way an editor would.)</p>
</section>
<section>
<h2><span class="n">05</span> The gallery</h2>
<p class="lede">All twelve scenes, straight off the render engine.</p>
<div class="gallery">
<figure><img src="img/troy.png"/><figcaption>Troy β€” the fall and the departure</figcaption></figure>
<figure><img src="img/storm.png"/><figcaption>Poseidon's storm</figcaption></figure>
<figure><img src="img/cyclops.png"/><figcaption>The cave of Polyphemus</figcaption></figure>
<figure><img src="img/sirens.png"/><figcaption>The Sirens' song</figcaption></figure>
<figure><img src="img/charybdis.png"/><figcaption>Charybdis, the whirlpool</figcaption></figure>
<figure><img src="img/calypso.png"/><figcaption>Calypso's isle</figcaption></figure>
<figure><img src="img/ithaca_card.png"/><figcaption>Ithaca β€” the twentieth year</figcaption></figure>
<figure><img src="img/hall.png"/><figcaption>The great hall</figcaption></figure>
<figure><img src="img/penelope.png"/><figcaption>The reunion</figcaption></figure>
<figure><img src="img/end.png"/><figcaption>Journey's end</figcaption></figure>
<figure><img src="img/cyc_card.png"/><figcaption>Intertitle, silent-film style</figcaption></figure>
<figure><img src="img/title.png"/><figcaption>Opening card</figcaption></figure>
</div>
</section>
<section>
<h2><span class="n">06</span> Beaten 495 times, kept working</h2>
<p class="lede">Kimi K3 runs on a shared, rate-limited API. Over the two-hour build it got knocked back with "rate limit exceeded" <b>495 separate times</b> β€” and just retried, quietly, until each scene actually rendered.</p>
<div class="stat-row">
<div class="stat"><b>145</b><span>agent turns</span></div>
<div class="stat"><b>495</b><span>rate-limit hits survived</span></div>
<div class="stat"><b>125 min</b><span>build time</span></div>
<div class="stat"><b>$6.75</b><span>total cost</span></div>
</div>
</section>
<section>
<div class="frame">
<video controls preload="metadata" poster="img/title.png">
<source src="odyssey_scored.mp4" type="video/mp4" />
</video>
</div>
</section>
<section>
<h2><span class="n">07</span> Then it scored its own film</h2>
<p class="lede">In a follow-up session, Kimi turned the silent film into a full production β€” narrator, orchestral score, and sound design β€” using ElevenLabs. It wrote twelve original passages, one per scene, then had to solve the hardest part: making a real human voice land <em>exactly</em> on the picture.</p>
<div class="quote">Bill speaks ~20% slower than George β€” every passage was shortened and re-measured until it fit its window with margin: troy 28β†’19 words, cyclops 28β†’22 (kept the "Nobody" wordplay), penelope 24β†’16.<small>repacing the narration, take 2</small></div>
<p class="lede">That "Nobody" line is a three-thousand-year-old joke: in the original, Odysseus tells the Cyclops his name is <em>Nobody</em> β€” so when he's blinded and screams for help, the other Cyclopes hear "Nobody is hurting me!" and walk away. Kimi kept the gag.</p>
</section>
<section>
<h2><span class="n">08</span> Casting an elder bard</h2>
<p class="lede">The first cut used a smooth, youthful narrator. Asked for someone older, Kimi auditioned voices instead of guessing:</p>
<div class="quote">The only roster voice labeled "old" β€” wise, mature, balanced. Previewed against Callum (husky trickster β€” wrong character) with the title line before committing.<small>casting the narrator</small></div>
</section>
<section>
<h2><span class="n">09</span> The trick that keeps the voice audible</h2>
<p class="lede">Orchestral score and narration fight for the same space. Kimi's fix is the same one real film mixers use: <b>sidechain ducking</b> β€” the score automatically drops in volume the instant the narrator speaks, then swells back in the silence.</p>
<table class="fx-table">
<tr><td>Sidechain duck</td><td>8:1, 30ms attack</td><td>music ducks 10–13 dB under speech, swells back between lines</td></tr>
<tr><td>Thunder crack</td><td>18.5s</td><td>timed to the lightning flash, not just "somewhere in the storm"</td></tr>
<tr><td>Cyclops' roar</td><td>30.6s</td><td>lands exactly on the blinding flash</td></tr>
<tr><td>Arrow whoosh</td><td>68.8s</td><td>fired on the frame the bowstring releases</td></tr>
<tr><td>Hall melee</td><td>70.3s</td><td>covers the suitors' fall under score</td></tr>
</table>
<p class="lede" style="margin-top:16px">Final master: three audio buses (voice / ducked music / effects) through a limiter and two-pass loudness normalization β€” the same signal chain a professional mix engineer would reach for.</p>
</section>
<footer>
Built end-to-end by <b>Kimi K3</b> (via OpenRouter) inside Claude Code, on the user's own Hetzner instance.
ASCII engine, ten scenes, narration, score and sound design β€” all model-authored.
</footer>
</div>
</body>
</html>