Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
jellyfin-plugin-floatplane
A Jellyfin server plugin that exposes your Floatplane subscriptions (creators → channels → videos, plus live streams) inside Jellyfin and all its clients, so Floatplane content shows up next to the rest of the library on the Pi5 server and plays through the normal Jellyfin players.
Status (2026-10-25): browsing works (verified against a local Jellyfin
10.10.7); playback proxy is implemented but still needs a real session
cookie to be verified. See doc/plan.md for milestones and
doc/floatplane-api-notes.md for the API.
The plugin is a pure managed .NET assembly (AnyCPU IL), so one build runs
on both linux-x64 (dev box) and linux-arm64 (the Pi5).
Prerequisites
| Target | What to install |
|---|---|
| Arch / Garuda (dev box) | sudo pacman -S dotnet-sdk-8.0 (Jellyfin 10.10.x = .NET 8) — for Jellyfin 12.x use dotnet-sdk (.NET 10) |
| Debian / Ubuntu | apt install dotnet-sdk-8.0 from the Microsoft repo |
| Pi5 (runtime only) | nothing — the plugin runs inside the existing linuxserver/jellyfin container |
Optional, for local testing: Docker (to run a throw-away Jellyfin of the same version as the Pi5 with the plugin folder mounted).
Build
git clone https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane.git
cd jellyfin-plugin-floatplane
scripts/package.sh # → build/Floatplane_<ver>/ (DLL + meta.json), build/floatplane_<ver>.zip (+ .md5)
The VS Code build task (Ctrl+Shift+B) runs the same script. Plain
dotnet build works too (jellyfin-plugin-floatplane.sln).
Install
From the plugin repository (recommended): Dashboard → Plugins → Repositories → add
https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/releases/download/latest/manifest.json
then Catalog → Channels → Floatplane → Install → restart Jellyfin.
Manual, on the Pi5 (linuxserver image):
curl -fsSL https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/releases/download/latest/install-pi5.sh | sh -s -- --dry-run
# then without --dry-run; it installs into /srv/docker/jellyfin/data/plugins/ and restarts the container
Manual, from a local build:
# linuxserver image keeps data under /config/data (container path);
# host path on the Pi5: /srv/docker/jellyfin/data/plugins/ (infra-Doc services/media-stack.md)
cp -r build/Floatplane_0.1.0.0 /srv/docker/jellyfin/data/plugins/
docker restart jellyfin
The Pi5 runs Jellyfin 10.10.7 but
lscr.io/linuxserver/jellyfin:latestis already 12.3 (.NET 10). Pin the tag (10.10.7ubu2404-ls80) before anydocker pull, or the plugin becomesNotSupportedovernight.
Then Dashboard → Plugins → Floatplane → paste your sails.sid cookie
(the page explains where to find it) → Validate → Save. A "Floatplane"
channel appears under My Media: creators → sub-channels → videos.
Without a cookie you can still browse creators listed under
"Extra creators" (public data); playback needs the cookie.
How it works (short)
FloatplaneChannel(IChannel) lists creators → sub-channels → posts from Floatplane's public listing API; ids arecreator:…,channel:…,post:….- On play,
IRequiresMediaInfoCallbackfetches the post (login) and hands Jellyfin signed URLs to the plugin's ownFloatplane/Stream/…endpoints. - The stream endpoint calls
delivery/info(cached, throttled to ~2/min), fetches the HLS playlist, and rewrites it: the AES-128 key URI points back at the plugin (which fetches the key with the cookie), segments go straight to the CDN. ffmpeg then remuxes (stream copy) for the client. - A scheduled task refreshes the catalogue and bumps the channel cache key.
Test
dotnet test # unit tests (models, HLS rewriter, API client with fixtures from the HAR)
The test host needs the ASP.NET Core 8 shared runtime (the plugin references
Jellyfin's controllers): on Arch sudo pacman -S aspnet-runtime-8.0.
Local end-to-end test with a disposable Jellyfin matching the Pi5 version:
mkdir -p .jellyfin-test/config/data/plugins
cp -r build .jellyfin-test/config/data/plugins/Floatplane_0.1.0.0 # writable copy, not :ro
docker run --rm -p 8096:8096 -v $PWD/.jellyfin-test/config:/config \
lscr.io/linuxserver/jellyfin:10.10.7ubu2404-ls80
# logs: .jellyfin-test/config/log/log_*.log ; plugin status: Dashboard → Plugins
Docs
doc/plan.md— goal, stack, milestones, roadmapdoc/floatplane-api-notes.md— endpoints, auth, HLS/AES-128 playback flowdoc/research/jellyfin-plugin-research.md— plugin API research (10.10 vs 12.x, channels, proxy pattern, packaging, paths)doc/research/floatplane-api-research.md— community API docs, OAuth device flow, DPoP, rate limits, other clientsdoc/research/reference-sources/— snapshots of other clients' source for study (chaosflix is the template to follow)doc/har/— the captured browser session (gitignored, contains credentials)- Gitea wiki (once the repo exists) — architecture and design decisions