Learn a language from the words on screen.

Yakopop turns video, and game dialogue, into subtitles you can study. Every word shows how it is written, how it is read, what it means and how it works in the sentence, and lights up with the part of the translation it matches.

Try the live components All the components yakopop.com

Yakopop is its own project. The Kamikin characters on this site come from the Kamikin game, which lives in the Yakopop repository. Source code is private.

A still made with the overlay's own markup and style sheet. The sentence is one of the sample sentences shipped in packages/shared/src/langs.ts. Live versions are in the demos below.

What Yakopop is for learning

Yakopop is a platform for learning a language from things you already want to watch. The repository describes it as word-synced, colour-coded bilingual subtitles for language learners. A learner watches, reads along, looks up what they do not know, practises, and comes back to review.

  1. Watch with layers available

    Each subtitle word is a column of up to five rows: the reading (hiragana for Japanese, syllables with stress for Spanish), the word in its own script, the romanisation (rōmaji, pinyin, IPA and so on), the meaning in context and the grammar (part of speech and form). Below the words sits a translation in the language you choose, split into chunks that are linked to words. Particles are drawn grey; every other word gets its own colour, and its chunk in the translation uses the same colour. Rows can be shown, hidden, resized and reordered, and profiles remember the choice.

    Source: packages/overlay/src/SubtitleStack.tsx, player/LayersPanel.tsx, player/prefs.ts

  2. Look a word up available

    Resting on a word opens a card with the word, its reading, its meaning in this sentence, the grammar, role markers explained (a topic marker is not translated, it is labelled) and a play button. For Japanese the card also pulls extra dictionary meanings, a JLPT level and a common-word flag from Jisho. While a card is open the video waits.

    Source: packages/overlay/src/WordCard.tsx, apps/server/src/dict/jisho.ts

  3. Practise available prototype

    Available in the web app: a practice quiz on a video, favourites, completion and progress, flashcard decks with spaced repetition, and a learning path per language made of video lessons, full-screen practice lessons with hearts and XP, daily quests and a weekly leaderboard. Speaking practice (record yourself saying the line, each word marked said, close or missed) is built into the player but only appears when the host supplies a speech-to-text service, so it is marked prototype.

    Source: README.md "Supported now", docs/plans/learning-path.md, packages/overlay/src/player/practice.ts

  4. Hear it available

    Click-to-hear voices: Kokoro for many languages, VOICEVOX characters for Japanese, and a designed-voice library. When no neural voice is reachable the player falls back to the browser's own voice. More in Voices.

    Source: packages/overlay/src/player/neuralVoice.ts, apps/server/src/routes/tts.ts

  5. Many languages available

    Videos in Japanese, Mandarin, Korean, Russian, Spanish, Hindi, Nepali, Thai and Tibetan. Translations into 12 languages (English, Spanish, French, German, Portuguese, Italian, Dutch, Polish, Turkish, Indonesian, Vietnamese, Hindi). The interface comes in 12 languages. Without a Claude key only Japanese can be built, with a free local annotator.

    Source: README.md "Languages", packages/shared/src/text.ts (OUTPUT_LANGS)

The layers, per language

LanguageReading rowWord rowRomanisation row
JapaneseHiraganaKanji and kanaRōmaji (Hepburn)
MandarinZhuyinHanziPinyin
KoreanPronounced, in HangulHangulRevised Romanization
RussianStress marksCyrillicLatin transliteration
SpanishSyllables, stress in capitalsSpanishIPA

Source: packages/shared/src/langs.ts (layers) and apps/server/src/pipeline/annotate.ts (LANG_RULES). Hindi, Nepali, Thai and Tibetan have their own rules in the same file.

Every component, and how far along it is

An inventory taken from the repository on 2026-10-25. Each badge repeats the status the sources give for that part. Paths are inside the private yakopop repository.

  • available in the shipped web app or its README "Supported now"
  • prototype built and working in the repo or a lab, not claimed as shipped
  • planned a plan or a staged hook, not working yet
  • unverified not checked against a running build

