Changelog¶
All notable changes to this project will be documented in this file
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning
starting from v3.0.0
Pre-v3.0.0
v1.0.0–v2.6.0used semver-like tags but without a formal policy or changelog- Their history is preserved in
GitHub Releases
v3.0.0 Is v0.1.0
-
Since
Mirumojiunderwent a complete refactoring / rewriting and has only started followingSemantic Versioninginv3.0.0, it should be treated as a initial release -
This means that the following
v3.xversions MIGHT STILL CONTAIN BREAKING CHANGES -
These changes will be clearly documented in this changelog
3.7.2 - 2026-07-21¶
This release fixes the in-process Modal log reading introduced in 3.7.1,
which could hang instead of returning entries, and stops the packaged GUI
from spawning Windows' fake Store python when following logs. It has no
breaking changes
Fixed¶
-
Launcher→ Reading theModal-hosted app's logs in-process could hang with anRPC request made outside of task contextwarning. Looking the app up creates modal's client on theSDK's own event loop, and the fetch then ran on a second loop, where the request lost its cancellation context and never completed. The fetch now runs on modal's own loop, the same way theSDK'sCLIhelpers run -
Launcher→ Following logs from the packagedGUIprinted aMicrosoft Storeinstall prompt instead of streaming. OnWindowsthePATHcarries a fakepython.exe(the app execution alias), which the bundle picked up to spawn themodalCLIwith. The alias is no longer treated as an interpreter anywhere, and the packagedGUInow always follows logs in-process instead of spawning whateverPATHoffers
3.7.1 - 2026-07-21¶
This release makes the packaged desktop GUI read the Modal-hosted app's
logs without needing a Python interpreter on the machine, and makes
deletions feel instant on a hosted deployment by removing rows optimistically
instead of waiting for the server round trip. It has no breaking changes
Fixed¶
-
Launcher→ Reading theModal-hosted app's logs from the packaged desktopGUIfailed with aNo Python Interpretermessage because the logs were the oneModalaction that still shelled out to themodalCLI. Logs are now read through theSDKin-process like the stop and volume actions, with theCLIkept as a fallback, and a followed stream polls in-process when noCLIcan be spawned -
Frontend→ Deleting a file, transcript, or clip only updated the interface after the delete and a follow-up list refetch had both completed, which on a hosted deployment left the row visible for noticeable time after the click. Rows now leave the list immediately and are restored if the delete turns out to have failed
3.7.0 - 2026-07-20¶
This release stops a local video being uploaded once per player action,
makes the interface report what actually happened instead of assuming success,
and fixes two GUI Modal actions that opened a second window and hung forever.
It also adds upload cancellation, double-tap seeking, a Modal log source in
the GUI, and quiets a large amount of misleading ERROR noise in the host logs.
It has no breaking changes
Added¶
-
Frontend→ An in-flight upload can be cancelled from the task tray, which stops the transfer and drops the row rather than leaving it to finish -
Frontend→ Double-tapping the left or right side of the player skips 5 seconds, matching the arrow keys -
Launcher→ TheGUILogs panel reads theModal-hosted app's logs as well as the localDocker Composestack, chosen with a new Source control, with the same tail and follow controls
Fixed¶
-
Frontend→ Running two player actions on the same device video uploaded the whole file twice. ClickingGenerate SRTandTo MP4on one video sent it in full on each action and left two profile files sharing a name. An action started while an upload is still running now joins that upload instead of beginning its own -
Frontend→ A player action on a file that had since been deleted reported success while the server rejected it, and no task ever appeared. Actions now wait for the result and report the real outcome, naming a deleted file rather than failing silently -
Frontend→ A profile video deleted while it was loaded showed theConvert To Playprompt, which could never succeed. A deleted file is now told apart from a container the browser cannot decode, and clears the player -
Frontend→ Deleting a file left the jobs it removed on the tasks dashboard, where deleting them failed with a not-found error that could not be cleared. Those jobs are dropped as the file is deleted, and any task that is already gone server-side clears instead of erroring. Transcripts and clips are refreshed the same way -
Frontend→ OniOSa recording's audio slider never moved and its length showed as0:00, because a browser recording carries no duration until it has been read in full. The duration is now picked up when it becomes known -
Frontend→ OniOSthe file dialog stopped responding after a few uploads. Picking the same file twice raised no event, and each preview held its audio in memory for the rest of the session, so repeated picks exhausted the browser. File inputs now reset between picks and previews are released once nothing shows them -
Launcher→DownandDownload Datain theGUI'sModal Hostpanel opened a second application window and hung indefinitely. The packaged app embedsPython, so themodalCLI could not be run the way those two actions ran it.Download Datanow streams the volume directly andDownstops the app in-process, so neither spawns anything -
Launcher→ TheModal Hostpanel's mode pills kept whatever was true when the panel first opened, so a change made inSettingswas not reflected on returning to it. They are re-read on every visit, as theDashboardalready did -
CLI→mirumoji modal logs --tailaccepted counts themodalCLI rejects, surfacing its raw usage text. It is bounded to the accepted range, also takes-t, and states that it does not apply with--follow -
Server→ Video conversions, saved clips andAnkiexports were mirrored to theModalvolume repeatedly while they were still being written, re-copying the same output several times over. Each is now written aside and moved into place when finished, so it is copied once -
Server→ Ordinary outcomes were logged as failures. A stale reference from the interface produced a databaseERRORand a full traceback on every attempt, burying real problems. Only genuine failures are logged that way now -
Server→ Deleting a task that was already gone failed instead of succeeding, which left the interface unable to clear it. Deleting a task that no longer exists now succeeds -
Server→ A cancelled upload was recorded as a server failure rather than as the deliberate action it is
3.6.0 - 2026-07-18¶
This release hardens the Modal-hosted deploy and adds new host compute modes.
It makes host data durable against a mid-write preemption, adds an offload-less
GPU host and a non-preemptible CPU host, adds a modal logs command, and reworks
the image-version pin into a single deploy-time option applied across every image
command. It also fixes a Windows crash in the modal CLI, several volume-sync
inefficiencies, a stop that could not delete the volume, and a host-mode toggle
that silently did nothing
Breaking Changes¶
-
The image-version pin is renamed. The
MIRUMOJI_VERSIONconfig key becomesMIRUMOJI_IMAGE_VERSIONand the--versioncommand flag becomes--image-version, with no compatibility alias, so update any script or config that pinned an image version -
The global
mirumoji --version(which prints the installed package version) is unchanged
Added¶
-
Launcher→ An offload-less GPU host. SettingMIRUMOJI_HOST_ON_GPU=1(or passing--host-on-gpu) runs the whole host on a GPU with thelocalwhisper backend in-process, on theMIRUMOJI_MODAL_GPUtype, so there is a single always-warm app and no on-demand offload worker -
Launcher→ A non-preemptible CPU host.MIRUMOJI_HOST_NONPREEMPTIBLE=1(or--nonpreemptible) runs the host on guaranteed capacity at a 3x price, so a spot reclaim never restarts it mid-job. It cannot be combined with a GPU host, whichModaldoes not allow -
Launcher→ Amirumoji modal logscommand that fetches the hosted app's recent logs (--tail) or live-follows them (--follow, stopped with Ctrl+C) -
Launcher→--image-versionis honored by every image command (up,pull,render,build,modal deploy), andbuildnow checks out the matchingv<version>source tag
Changed¶
Launcher→ The image-version pin is a single deploy-time option resolved in one place (flag, then config, then shell, then the installed version) and is never injected into a container. See the breaking note above for theMIRUMOJI_VERSION/--versionrename
Fixed¶
-
Launcher→ AFix-SRT(or any media write) could survive a mid-writeModalpreemption as a database row whose media file was missing. Media writes are now atomic (written to a temporary sibling and renamed into place) and the background volume sync is ordered, so the volume never holds a row referencing a file that has not been mirrored yet -
Launcher→ ThemodalCLI could crash partway through onWindowswhen its output held a character the legacycp1252console could not encode (a box border or a Japanese filename), sodownload-dataand log fetching could fail. Its subprocesses now encode their output asutf-8 -
Launcher→mirumoji modal down --volumecould not delete the data volume once the app had stopped or failed to stop. A stop failure is now a warning, so the volume is still deleted -
Launcher→ The host volume sync thrashed theFUSElayer, re-copying a transcription's growing scratch audio and the streamed-back converted video many times over. Transient scratch is no longer mirrored, and the offload worker's result is written atomically, so each file is copied once
3.5.1 - 2026-07-16¶
This release fixes several issues with the Modal-hosted deploy. It moves media serving and the
database off the volume's slow network layer so hosted video plays smoothly,
makes shutdown and spot preemption exit cleanly, completes the PWA install
behind the host login on iOS, and stops the installed app from re-prompting for
the password. It also fixes a previously uncaught clip-recording hang on iOS.
It has no breaking changes
Fixed¶
-
Launcher→ Besides an overall poor application performance when hosting onModal, video playback stalled and clip recording failed. TheModalhost served media and ran the database directly off the persistent volume'sFUSElayer, whose per-request random reads take seconds, so every seek re-buffered and the browser recorder (which captures live playback) had no continuous stream to record. The host now reads and writes user data on the container's local disk and mirrors changes to the volume in the background, keeping media and database I/O off the slow layer whileModalstill persists the data -
Launcher→ TheModalhost could overrunModal's shutdown grace and be force-killed (loggingRunner has been shutting down for too long) when a stop or a spot preemption stranded an in-flight volume read on a background thread. A watchdog (a daemon thread started at shutdown that terminates the process if it doesn't exit in less than 10 seconds) now exits the container cleanly within the grace window, so a stop or preemption releases promptly -
Launcher→ TheModalhost wrote its request log to the persistent volume on every request, growing it unbounded and adding a volume write to the hot path. It now logs to standard output, whichModalcaptures, so nothing is written to the volume.Modalpersists logs natively through theStopped Appsinterface, so writing to a log file would be redundant and decrease performance -
Frontend→ The installedPWAicon did not render oniOSand the app was not installable behind the host login.iOSfetches the manifest, its icons, and theapple-touch-iconas install subresources without the login, so behindHTTP Basic Auththey returned401. The host now serves exactly those public install files without auth, while the shell, the hashed assets, and the API stay gated -
Frontend→ An installediOSPWAre-prompted for the host password on every reopen, sinceiOSdrops theBasic Authcredential cache when the app is suspended. A passed login now sets a persistent,HttpOnlycookie that the host accepts in place of the credentials, so a reopened app authenticates silently (rotating the password invalidates it) -
Frontend→ Saving a clip oniOScould hang onRecordingfrom a fresh player. The recorder's audio pipeline needs itsAudioContextresumed inside a user gesture, but fetching the word explanation first spent it, leaving the audio track dead. The save now resumes the context on the tap, and the recorder can no longer hang indefinitely -
Server→GET /api/jobsreturned400for a poll that arrived without anX-Profile-IDheader (a service-worker replay the app cannot attach the header to). It now returns an empty list, so the errors stop
3.5.0 - 2026-07-15¶
This release makes the launcher run the container images that match the
installed version instead of always pulling latest, so an install runs the
images built for it and any published version can be pinned. It also makes the
live demo installable as a PWA, adds an in-app cache reset, and fixes a set of
mobile, caching, and Modal deploy issues. It has no breaking changes
Added¶
-
Launcher→ From this release on, the launcher pulls and composes the<version>-tagged images matching the installed package rather thanlatest, so apip install mirumoji==X(forX >= 3.5.0) runs the images built forXand the launcher never drifts onto an incompatiblelatest. AMIRUMOJI_VERSIONconfig variable and a--versionflag onup/pull/render/modal deploypin any published version, checked against Docker Hub first so a version with no published images fails early with a clear message (older, pre-3.5.0 installs still pulllatest, since the version-pinning code only ships from here on) -
Launcher→mirumoji --versionprints the installed version -
Frontend→ The live demo is now an installable PWA, so a visitor can add it to their home screen and see how the app behaves once installed. The app also gained aReset App Dataaction (Dashboard → Advanced) that unregisters the service worker and clears its caches, to recover from a stale cached build
Fixed¶
-
Launcher→MODAL_FORCE_BUILDhad no effect onmirumoji modal deploy. The Modal SDK reads it from the local process environment when it builds the derived host image, but the deploy exported only the Modal tokens, so setting the variable never forced a rebuild and the host stayed on a stale cached image. It is now exported for the deploy, somirumoji config set MODAL_FORCE_BUILD 1rebuilds the host image -
Frontend→ Toasts were rendered under the notch on notched phones. They now inset off the safe area and clear it -
Frontend→ The player's volume slider did nothing on iOS, where the media volume is read-only and owned by the hardware buttons, so it looked broken. It is now hidden on iOS, leaving the mute toggle, which still works -
Frontend→ The PWA could not be installed behind the Modal host's HTTP Basic Auth. The manifest link was fetched without credentials, so it and its icons returned 401 and the browser saw no installable manifest, leaving no app icon or install prompt. The manifest is now requested with credentials -
Frontend→ A new build could be hidden behind a stale cached shell. Neither Nginx nor the Modal host setCache-Control, soindex.html, the service worker, and the manifest could be served stale from the HTTP cache, pinning old hashed assets. They are now servedno-cache(with hashed assets marked immutable), so a new version is picked up on the next load
3.4.0 - 2026-07-14¶
This release adds a one-command private full-host deploy to Modal, reworks the Modal GPU offload
into a warm, reusable worker that skips the per-job cold start, warms the tokenizer and dictionary at
startup, and takes the frontend edge-to-edge on notched phones. As a v3.x release (see the
v0.1.0 note above) it includes two breaking changes, listed first
Breaking Changes¶
-
REST API→ The Kanji dictionary endpoints now carry the Kanji as a query parameter instead of a path segment (/dict/kanji/{literal}→/dict/kanji?literal=..., and likewise for/strokes,/audio, and/audio/clip). A Kanji literal is always non-ASCII, and a Modal-hosted deploy rejects any request whose URL path holds non-ASCII bytes, so the glyph is kept out of the path. Clients of these endpoints need to adopt the query-parameter form -
Launcher→ The local data folder (managed config, logs, cached builds, and any non-Docker data) is no longer keyed by the app version. Earlier versions stored it under a per-version subfolder, so every upgrade silently started from an empty folder and orphaned the previous install's data, despite the compose comment promising data survived version bumps. From3.4.0the folder is unversioned, so future upgrades keep your data, but the one-time move to3.4.0does not read a pre-3.4.0versioned folder. Re-enter your keys, or import the old file withmirumoji config import <path>. The old data is left in place, not deleted, and Docker data volumes are unaffected
Added¶
-
Launcher→mirumoji modal deployhosts theentireapp (the FastAPI server and the built React frontend) privately on your ownModalaccount, with no local Docker. It runs as a single always-warm CPU container gated by a browser login (HTTP Basic Auth), keeps its database and media in a persistent Modal volume, and offloads GPU transcription to the same worker the localmodalbackend uses.modal status,modal down, andmodal download-datainspect, tear down, and back it up. The deploy image is composed from the published backend and frontend images, so no new artifact ships. See the newModal Host Setupguide -
Launcher→mirumoji config showgained--raw(reveal masked secret values, for reading a generated web password) and--json(export the config) -
Frontend→ A backend-freelive demonow runs at the docs site root. A build-time--mode demoswaps the network layer for committed fixtures captured from a real session, so a pre-loaded sample episode (the player, tokenized subtitles, and word breakdowns) and a curated dictionary slice work with no server. Off-rails input (upload, free search, profile switch) is gated, and dictionary links outside the captured set are disabled
Changed¶
-
Server→ The Modal GPU offload now runs a single deployed, warm worker that loads the multi-GB Whisper model once per container and stays warm for the scaledown window, instead of spinning up an ephemeral app per job that reloaded the model every time. Back-to-back jobs skip the cold start, while the worker still scales to zero when idle, so an idle GPU never costs you. The server auto-deploys it on first use (tracked by ownership tags so it is never duplicated and rolls forward on upgrade) and stops it on shutdown -
Server→ The Japanese tokenizer (fugashi/UniDic) and the dictionary (kotobase) are warmed during startup, so the first tokenization and lookup are fast instead of paying a one-time cold load. Each warm-up runs in a thread and only warns on failure, so a broken language dependency degrades only its own endpoints while transcription and file management keep working -
Frontend→ The app goes edge-to-edge on notched phones (filling the letterbox bars viaviewport-fit=cover) while respecting safe-area insets across both headers, the drawer, the hover rail, the floating button, the player toolbar, and the task tray. Every inset resolves to zero on a non-notched display, so desktop and portrait layouts are unchanged
Fixed¶
-
Server→ The/health/systemprobe runs off the event loop. It shells out tonvidia-smi(up to a 5s timeout), which previously blocked every other request while it waited -
Frontend→ The player adapts to a phone held in landscape, reusing the desktop side-by-side subtitle rail instead of stacking the panel below the video and splitting the short height in half. The subtitle-style popover is also bounded to the viewport with an internal scroll so it no longer runs off a short landscape screen -
Server+Frontend→ Non-ASCII characters are kept out of URL paths and profile ids. The frontend gates profile names to ASCII and the server rejects a non-ASCIIX-Profile-IDheader with a400, so a profile named with Japanese or other Unicode text no longer produces invalid URLs or ids (which also lets the whole app run on a Modal-hosted deploy) -
Launcher→mirumoji resetprunes themirumojifolder in everyplatformdirsroot (the cache, config, state, and log locations), so a reset cleans up uniformly on Linux, macOS, and Windows and leaves nothing orphaned
3.3.0 - 2026-07-08¶
This release organizes profile files, lets a word breakdown pull in the surrounding subtitle
lines, adds a one-command local-data reset, and hardens the server's logging and shutdown.
As a v3.x release (see the v0.1.0 note above) it includes a breaking database change
Breaking Changes¶
Database→ Profile files now record their lineage (the source video from which a generated subtitle or converted MP4 came) through two new columns, added without a migration. An existing install must start from a fresh database (runmirumoji resetfirst, ormirumoji down -vfor a Docker deployment, before updating)
Added¶
-
Frontend→ Profile files are organized by video lineage. Each source video nests its derived files (generated / fixed subtitles, a converted MP4) beneath it with readable names instead of opaque ids, grouped by folder. The player'sLoad Medialist is also updated to group related files -
Server+Frontend→ A word breakdown can include the surrounding subtitle lines. A prompt template opts in with a{context}placeholder and{#context}…{/context}conditional blocks. The LLM template editor shows a live preview of the assembled prompt, and a control in the player toolbar sets how many lines on each side (N lines before the current sentence + N lines after it) are sent -
Launcher→ Amirumoji resetcommand (and aDelete Databutton in the GUI Settings) deletes Mirumoji's local data folder, which is otherwise tucked away in a hidden system directory.--keep-configand--keep-logspreserve those. Docker data volumes are left todown --volumes -
Launcher→ The LLM batch concurrency and a Modal container keep-warm window are configurable through new environment variables and Settings fields
Changed¶
-
Server→ Logging was reworked so the server console stays clean, every log line carries a per-request id, and upload progress shows a themed bar -
Server→ The previously untyped JSON endpoints (the profile deletes and the provider / model / health routes) now return typed models, so they are documented in the API schema -
Frontend→ Info tooltips are a single shared component that stays on-screen on mobile and can hold richer content
Fixed¶
-
Frontend→ Deleting a file that is open in the player now clears it, so a deleted video no longer looks like an unplayable format and a deleted subtitle no longer lingers -
Server + Frontend→ Deleting several files at once is safe (previously, the database ran into a race-condition where deleting multiple files at once would try to wipe already-deleted jobs shared by them, stopping the deletion). The frontend now clears completed jobs related to already-deleted files from the task tray -
Server→ On shutdown, the server releases its log file and stops any runningFFMPEGprocess, so nothing is left holding a file open and the local data folder can be removed (notably on Windows) -
Frontend→ The local CA can be downloaded overHTTPS. The service worker was catching the request and serving the app (which rendered its 404 page), so the certificate could previously only be fetched overHTTP
3.2.0 - 2026-07-04¶
This release turns the dictionary into a full study hub (kanji stroke-order animations,
radical search, English lookup, pronunciation audio) and makes Mirumoji installable as
an app on every device via a one-time certificate install. As a v3.x release (see the
v0.1.0 note above) it includes a breaking change
Breaking Changes¶
REST API→ The dictionary lookup response was restructured to carry the richer data below (senses with multiple glosses and readable tags, examples with translations, furigana, fuller kanji profiles). Clients of/dict/queryand/dict/analyzeneed to adopt the new shape
Added¶
-
Frontend→ TheDictionarypage is now a study hub. One search bar covers Japanese words, wildcard patterns, English meanings, and finding kanji by their radicals (matching all or any of them), a breadcrumb trail connects every view, and the landing page offers your recent lookups plus kanji and words to explore -
Frontend→ Kanji show animated stroke-order diagrams that draw themselves (with replay, step, and speed controls on the kanji page), their radical components, pronunciation clips, words that use the kanji, and example sentences -
Frontend→ Word entries show accurate furigana above the headword, senses with plain-language grammar tags instead of dictionary codes, common-word and JLPT badges, antonym and see-also links, and example sentences with English translations -
Frontend→ The word pop-up in the player was reorganized into collapsible sections (Entry, Names, Kanji, Examples, Grammar) with playable stroke animations, grammar terms that explain themselves on hover, and a link into the Dictionary
Changed¶
-
Server→ Dictionary lookups run onkotobase 0.4.1and use the sentence context of a clicked word (its reading and part of speech) to rank the right entry first, so words that share a written form resolve to the reading you actually clicked -
Docker Images→ The server images now bake the pronunciation audio pack alongside the dictionary database
Fixed¶
PWA→ Mirumoji can be installed as an app (with offline interface caching) on phones and other devices. The server now runs a persistent local certificate authority, and installing its certificate once per device (downloadable from the running app, see the new docs guide) makes the connection fully trusted. The app couldn't be installed before because browsers require a fully trusted certificate for service worker registration
3.1.1 - 2026-06-22¶
A patch release with two fixes
Fixed¶
-
Server→ GPU video conversion now correctly detectsNVENC. The capability check encoded a probe frame smaller thanNVENC's minimum supported size, so it always failed and every conversion fell back to CPU, even on a GPU whose encoder works -
Package→ the package reports its real version again.__version__was not updated for the3.1.0release, so the version shown in the desktop launcher (and used to name the local data directory) was stale
3.1.0 - 2026-06-21¶
This release moves every long-running media operation into a background job system,
adds batch processing so one operation can run over many files at once, and makes the
GPU Docker images much smaller. As a v3.x release (see the v0.1.0 note above) it
includes a few breaking changes, listed first
Breaking Changes¶
-
REST API→ the old one-shot endpoints for transcription, subtitle generation, conversion, and subtitle cleanup were removed. These operations now run through the background job system instead -
REST API→ word breakdowns and sentence explanations are now sent as a live stream while they are generated, rather than as a single response at the end -
CLI→ themirumoji servercommand moved into a new development-only group and is nowmirumoji dev server -
Database→ the database format changed and is not upgraded automatically from3.0.0. Reset it when upgrading by runningmirumoji down -v(this clears local data, in keeping with the pre-1.0 note above)
Added¶
-
Server→ long operations (transcription, subtitle generation, conversion, and LLM subtitle cleanup) now run in the background. A file is uploaded once, and any number of operations can then run on it without uploading it again -
Server→ batch processing runs one operation across many files at once and tracks each file on its own. On the Modal backend the files are processed in parallel -
Frontend→ a task tray keeps your running and finished jobs visible as you move around the app, and loads each result back in when it is done -
Frontend→ newFilesandTaskssections on the dashboard let you upload files or a whole folder, select several and run them as a batch, browse the full job history, and open each result -
Frontend→ when setting up an LLM, you can now pick the model from a searchable list of your provider's models instead of typing its exact name -
Frontend→ video conversion now has a quality preset (Performance,Balanced, orQuality) alongside the resolution and bitrate options, so you can trade encode speed for output quality -
CLI→mirumoji dev upbuilds and runs the app from a local source checkout, for testing the Docker setup during development
Changed¶
-
Frontend→ running an operation in the player no longer freezes the toolbar. It is handed to the task tray, which loads the result back in when it finishes. The video player was also reworked into a shared component that clip previews reuse -
Frontend→ a phone held sideways now uses the mobile layout, since the desktop layout only starts at tablet width -
Launcher→ the launcher's logs and the Docker download progress are tidier and easier to follow, in both the CLI and the desktop app -
Docker Images→ the GPU images are smaller. PyTorch was removed because transcription does not need it, and the speech model now downloads on first use into a persistent cache instead of being baked into the local GPU images -
Server→ video conversion is faster and leaner. On the GPU the whole decode, scale, and encode pipeline now stays on the GPU instead of copying frames back and forth, and the GPU and Modal images ship a newer FFmpeg build to support it. Conversion also picks the encoder from what the GPU can actually do, so machines whose GPU cannot encode (and CPU-only setups) go straight to a fast CPU encode. Converted videos keep their original aspect ratio now rather than being padded with black bars
Fixed¶
-
Frontend→ the player now handles video formats your browser cannot play (such as.mkvon iOS) by offering to convert them to MP4 instead of showing a broken player. Loading a different video also resets the saved position so it never starts past the end of a shorter one -
Frontend→ the navigation menu scrolls on short screens (such as a phone held sideways) so every item stays reachable, and long entries on theHomepage no longer stretch the layout out of shape -
Server→ saving a clip no longer fails for clips with long Japanese text, and saved clips now use a server-generated filename that closes a security issue where a crafted upload name could write outside its folder -
Server→ deleting a file also removes the jobs that used it (and is blocked while one of those jobs is still running), cancelling or deleting a running job no longer leaves the job list in a broken state, and a failed job now shows a clear reason -
Server→ converting a video on a cloud GPU that has no video encoder (such as anA100,H100, orB200) no longer wastes time on a failed hardware-encode attempt before falling back, which had made GPU conversion slower than plain CPU -
CLI→mirumoji logs -fno longer crashes when you press Ctrl+C, and re-runningmirumoji upno longer contacts Docker Hub when the images are already downloaded
3.0.0 - 2026-06-15¶
A structural and packaging rewrite of Mirumoji
-
The backend + CLI are merged into a single, pip-installable
mirumojipackage, and the release, docs, and dev-container tooling are rebuilt around it -
The core immersion workflow is unchanged from
2.6.0, theLauncher(CLI + Desktop GUI) is substantially expanded, and LLM support is no longer limited toOpenAI -
There is intentionally no
2.6.0→3.0.0diff, since nearly everything moved internally, so this entry answersWhat Carried Over?+What's New?+How To Run Itinstead
What Carried Over From 2.6.0¶
The immersion workflow is Unchanged
-
Upload local videos, anime episodes, or audio for clickable
tokenized Japanese subtitleswith dictionary lookups -
Transcribe audio / generate subtitles with
Whisper -
Get word / sentence breakdowns from LLMs, or prompt the LLM to refine the Whisper-generated subtitles
-
Save
clipsand export them to anAnkideck -
Organize your data (clips, LLM templates, files, transcriptions, ...) on the server by profile
-
Self-host the
Docker Compose ApplicationwithLocal-NVIDIA-GPU/Modal Cloud-GPU Offloadbackend options -
Access the application via HTTPS from any device on your local network using the automatically generated self-signed certificate
What's New / Expanded¶
Multiple LLM Providers (New)¶
2.6.0 required an OpenAI API key
3.0.0 makes LLM features completely optional and adds Anthropic (Claude) + Google (Gemini) + Any Custom OpenAI-Compatible Endpoint support via a provider / model picker
CLI Launcher (Expanded)¶
The 2.6.0 CLI had 5 commands (launch / shutdown / launch_local /
build / gui) driven by interactive prompts and a hand-managed .env
3.0.0 rebuilds it on Typer / Rich, adds the status / logs / doctor
/ server / render commands + a managed-config surface (config set/delete/import/show/path/clear)
Desktop Launcher (Expanded)¶
The 2.6.0 flaskwebgui / PyInstaller window is rebuilt on Flet and gains
a Settings panel where you can configure the transcription backend, image
source, and LLM / Modal keys. It also has full environment checks, live status
display, and Docker Compose log filtering
Modal Offload (Hardened)¶
Modal GPU jobs stream their media through a per-job ephemeral Modal Volume
instead of a baked image mount, so long media (multi-hour, multi-GB) transcodes
and transcribes reliably. Large uploads also stream at full speed rather than
being throttled at the reverse proxy
How To Run It¶
The Setup Section contains detailed information on all of
the ways that you can get Mirumoji running
Upgrading From 2.6.0¶
Your Data Does Not Carry Over
The database schema changed in 3.0.0, so existing 2.6.0 profiles,
clips, transcripts, and templates are NOT migrated
Treat 3.0.0 as a fresh install.
Additional Details → Changed Surfaces
-
Package→apps/backend+apps/climerged into oneapps/mirumoji/package published to PyPI asmirumoji -
CI / CD→ 12 workflows redesigned as an orchestratedrelease.yamlcalling reusable_version/_images/_pypi/_pages/_desktopworkflows. Images are published toDocker Hubonly (GHCR dropped) -
Docs→ MkDocs Material custom CSS theme,mkdocstrings-python(API) +TypeDoc(frontend API),awesome-navstructure -
Dev Containers→ fixed builds +postCreateCommandbootstrap, andflake8changed toruff
Community → community files moved to .github/, YAML issue forms, quality-gate PR template