# Kyoo ships edge images and strikes through two v5 features it has not rebuilt

> A self-hosted media server for video, positioned as an alternative to Jellyfin and Plex, built as six separate services on Postgres with no plugin system. Its compose file runs edge tags rather than the tagged releases, two features removed in the v5 rewrite are still struck through, and the author develops it alone.

**zoriya/Kyoo** — A portable and vast media library solution.

- Repository: https://github.com/zoriya/Kyoo
- Website: https://kyoo.zoriya.dev
- Stars: 2,529 · Forks: 79
- Language: TypeScript
- License: GPL-3.0
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/zoriya-kyoo

## Two shipped features are struck through as not reimplemented in v5

The feature list carries two entries wrapped in strikethrough, and both carry the same parenthetical saying they are not reimplemented in v5 yet. One is watch list scrubbing, where a watch list syncs to connected services, with the TMDB-like service named as the first target and two issue numbers attached. The other is download and offline support, where videos are downloaded for viewing without a connection and progress syncs the next time a device comes online. Both read as descriptions of behaviour that shipped and then stopped existing. The reason sits further down, where the author writes that v5 rewrote most of the code. So a major version removed two user-facing features, the README marks them rather than deleting them, and neither has a target version given.

## No plugin system, so third parties consume the transcoder instead

There is deliberately no plugin system, and the stated aim is to have every feature built in instead. That removes one extension route and puts the weight on the other one. The project is split into multiple services that can work separately, and the text says this exists so third party apps can use those services, naming one that does: Meelo, which uses Kyoo's transcoder. So integration happens by calling a running service rather than by loading code into it, and writing scripts is described as easy for the same reason. The named consumer is a separate project with its own repository, which is the clearest evidence available that the service boundary is real and not just an internal split.

## One maintainer, four client targets, and Android TV still unchecked

The client table has three boxes ticked: web, Android and Chromecast. Android TV is unticked and marked as planned, hopefully soon. The explanation given is that the project is developed by one person only, and that this is why few clients exist. It then adds that the front end is written in react-native, so maintaining more clients is not a huge burden, while adapting the code so the native experience is good still takes time. The Android client also carries a second decision: it uses VLC to support as many codecs as possible, and you can use ExoPlayer instead if you prefer. That places a native media engine choice in the client rather than in a server-side pipeline, which is unusual for a server project and explains the codec coverage claim.

## The shipped compose runs edge images while the releases are numbered

Three of the service definitions name images from the project's own registry, and every one is tagged edge: the transcoder, the front end and the auth service. The release history is numbered, with v5.2.1 and v5.2.0 on the same day in August 2026 and v5.1.0 before that, so versioned artifacts exist and the compose file does not reference them. Two other details in the same file are worth reading before deploying. A CORS middleware sets its allowed origin list to a wildcard while permitting the Authorization, Content-Type, Range and X-Api-Key headers. And a phantom-token forward-auth middleware guards only the transcoder route, pointed at the auth service, while the front route on the root path prefix carries no auth middleware in the visible labels, so the proxy does not gate it.

## Six services and Postgres against a stated five minute setup

The top level is six service directories: api, auth, chromecast, front, scanner and transcoder, plus a chart directory holding the Helm chart and two compose files, one for development. The author names the architectural choice directly, saying the project targets servers, with Postgres instead of SQLite and multiple services, and that this is a deliberate move away from low technical depth. The stated philosophy is the opposite: few server-wide options, no directory structure to follow, setup in five minutes, and no cleaning up of media afterwards. Media that fails to scan is called a bug even with weird names, which is a clear quality bar. What the layout costs is visible in the deployment files: a wildcard image set, a reverse proxy with per-route middleware, and a readiness condition on the database.

## Empty API keys fall back to a shared default, and any loopback port is a redirect target

Two third-party credentials are configured by example file. The instruction is to leave them empty to use Kyoo's default API key, with a pointer to copy a read access token rather than an API key from the movie database settings page, and a second pair for the television database including an optional subscriber pin. An empty value therefore does not disable the feature, it routes requests through a credential shipped with the project, which every default installation shares. The example file also documents the OIDC redirect allowlist in unusually specific terms: the official web and mobile apps are always allowed, loopback addresses on any port are always allowed, and other third-party clients must be added explicitly as web origins matched by scheme, host and optionally port.

## The default transcode preset is the lowest quality and vaapi cannot use presets

Hardware transcoding is selected through compose profiles rather than a separate config file, with the example file noting the variable is equivalent to the docker compose profile option. The four choices are cpu, which is no hardware acceleration, and then vaapi, qsv and nvidia. Alongside them sits a preset variable whose default is fast, and the comment on that line says faster means worst quality and suggests a slower preset once hardware acceleration is in use, because the codec preset and the hardware path are separate decisions. A second comment carries a warning that using the vaapi acceleration disables presets entirely because they are not supported there. So the shipped default is the lowest quality setting, and one of the three hardware paths cannot use the setting at all.

## Conclusion

Adopt this if you want a video library that tolerates bad file naming and you are willing to run several services rather than one container on SQLite. The trade is stated plainly by the author, who is the only maintainer. Before you commit, check the three gaps that are documented rather than hidden: the two features struck through as not yet reimplemented in v5, the Helm chart's lack of replica support, and the fact that the default compose pulls edge images so your deployment does not correspond to any release tag. Decide separately whether the shared default API credentials and the wildcard CORS origin in that compose are acceptable for your network.

## FAQ

### What is Kyoo?

A self-hosted media server focused on video, covering movies, series and anime, and positioned as an alternative to Jellyfin or Plex. It is written with a react-native front end and has no plugin system, aiming to build features in rather than extend it.

### Does Kyoo need a tidy folder structure for media files?

No. Requiring no folder structure is one of its stated design goals, and bad naming, everything in one directory and unusual anime names are all said to work out of the box. Media that fails to scan is treated as a bug.

### How do I enable hardware transcoding in Kyoo?

Through compose profiles, with cpu for no acceleration and then vaapi, qsv or nvidia. The variable in the example environment file is equivalent to the docker compose profile option. Note that the vaapi path does not support presets.

### Can Kyoo download videos for offline viewing?

Not in v5. Download and offline support appear in the feature list struck through, with a note that they are not reimplemented in v5 yet. Watch list scrubbing to connected services is marked the same way.

### Does Kyoo have a plugin system?

No, and that is deliberate, with the aim being to build every feature in instead. Extension happens through the services, which can run separately, and one third party project is named as using Kyoo's transcoder.

## Sources

- [License: GPL-3.0](https://github.com/zoriya/Kyoo/blob/master/LICENSE)
- [Project website](https://kyoo.zoriya.dev)
- [README](https://github.com/zoriya/Kyoo/blob/master/README.md)
- [Releases](https://github.com/zoriya/Kyoo/releases)
- [zoriya/Kyoo on GitHub](https://github.com/zoriya/Kyoo)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/zoriya-kyoo