The subtitle overlay (packages/overlay)

  • SubtitleStack available

    The colour-coded word columns over the linked translation, with the lit word, the half-lit spoken words, speaking-practice marks and an optional bouncing ball that lands on each syllable. Live demos 1 and 2.

    Source: packages/overlay/src/SubtitleStack.tsx, overlay.css

  • WordCard available

    The hover card: word, reading, meaning, grammar, dictionary extras (Jisho, Japanese only), a play button. Kept inside the player; can be drawn in a separate layer when the host scrolls (a chat thread).

    Source: packages/overlay/src/WordCard.tsx

  • SubtitlePlayer available

    The whole stage: stack, progress track with a tick per line, play and pause, previous and next line, replay, speed, full screen, keyboard shortcuts, the translation language menu, layers and look panels. It follows any PlayerEngine, so it plays over a video, a film or a game cut scene. Live demo 1.

    Source: packages/overlay/src/player/SubtitlePlayer.tsx

  • PlayerEngine, videoEngine, useEnginePlayer available

    The small interface a host implements (time, duration, play, pause, seek, setRate, subscribe), a ready-made one for an HTML5 <video>, and the hook that turns the clock into the current line and lit word.

    Source: packages/overlay/src/engine.ts, useEnginePlayer.ts

  • Language and layer switch available

    The translation language menu, the layers panel (show, hide, drag to reorder, size), looks (box, shadow, colours, highlight, ball) and built-in profiles Classic and Learner. In the Talk overlay the same idea is the 文A card. Live demos 1, 2 and 3.

    Source: packages/overlay/src/player/{LayersPanel,LookControls,prefs}.ts(x); apps/world/src/features/meeting/logic/talkView.ts (subsPanel)

  • Speaking practice prototype

    Record the learner, send the recording to an OpenAI-style transcription server the host supplies, match the words said against the line, show each word as said, close or missed. No microphone button appears without a host-supplied transcriber.

    Source: packages/overlay/src/player/{practice,recorder,speech,transcribe}.ts, PracticeCard.tsx

  • Neural voice client available

    Probes the voice server, speaks a word or a line with a neural voice, and falls back to the browser's voice when the server is not a 200. Needs a TTS server behind it.

    Source: packages/overlay/src/player/neuralVoice.ts

The web app (apps/web)

  • Watch page available

    Overlay player over a YouTube lesson, plus transcript, word list, practice quiz, up next and creator info. Not extractable as a single component, so no demo here.

    Source: README.md "Pages" (/watch/lesson/:id)

  • Flashcard decks available

    Word and sentence cards with spaced repetition (due date, interval, ease).

    Source: README.md, docs/plans/curriculum.md

  • Learning path, lessons, quests, leaderboard available

    Per language: units of video lessons, full-screen practice lessons with hearts and XP, daily quests and a weekly leaderboard learners can opt out of.

    Source: docs/plans/learning-path.md

  • Reels and clips available

    Cut a 2 second to 3 minute clip with a word-snapped trimmer, keep it in a library, optionally publish it to a vertical feed of looping lines.

    Source: README.md, docs/plans/clips.md

  • Studio available

    Creators import YouTube videos, playlists or channels and choose languages, caption source, annotator, layers, range, level, style and a glossary. This is where transcripts become lessons (see Transcripts).

    Source: README.md, apps/web studio pages, apps/server/src/routes/studio.ts

  • Dubbed audio prototype

    Swap a video's soundtrack for a dub in the language being learned; dubs may come from a creator, an AI voice or a service. Phase 1 is built.

    Source: docs/plans/dubbed-audio.md

  • Curriculum package planned

    Draft courses (Japanese units 1 to 6, primers for six other scripts) with exercises: choose, match, build, gap, compose, type. Its own doc calls the primers a draft needing a native speaker's read. Whether the public site uses it is unverified.

    Source: packages/curriculum, docs/plans/curriculum.md

