No description
  • Python 86.4%
  • JavaScript 7.1%
  • HTML 4.3%
  • Just 1.5%
  • Dockerfile 0.4%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-22 15:59:35 -05:00
app fix: explain duplicate Quick Make requests (#10) 2026-10-22 15:59:35 -05:00
deploy Add creator RSS backfill management 2026-10-11 21:30:22 -05:00
docs Publish public URL mentions index (#9) 2026-10-22 13:37:25 -05:00
performance-reports docs: record Brainrot production Lighthouse results 2026-10-13 20:21:25 -05:00
scripts perf: reduce mobile feed startup work 2026-10-13 20:53:02 -05:00
tests fix: explain duplicate Quick Make requests (#10) 2026-10-22 15:59:35 -05:00
.dockerignore Ship Brainrot creator studio 2026-10-10 15:18:55 -05:00
.env.example Ship Brainrot creator studio 2026-10-10 15:18:55 -05:00
.gitignore feat: route Brainrot speech through Kokoro service 2026-10-11 11:07:19 -05:00
AGENTS.md Harden Python 3.14 checks and container 2026-10-10 18:46:38 -05:00
Dockerfile feat: route Brainrot speech through Kokoro service 2026-10-11 11:07:19 -05:00
justfile Harden Python 3.14 checks and container 2026-10-10 18:46:38 -05:00
mise.toml Harden Python 3.14 checks and container 2026-10-10 18:46:38 -05:00
pyproject.toml perf: streamline homepage and font loading 2026-10-13 16:37:23 -05:00
README.md Add searchable boring video catalog and caption styles 2026-10-11 18:44:10 -05:00
uv.lock perf: streamline homepage and font loading 2026-10-13 16:37:23 -05:00

Brainrot — Article Cinema

Working local prototype for brainrot.waylonwalker.com. Turn an article into a Kokoro-narrated 9:16 MP4 with precisely timed captions, regular gameplay cuts, and subtle zoom on every shot. Anyone can watch the public infinite-scroll feed. Creators log in to submit articles and render videos; each finished video appears in the feed automatically.

One-command local run

Requires mise and just installed. From the extracted project directory:

just dev

Open http://127.0.0.1:8018. Public feed works without login. Select Create → Log in, developer password dev, to access the creator studio. This local development password works only when BRAINROT_DEV_MODE=1; never expose just dev to the network. The first just dev installs dependencies via mise/uv, including the spaCy English model required by Kokoro. First real narration may download Kokoro model weights; subsequent renders reuse its cache. A pip-managed espeakng-loader supplies the native shared library when possible; if your local Kokoro installation still reports an eSpeak error, install espeak-ng with pacman as a fallback.

If you just want to inspect the UI without installing Kokoro, use just dev-light (real article renders require the tts extra). just check runs the full local gate; just test and just render-smoke are available for focused checks.

mise.toml selects Python 3.14, uv, just and FFmpeg via conda:ffmpeg so just calls mise exec for all needed tools. FFmpeg requires support for libx264, zoompan and libass. If your conda build omits a codec/filter, use a system FFmpeg build with those capabilities and remove the conda tool line. The supported Python range is Python 3.14 only; uv.lock pins the complete runtime and development dependency set.

Getting real Dropper footage

No PAT is packaged in this ZIP. The app automatically looks for Dropper's existing production PAT at:

~/git/dropper/.dropper-auth/dropper-prod.pat

Or set DROPPER_PAT_FILE=... in .env (copy .env.example to .env). The game picker uses Dropper's authenticated GET /api/games index when available, then checks each title's paginated /api/games/{title}/media results and only shows titles with media_kind: video; displayed counts are video counts, so image-only titles do not appear. Older Dropper deployments fall back to grouping video results from GET /api/media/search?q=type:video by metadata_summary.game. Imports use the result's original file_url after checking it stays on Dropper and matches the selected filename. category is the broad value gaming; it does not represent a genre. Legacy Minecraft, Silksong, and skateboarding choices remain available while Dropper metadata is being populated. Videos without game metadata are not guessed into a title. Use manual uploads to fill the gaps.

Usage: On the first article render, Brainrot attempts to import up to three matching clips if a Dropper PAT is available. To curate the footage, choose a game in the studio → Browse Dropper → Import. Set AUTO_DROPPER_IMPORT=0 in .env to turn off automatic imports. Media is cached in .data/footage/{game}/. You may also upload clips or copy owned MP4/WebM files into that directory. Use only recordings/footage you have the rights to reuse. Rendering requires real gameplay footage; without it, the job fails and asks you to import clips or connect Dropper.

Render behavior

  • By default, takes up to ~110 words from consecutive extracted article sections; choose starting section and word budget in the creator form.
  • Synthesizes only selected sections; rest of the article is not queued for TTS.
  • Uses Kokoro result.tokens[*].start_ts/end_ts already implemented in Listen, so no WhisperX or GPU alignment step.
  • Merges 24 kHz mono WAV sections and offsets their word timings by the actual segment durations. Each paragraph boundary adds a brief 0.1 s pause.
  • FFmpeg holds gameplay shots for about 12–18 s. Jump cut style skips a randomized 1–2 s from the middle of each shot, then resumes the same clip with no zoom. Punch style cuts to a 1.5× crop. Neither style uses continuous camera drift. It alternates among available clips and resumes each clip at its next unused frame, so longer gameplay events can continue across later shots without repeating footage. A job fails clearly if its available gameplay is too short to cover the narration without reuse.
  • Burns active-word-only captions into a vertical H.264/AAC MP4. Article title and author stay in video metadata and the public viewer HUD; the renderer removes a repeated article title from the narration opening when possible. Source URL is embedded in MP4 metadata and attached in the public viewer, where it remains clickable.
  • Outputs to .data/videos/{id}.mp4 and {id}.words.json. One queued FFmpeg job at a time.
  • Finished videos are public automatically and appear in the feed. Login is required to submit an article or request a render.

The public feed contains ready, published videos, including RSS imports. The bundled demo-footage.mp4 remains a sample asset; the render smoke check generates time-varying synthetic footage to verify unique source ranges.

Public video lookup API

GET https://brainrot.waylonwalker.com/api/lookup?url={article-url} checks for a ready, public Brainrot video and supports cross-origin browser requests. It ignores fragments, trailing slashes, common tracking parameters, and URL scheme or www differences. If a query string does not match exactly, it only ignores it when the base URL identifies one stored article, so distinct query-selected articles are not confused.

{
  "found": true,
  "match": "query_ignored",
  "video": {
    "id": "…",
    "title": "…",
    "source_url": "https://example.com/article",
    "url": "https://brainrot.waylonwalker.com/api/videos/…/media",
    "media_url": "https://brainrot.waylonwalker.com/api/videos/…/media",
    "poster_url": "https://brainrot.waylonwalker.com/api/videos/…/poster"
  }
}

When no matching public video is ready, the API returns {"found": false, "video": null}. The media URL can be linked directly from an RSS reader or another site.

Useful commands

just dev            # complete localhost app, real Kokoro engine
just dev-light      # UI, feed, extraction only — TTS extra not installed
just test           # unit/API tests
just check          # tests, Ruff lint + format, and strict ty checks
just format         # apply Ruff's safe fixes and formatting
just render-smoke   # real FFmpeg output with synthetic WAV + word timing fixture
just doctor         # dependency info
just clips          # currently imported gameplay videos

Homelab deployment

The app has an Argo-ready Helm chart in deploy/helm and a child Application in deploy/argo-application.yaml. Production keeps the feed and finished videos public; creator endpoints use Hlab Auth with the brainrot:create scope. Traefik strips incoming X-Hlab-* headers, applies ForwardAuth to creator routes, and a NetworkPolicy only allows Traefik to reach the pod.

To prepare the GitOps checkout:

  1. Commit the app changes, authenticate to registry.wayl.one, and run just publish. Record the printed image tag.
  2. Copy deploy/helm to ~/git/homelab-argo/k8s/brainrot/helm-chart, copy deploy/argo-application.yaml to ~/git/homelab-argo/argo-apps/apps/brainrot.yaml, and set the published image tag in the chart values.
  3. Register brainrot.waylonwalker.com and the brainrot:create scope in Hlab Auth.
  4. Commit and push homelab-argo, then verify the Brainrot Argo Application is synced and healthy before checking https://brainrot.waylonwalker.com.

The chart runs one replica because SQLite and the render worker share /data. Its default 100 GiB longhorn-backup PVC holds the database, uploaded footage, renders, and Kokoro model cache. Monitor capacity as videos accumulate; the app currently uses local filesystem storage only. A missing optional brainrot-dropper Secret disables automatic Dropper imports, but creators can upload footage in the studio.

Production deployment still needs backups and a retention plan before the media library grows. Crediting an author and linking to the article do not grant republication rights; Minecraft footage is subject to its usage guidelines.

Background music

Brainrot's original music is dedicated to the public domain under CC0. The studio offers one 8-bit loop, ambient, lo-fi, synthwave, and cinematic styles, with a 10-second preview for each preset. Previous videos can still render with the older 8-bit selections. Regenerate the generated loops with python scripts/generate_music_presets.py and python scripts/generate_generic_music.py.

Known limits: Localhost dev has only one creator identity; no online video hosting/CDN integration, multiuser account separation beyond identity strings, editing subtitles, or automatic rights verification; extraction inherits Listen's known DNS-rebinding caveat; long articles generate one section range per requested video (multi-part orchestration remains future work). Kokoro's word timing is model-predicted and may differ a little from audible boundaries.