Status: Active Jellyfin plugin. Releases are published through GitHub Releases and the plugin manifest; issues are open for reproducible bugs and focused feature requests.
YummyKodik is a Jellyfin plugin that builds a local anime library from YummyAnime and streams episodes through Jellyfin from Alloha, CVH, and Kodik-backed sources.
- Releases:
https://github.com/queukat/YummyKodik/releases - Raw Jellyfin manifest:
https://raw.githubusercontent.com/queukat/YummyKodik/gh-pages/manifest.json - GitHub Pages manifest:
https://queukat.github.io/YummyKodik/manifest.json - Actions:
https://github.com/queukat/YummyKodik/actions - Issues:
https://github.com/queukat/YummyKodik/issues
- Creates a local Jellyfin TV library layout with
tvshow.nfo,Season XX/*.nfo, andSeason XX/*.strm. - Reads anime from manually configured Yummy slugs or from a Yummy user list.
- Combines episode availability from three provider families under the hood: Alloha, CVH, and Kodik.
- Generates as many episode files as it can from all available provider data, instead of assuming one player has complete coverage.
- Uses the requested quality as a preference, then asks the selected provider for the best matching HLS stream.
- Falls back to another provider when an episode is missing, a selected provider has fewer episodes, or playback resolution fails.
- Resolves and caches a Kodik token automatically, with an optional manual token override.
- Adds intro/outro media segments from Yummy/Kodik skip timings for Jellyfin clients that support skip actions.
- Injects a small Jellyfin Web series-page widget where each user can choose a preferred voice translation or return to auto mode.
- Can create one episode file per episode, or one episode file per voice translation.
Anime providers rarely have identical coverage. One player may already have four aired episodes, another may have two, and a third may have only one or a different set of voice translations. YummyKodik is built around that reality.
During refresh, the plugin asks Yummy for provider metadata and builds a combined picture of what is currently playable. It prefers direct Yummy-backed providers first:
Alloha: usually the first generated provider when Yummy exposes enough Alloha data.CVH: used alongside Alloha and as a fallback when CVH has better episode/voice coverage.Kodik: used as a fallback and supplement when Yummy provider data is incomplete or a Kodik id is the best available route.
The result is that normal setup has no provider picker to babysit. You configure the anime source and desired quality, then let the plugin do the coverage work across all three providers. If episode 4 exists only in Kodik, refresh can still create the episode file even when Alloha has fewer episodes. If playback for a generated Alloha or CVH URL fails at runtime, the stream endpoint tries neighboring providers before giving up.
Voice selection follows the same idea. The plugin first honors an explicit per-user choice from the Jellyfin Web widget, then Preferred translation filter, then automatic fallback. In per-voice mode it creates separate files for available voice translations; in normal mode it keeps one episode file and resolves the best voice when you press play.
At startup, the plugin tries to patch Jellyfin Web index.html with a small bootstrap script:
/web/ConfigurationPage?name=seriesTranslation.js&v=<plugin-version>
That script adds an Озвучка row to supported series details pages. The widget asks the plugin for available voices, shows Авто plus the combined Alloha/CVH voice list, and saves the choice through YummyKodik/setTranslation.
The saved value is per Jellyfin user and per Yummy series, so different users can choose different voices for the same anime. In normal single-file mode, this is how SxxEyy.strm can still play a chosen voice without creating separate episode files. Changing the voice in the widget does not require a library refresh; the next playback request reads the saved preference and resolves the best matching provider.
If the selected voice exists only in a neighboring provider, playback can move from the generated provider URL to that provider instead of silently playing another voice. Choosing Авто clears the saved preference and returns to Preferred translation filter plus automatic fallback.
If Jellyfin Web index.html is not writable or not found, the widget is skipped. Playback still works through generated files, Preferred translation filter, and per-voice files if that mode is enabled.
- Jellyfin
10.11.x. The plugin is built against10.11.0for Docker/base-image compatibility. - A writable folder visible to the Jellyfin server for generated
.strmand.nfofiles. - A Jellyfin library pointing at that generated folder, usually with content type
Shows. - A Yummy public token from
https://site.yummyani.me/dev/applications. - Optional: an Alloha API token if you want the plugin to supplement missing Alloha entries by
kp_id/imdb_id.
Use one of these repository URLs in Jellyfin:
https://raw.githubusercontent.com/queukat/YummyKodik/gh-pages/manifest.json
https://queukat.github.io/YummyKodik/manifest.json
Then install:
- Open
Dashboard -> Plugins -> Repositories -> Add. - Paste the manifest URL.
- Open
Dashboard -> Plugins -> Catalog -> YummyKodik -> Install. - Restart Jellyfin.
- Open
Dashboard -> Plugins -> My Plugins -> YummyKodik -> Settings.
Download YummyKodik_<version>.zip from GitHub Releases and extract the files directly into a versioned plugin folder.
Windows service or tray install:
$version = "1.1.2.0"
$plugins = "$env:ProgramData\Jellyfin\Server\plugins"
New-Item -ItemType Directory -Force "$plugins\YummyKodik_$version"
Expand-Archive ".\YummyKodik_$version.zip" "$plugins\YummyKodik_$version" -ForceWindows portable install:
$version = "1.1.2.0"
$plugins = "$env:LOCALAPPDATA\jellyfin\plugins"
New-Item -ItemType Directory -Force "$plugins\YummyKodik_$version"
Expand-Archive ".\YummyKodik_$version.zip" "$plugins\YummyKodik_$version" -ForceDocker install by copying an already extracted package:
$version = "1.1.2.0"
docker exec jellyfin mkdir -p /config/plugins/YummyKodik_$version
docker cp .\artifacts\package\. jellyfin:/config/plugins/YummyKodik_$version/
docker restart jellyfinDocker install from a zip inside the container:
version=1.1.2.0
mkdir -p "/config/plugins/YummyKodik_$version"
unzip "YummyKodik_$version.zip" -d "/config/plugins/YummyKodik_$version"If Jellyfin cached a failed manual install as NotSupported, remove or rename /config/plugins/YummyKodik_<version>/meta.json after fixing the files, then restart Jellyfin.
Open Dashboard -> Plugins -> My Plugins -> YummyKodik -> Settings.
Buttons:
Save: writes the current settings to the Jellyfin plugin configuration.Reload: discards unsaved edits and reloads settings from Jellyfin.Cancel: closes the settings page.
Main settings:
Yummy public token (X-Application): public token fromhttps://site.yummyani.me/dev/applications.Yummy API base URL: defaults tohttps://api.yani.tv; change only if the API endpoint changes.Alloha API token: optional token for extra Alloha catalog lookup.Alloha API base URL: defaults tohttps://api.alloha.tv.Output root path: path on the Jellyfin server where generated files are written.Jellyfin server base URL: base URL inserted into generated.strmfiles.Preferred translation filter: preferred voice tokens separated by|, for exampleanilibria|aniliberty|shiza.Create separate STRM for each voice translation: changes library layout from one file per episode to one file per voice.Preferred quality: target quality, usually720or1080; providers may return the nearest available stream.Minimum plugin log level: defaults toWarning; set toInformation,Debug, orTraceonly when diagnosing noisy refresh/playback behavior.Yummy slugs: one Yummy slug per line for manual mode.
Optional settings:
Enable Kodik HTTP request debug logs: noisy HTTP request/response diagnostics for Kodik troubleshooting.Enable refresh performance diagnostics: logs refresh stage timings and file-operation counters.Use user list subscription: pulls anime from/users/{id}/lists/{list_id}.Yummy user IDandYummy list ID: identify the Yummy list to sync.Yummy access token: bearer token for private Yummy endpoints.Yummy loginandYummy password: fallback login flow if no access token is provided.Refresh interval: scheduled refresh interval in minutes.
Manual slug mode:
- Put one or more Yummy slugs in
Yummy slugs. - Leave
Use user list subscriptionoff. - Run
Dashboard -> Scheduled Tasks -> YummyKodik library refresh.
User list mode:
- Turn on
Use user list subscription. - Set
Yummy user ID,Yummy list ID, and eitherYummy access tokenor login/password. - Manual slugs are still honored, so you can combine both sources.
Single episode file mode:
- Leave
Create separate STRM for each voice translationoff. - The plugin creates
SxxEyy.strm. - Playback picks a voice using the per-user saved choice, then
Preferred translation filter, then provider fallback.
Per-voice file mode:
- Turn on
Create separate STRM for each voice translation. - The plugin creates files like
S01E01 - AniLibria.strm. - Jellyfin can show voice translations as separate episode versions.
Translation widget mode:
- The plugin patches Jellyfin Web
index.htmlat startup to loadseriesTranslation.js. - On a supported series details page, the widget shows
Autoand the combined available Alloha/CVH voice choices. - Choosing a voice saves a per-user, per-Yummy-series preference that normal single-file playback uses on the next play.
- Choosing
Autoclears the saved preference and returns to automatic selection. - No library refresh is required after changing the widget choice.
Use container paths in plugin settings. A Windows path such as D:\video\YummyKodik only works for Windows Jellyfin. In Docker, use a path inside the container, for example:
/media/yummykodik
Mount that path from the host, then point a Jellyfin Shows library at the same container path.
Jellyfin server base URL must be reachable from the Jellyfin container and from playback clients. On Docker Desktop, this often works well:
http://host.docker.internal:8096
or, if Jellyfin is published on host port 8099:
http://host.docker.internal:8099
A trailing slash is safe. The plugin trims it before generating paths, so this:
http://host.docker.internal:8099/
generates:
http://host.docker.internal:8099/YummyKodik/stream?...
not:
http://host.docker.internal:8099//YummyKodik/stream?...
After changing slugs, user-list settings, Output root path, Jellyfin server base URL, or per-voice mode:
- Save the plugin configuration.
- Run
Dashboard -> Scheduled Tasks -> YummyKodik library refresh. - Scan the Jellyfin library that points at
Output root path. - Open a generated series and start playback.
Playback URL types:
provider=alloha: builds an Alloha HLS session and proxies playlists/segments through/YummyKodik/alloha-proxy; can fall back to CVH/Kodik-compatible data when needed.provider=cvh: builds a CVH HLS session and proxies nested playlists/segments through/YummyKodik/cvh-proxy; can fall back to Alloha/Kodik-compatible data when needed.type=...&id=...: Kodik-backed URL mode, used as legacy playback and as a supplement when provider coverage is incomplete.
Restore and build:
dotnet restore .\YummyKodik\YummyKodik.csproj
dotnet build .\YummyKodik.sln -c ReleaseRun the lightweight regression suite:
dotnet run --project .\YummyKodik.Tests\YummyKodik.Tests.csproj -c ReleaseCreate a local release ZIP on Windows:
.\scripts\package.ps1 -Version 1.1.2.0Create a local release ZIP on Linux/macOS:
bash ./scripts/package.sh 1.1.2.0This produces:
artifacts/YummyKodik_<version>.zipartifacts/YummyKodik_<version>.zip.md5
The release workflow runs on version tags and publishes the ZIP, MD5 checksum, GitHub Release, and gh-pages manifest.
Recommended tag format follows the existing release convention:
git tag 1.1.2.0
git push origin 1.1.2.0Tags with a leading v also work because the workflow normalizes versions.
The package was smoke-tested against jellyfin/jellyfin:10.11.0 with a single configured slug:
fermerskaya-zhizn-v-inom-mire-2
Verified:
- The plugin loads as
Active. - The refresh task generates one series and five aired episode
.strmfiles. - A trailing slash in
ServerBaseUrldoes not produce a double slash in generated URLs. - The generated Alloha stream returns an HLS master playlist.
- A nested playlist returns
200 application/vnd.apple.mpegurl. - The first proxied
.tssegment returns200 video/MP2T.
- Generated playback sources use HLS.
- Intro/outro skip support depends on the Jellyfin client honoring media segments.
- If you update from an older manual install, restart Jellyfin after replacing plugin files.
Special thanks to YaNesyTortiK/AnimeParsers, which helped show that building a plugin like this was possible in the first place.
This project is licensed for non-commercial use under the PolyForm Noncommercial License 1.0.0. Commercial use, resale, paid distribution, marketplace publication, SaaS hosting, or bundling into a paid product requires separate written permission from the author. Project names, logos, package identifiers, store listings, screenshots, and other branding assets are not licensed for use in forks or redistributed builds.