Everywhere else

  • Browser extension prototype

    The overlay drawn over streaming sites. Two sites are listed as tested; selectors for the others still need checking. A store listing is listed as "later".

    Source: apps/extension/README.md, docs/plans/extension.md

  • Talk overlay prototype

    Speech bubbles, thought clouds and shouts that follow characters' heads, a typewriter reveal with voice blips, the 文A language and layer card, word choices for the player. Live demo 3 (logic extracted, markup re-implemented).

    Source: apps/world/src/features/meeting/Talk.tsx, logic/talkView.ts, talkLangs/

  • AI chat with characters prototype

    Free conversation with townsfolk in the game, shown with the same subtitle stack inside the chat bubble, signed-in players only.

    Source: apps/world/src/features/npcChat/, apps/server/src/routes/npc.ts

  • Godot HUD: SubtitleView and TalkBubbles prototype

    The same stack in Godot (SubtitleView: reading, word, romanisation, colours, particles grey, English chunks in their word's colour, hover for meaning and grammar) and Solid-on-Godot talk bubbles. Not browser code, so it cannot run on this page. The web stack above is the reference it is held to.

    Source: apps/godot/hud/subtitle_view.gd, apps/godot/kosmos-js/js/hud/TalkBubbles.tsx

  • Film subtitles prototype

    The same player mounted on cut scenes, with a second "typed out letter by letter" style. Built in the film lab, ready to mount in the world game.

    Source: docs/plans/film-subtitles.md, apps/world/src/film/

  • Speech server (TTS) available

    One OpenAI-style endpoint over Kokoro, VOICEVOX and a designed-voice library, returning WAV with mouth shapes. A guarded proxy in the app server exposes it to the browser.

    Source: tools/tts/server.py, apps/server/src/routes/tts.ts

  • Speech-to-text server prototype

    faster-whisper behind POST /v1/audio/transcriptions, used by speaking practice and the film voice tool. In the lesson pipeline the transcribe stage exists but is not used yet.

    Source: tools/stt/server.py, apps/server/src/pipeline/providers.ts

  • Face rigs and lip sync prototype

    Characters' faces are 45 blendable channels (lids, special eyes, brows, mouths, manga marks, gaze) with about 65 named expressions, and the mouth follows the voice's viseme timings.

    Source: apps/world/src/face/README.md, tools/tts/server.py (x-visemes)

  • Character kits: mochi, rubber hose, noodle prototype

    Code-built cute characters. The mochi kit made the Kamikin cast.

    Source: apps/world/src/mochi/README.md, apps/world/src/hose/README.md

Live components, taken from the app

The demos below are Yakopop's own React components, bundled from copies of the source files into one small module that loads when you scroll here. They run with no network and no model: the sentences are the samples shipped in the repository, and a timer stands in for a video. Nothing leaves your browser.

The module is about 316 KB minified (see README.md in this folder for the build). Layer and language choices in demo 1 are kept in your browser's local storage under yakopop.* keys, as in the app.

1. SubtitlePlayer

available

Faithful extraction. Only the clock behind it is ours.

The full player on a sample timeline. Press play; hover or tap a word for its card; open the translation menu, the CC panel (layers) and the gear (speed, look, keys). Space, arrow keys and F work while the player has focus.

Live demo loads when it comes into view.

Props and data shape
<SubtitlePlayer
  lines={Line[]}        // timed lines, see "Transcripts" below
  engine={PlayerEngine} // anything with a clock: <video>, a film, a cut scene
  lang="ja"             // language of the words (layer names, word cards)
  primary="en"          // language of line.en
  title="Sample timeline"
  captureKeys={false}   // keyboard only while the player has focus
/>

interface PlayerEngine {
  time(): number; duration(): number;
  play(): void; pause(): void; seek(t: number): void; setRate(r: number): void;
  subscribe(fn: (e: EngineEvent) => void): () => void;
}

Source: packages/overlay/src/player/SubtitlePlayer.tsx, engine.ts, useEnginePlayer.ts. Sample data: packages/shared/src/langs.ts. One change: the player's accent colour is set to off-white so its bar matches this site's monochrome buttons.

2. SubtitleStack, word card and layer switches

available

Faithful extraction. The checkboxes call the same profileStyle the app uses.

The stack on its own, driven by the same engine hook. Press play to follow the sync, or tap a word to jump to it. Rest the pointer on a word (or focus it with Tab) for the word card. Switch the reading, romanisation, meaning and grammar rows, the colours and the translation language.

Live demo loads when it comes into view.

Props and data shape
<SubtitleStack
  line={Line}            // one subtitle line
  out="es"               // viewer's translation language
  primary="en"           // language of line.en
  mark={{ active: 2, spokenBefore: 2 }}   // lit word / half-lit words
  lang="ja"              // turns on the hover card
  className="hide-gl hide-gr"             // from profileStyle(profile)
  style={{ "--s-og": 30, "--o-og": 0 }}   // row sizes and order
  clock={() => mediaTime}                 // optional, for the ball
/>

Source: packages/overlay/src/SubtitleStack.tsx, WordCard.tsx, player/prefs.ts (profileStyle). The dictionary part of the card is switched off here (no network); the card's Jisho link is a plain link.

3. Talk bubbles with word choices and the 文A card

prototype

Logic extracted, markup re-implemented. The React component Talk.tsx is tied to the game engine (camera, entities), so only its pure logic file talkView.ts, the dialogue and the language tables run here. The bubbles' HTML and CSS are ours.

A conversation with the game's fox. Open 文A to pick the language (Japanese, Mandarin, Korean, Russian, Spanish, Hindi, Nepali, Thai, Tibetan or English) and switch the reading, romanisation and English layers. Tap a word to hear it with your browser's voice, if it has one. Choose what to say; thoughts are dashed.

Live demo loads when it comes into view.

Props and data shape
said(english, shown, lang, prefs, choice?) → {
  plain: { typed, ghost } | null,        // English: the typewriter text
  words: [{ rd, og, typed, ghost, ro, full, hear, title }],
  spaced: boolean, bcp: "ja-JP", en: string | null,
  enGhosted: boolean, hear: string | null, length: number
}
prefs = { lang: "ja", reading: true, romanization: true, english: true, readAloud: false }
// a language file maps an English line to its words: "word|hiragana|romaji"
"Hi! I'm here for the Sakura Trial.": ["こんにちは!||konnichiwa", "さくら||sakura", ...]

Source: apps/world/src/features/meeting/logic/talkView.ts (said, subsPanel, talkPrefs, typeStepMs, lingerMs), dialogue.ts, talkLangs/*.ts. Re-implementation of the markup in Talk.tsx and talk.css; the fox's dialogue is the game's own text.

4. Transcript to translation, to a subtitle file

prototype

Sample data. Reading the cues uses the repository's real subtitle parser; the annotation and translation are looked up from the sample sentences, not computed. No model is called.

Pick a sample transcript or paste your own: a JSON list of cues, WebVTT or SRT. Cues that match a sample sentence get their word layers and translations in English, Spanish or French (Japanese, Korean, Mandarin) or English (Spanish). Anything else is reported as missing: that is the step where the real pipeline would call an annotator. Then download the translation as .srt or .vtt, made in your browser.

Live demo loads when it comes into view.

Source: packages/shared/src/subtitles.ts (parseSubtitles), text.ts (translationOf, outputsFor), langs.ts (samples and their translations). File writing is ours.

Using it anywhere

The subtitle player does not know about video. It reads a list of lines and a clock, so anything that has a clock can carry it. These are the integration paths the sources support, with how far each one goes.

WhereHowStatusSource
The Yakopop web appA YouTube lesson with the player, transcript, quiz and decks.availableREADME.md
Over any HTML5 videovideoEngine(video) wraps a <video> element in the engine interface; the player draws over it.available in the repooverlay/engine.ts
Over a streaming siteBrowser extension: a page hook reads the site's subtitle tracks, windows of about five minutes are annotated by the server and drawn in a shadow root over the player.prototypeapps/extension
Over a film, a cut scene, a gameImplement PlayerEngine over the film's or the game's clock (this page does it with a timer). Game dialogue goes through the overlay by design.prototypefilm-subtitles.md, ADR 0003
Inside a chat or a bubbleThe stack and its cards can be drawn in a layer of their own, for a host whose subtitles sit in a scrolling box.prototypeoverlay/env.tsx (portal)
GodotSubtitleView builds the stack from the same line data.prototypeapps/godot/hud
Game consolesThe overlay is DOM today; the decision record says consoles need a native subtitle renderer.plannedADR 0003
Your own annotation servicePoint the worker at a service that speaks the annotate contract (see Transcripts).availableproviders.ts
Your own voiceAny server speaking POST /v1/audio/speech; see Voices.availabletools/tts
Any web page, as an embeddable widget or published packageNo iframe widget or npm release is documented. @yakopop/overlay is a private workspace package with a React 18 peer dependency.planned unverifiedoverlay/package.json

A host in a few lines

import { SubtitlePlayer, videoEngine } from "@yakopop/overlay";
import "@yakopop/overlay/overlay.css";
import "@yakopop/overlay/player.css";

const engine = videoEngine(document.querySelector("video")!);
// lines: Line[] from GET /api/lessons/:id, or your own annotated lines
<SubtitlePlayer lines={lines} engine={engine} lang="ja" primary="en" />

Source: packages/overlay/package.json (exports), src/index.ts, src/player/SubtitlePlayer.tsx. The package is inside the repository only. The hook useOverlayEnv lets a host supply its own translator for the UI strings, a dictionary lookup and the box word cards stay inside.

Kamikin chat on this site

The Kamikin page on this site has a scripted Japanese practice chat built from the ideas of the Talk overlay and the subtitle stack. It does not use Yakopop's code: it is a separate vanilla implementation with hand-written lines, no AI model, and an optional local voice server. Open Kamikin.

How transcripts and translations are made

The pipeline runs on the Yakopop server as queued jobs, not in the browser. Each stage is swappable: a provider registry lets a stage move to another service without touching the build. This is the real flow in apps/server/src/pipeline/build.ts.

  1. 1. Get the words available planned

    Available: the creator's or auto-generated YouTube captions, fetched with yt-dlp without downloading the video, or a .vtt, .srt or TTML file the creator uploads. The browser extension instead reads the text tracks the streaming page already loads (DASH and HLS manifests, WebVTT and TTML responses, or video.textTracks).

    Planned: speech-to-text for a video with no captions. The hook exists (transcribe stage, an OpenAI-compatible POST …/audio/transcriptions with response_format=verbose_json, reference server tools/stt/server.py running faster-whisper) but the pipeline does not use it yet, and video file upload is listed under "not yet".

    Source: apps/server/src/pipeline/captions.ts, providers.ts, docs/plans/extension.md, README.md

  2. 2. Cues available

    Whatever the source, the result is a list of timed text pieces. The builder groups caption text into chunks of about 200 characters with a per-character time map, so annotated sentences can be timed afterwards. Sound notes in SDH captions are dropped. The extension cuts a track into windows of about five minutes, each cached under a hash of language, target, annotator and text, so an episode is annotated once.

    // packages/shared/src/subtitles.ts
    { "start": 0.8, "end": 5.7, "text": "今日は天気がいいですね" }

    Source: packages/shared/src/subtitles.ts (Piece, parseSubtitles, splitWindows), pipeline/captions.ts

  3. 3. Annotate: words, readings, meanings, grammar available

    An annotator turns caption text into sentence-sized lines. Each line is a list of tokens [surface, reading, romanisation, gloss, grammar] and a translation made of chunks that point at token numbers. Three annotators exist:

    Claude (a language model with structured JSON output and per-language rules for the reading and romanisation systems; best quality; may be limited to admins on a server). A free local annotator for Japanese: kuromoji for splitting, readings and parts of speech, wanakana for kana and rōmaji, Jisho's public API for meanings, with rougher results and a label saying so. An external annotation service that speaks Yakopop's contract: POST {url} with { lang, target, pieces, options }, answering { lines: [{ start, end, t, en }] }.

    The rules the model follows are visible in the source: the tokens must add up to the caption text with nothing invented or dropped, a gloss is one to three words, particles with no equivalent get a role tag (#TOPIC, #SUBJ, #OBJ) instead of a translation, and every translated chunk carries the index of the source word it translates, or -1.

    Source: apps/server/src/pipeline/annotate.ts (systemPrompt, LANG_RULES), local-ja.ts, providers.ts

  4. 4. Translate available

    The annotator writes the translation into the creator's chosen target language as part of annotation, with every chunk linked to a word. Extra output languages travel on the same line as line.tr (a translation and one gloss per token, per language). Where an annotator does not translate on its own (the free local one), a sentence translator is used: a LibreTranslate-compatible service you configure, or MyMemory's free API (about 5,000 characters a day). A track in a dub's language starts from the captions in that language, or from the original captions machine-translated piece by piece, timings kept.

    Source: pipeline/providers.ts (translators), build.ts (translatePieces), packages/shared/src/text.ts (translationOf)

  5. 5. Time the words available planned

    Today: timing is per line, taken from the caption cues (timing: "line"). The words inside a line are spread across it by weight, the length of their romanisation plus a constant, on the client (wordAt, wordTime). That is what lights the words in the demos above. Planned: per-word forced alignment. The speech-to-text server can already return word times (timestamp_granularities[]=word), and the film voice tool uses them.

    Source: pipeline/build.ts ("word timing is interpolated on the client for now"), packages/shared/src/text.ts, tools/stt/server.py

  6. 6. Save and play available

    The track is saved as a new version of that language's lesson, the player fetches it as JSON, and the extension asks the server for windows. A creator can edit lines afterwards in the studio, with revisions and restore.

    GET  /api/lessons/:id
    POST /api/overlay/windows        { lang, target, site, pieces }  → key
    GET  /api/overlay/windows/:key   → status or lines
    GET  /api/translation/providers  → which stages are configured
    GET  /api/dict/:lang/:word       → dictionary entry for a word card

    Source: apps/server/src/routes/{lessons,overlay,system,studio}.ts. The window cache returns lines only for a key the client could compute, so it never hands subtitles to someone who does not hold them.

The data shapes

A line, as the repository defines it (Line, Token, Segment in packages/shared/src/types.ts). This is the first Japanese sample sentence with the times a lesson line would carry. start and end are absent on the shared demo sentences.

{
  "start": 0.8, "end": 5.7,
  "t": [
    ["今日", "きょう", "kyō", "today", "noun · time"],
    ["は", "は", "wa", "#TOPIC", "particle"],
    ["天気", "てんき", "tenki", "weather", "noun"],
    ["が", "が", "ga", "#SUBJ", "particle"],
    ["いい", "いい", "ii", "good", "i-adjective"],
    ["ですね", "ですね", "desu ne", "isn't it", "copula + particle"]
  ],
  "en": ["The ", ["weather", 2], " is ", ["nice", 4], " ", ["today", 0], ", ", ["isn't it", 5], "?"],
  "tr": {
    "es": {
      "line": [["Hoy", 0], " hace ", ["buen", 4], " ", ["tiempo", 2], ", ", ["¿verdad?", 5]],
      "gloss": ["hoy", "#TOPIC", "tiempo", "#SUBJ", "bueno", "¿verdad?"]
    }
  }
}

A lesson wraps lines with: id, lang, videoLang, target, title, source (YouTube id or upload), captions (manual, auto, uploaded), annotatedBy (claude, hand, local, external), timing (line or word), audio dubs and the sibling subtitles tracks.

What the speech-to-text server answers, when asked for word times:

{ "task": "transcribe", "language": "ja", "duration": 0, "text": "…",
  "segments": [{ "id": 0, "start": 0, "end": 0, "text": "…",
                 "words": [{ "word": "…", "start": 0, "end": 0, "probability": 0 }] }],
  "words": [ … ] }

Source: tools/stt/server.py. Numbers are placeholders; the keys are the server's.

Try it yourself

The same flow from the command line, on a machine with the repository running. Only fetch captions for videos you have the rights to use.

npm run build-lesson -w @yakopop/server -- <video url> --lang ja --to en --max-minutes 3
# the lesson is queued as a job; the worker fetches captions, annotates, translates and saves
npm run prewarm-overlay -w @yakopop/server -- path/to/file.srt --lang ja --to en --site demo

Source: README.md "Video lessons (beta)", apps/extension/README.md. Demo 4 above shows the shape of the result with sample data.

Voices and mouth shapes

Voices come from one text-to-speech server that speaks the OpenAI speech API, so a client does not care which engine says the line. The voice name picks the engine by its prefix. In the app, the browser never talks to that server directly: a thin proxy in the app server checks the request, limits it per user (or per address for guests) and passes it on.

  • Kokoro available

    Fast, soft voices in many languages, including Japanese. Voices can be blended to make new ones. Apache 2.0 model.

    Voice prefix kokoro:

  • VOICEVOX available

    Anime-style Japanese character voices. Each voice has its own terms of use and asks for a credit.

    Voice prefix voicevox:

  • Designed-voice library prototype

    Base voices designed from text descriptions with Qwen3-TTS and cloned into ten languages, with moods. It needs its own speech server (Apple silicon, or a PyTorch backend elsewhere), so it runs in development.

    Voice prefix qwen:, tools/voices

POST /v1/audio/speech
{ "input": "こんにちは", "voice": "kokoro:jf_alpha", "speed": 1.0, "reading": "こんにちは" }

200 audio/wav   24 kHz, mono
x-visemes: [[viseme, start, end], ...]   seconds into the audio; visemes aa ee ih oh ou fv mbp sil

The reading field gives Kokoro the kana when the Japanese pronunciation engine is not installed. The proxy accepts one short text per request (up to 400 characters), speed from 0.5 to 2, and answers 404 when no neural voice exists, so clients fall back to the browser's voice. Mouth shapes drive the characters' faces; the library's voices send speech start and end times instead.

Source: tools/tts/server.py, apps/server/src/routes/tts.ts, packages/overlay/src/player/neuralVoice.ts, docs/plans/anime-voices.md. Credits as the repository states them: VOICEVOX (春日部つむぎ, 白上虎太郎, ずんだもん), Kokoro, and Whisper via faster-whisper.

Games, characters and where Kamikin fits

Yakopop's decision record says it is the learning layer inside every game: games show dialogue through the overlay and words met in play are meant to go to the player's deck. Kamikin, the cute mochi universe for young children, is the first game built that way, and it teaches Japanese words.

  • Kamikin prototype

    Mochi friends on a round meadow wake things by saying their words, first in Japanese and then in the player's language. Two implementations exist in the repositories, a Godot slice and a port to the Kosmos engine. A public play site is not documented, so availability is unverified.

    Source: docs/kamikin-context.md, games/kamikin/README.md

  • Season 1 and the curriculum planned

    A design for lessons Monday to Friday (Hello Meadow, Pond Friends, Count the Stones, Snack Share, Review) with at most six new items each. Design and draft content, not a shipped course.

    Source: docs/plans/kamikin-season1.md, packages/curriculum

  • Words to the deck planned

    The design sends words met in a game to the learner's flashcard deck. The notes say nothing in the game calls the deck yet.

    Source: docs/adr/0003-yakopop-learning-layer.md

  • Other games on the same platform unverified

    The repository also holds the Yakopop world game and Kosmica. They use the same overlay but are not described here beyond that.

    Source: docs/ROADMAP.md

Yakopop

Provenance

Yakopop is the language learning platform; its repository is private (Modern-Telepathy/yakopop) and its README says it is live at yakopop.com. Kamikin is the game that lives in that repository. The Kamikin characters shown on the Kamikin page of this site are the game's mochi cast, converted for this site. This page is a Kamiji study of Yakopop's public description and of its code, read-only.

What is not claimed

Yakopop's README lists these as not yet built: video file uploads, speech-to-text for videos without captions, connecting a YouTube account, follows, playlists or series, reports from learners, analytics and billing (plans and limits work, but an admin sets plans until a payment provider is connected). The pricing page in the app is a mock-up, and this page states no prices.

Left out of this page on purpose: server addresses, deployment files, keys and settings, user accounts and data, and the way the voice server is reached in production. The TTS proxy is described only by what it accepts and returns.

Not checked against running builds: the status badges repeat what the repository's documents say. Nothing here was run against the live site except the extracted components on this page, which run on sample data.