Files
jellyfin-plugin-floatplane/README.md
claude bf476134c2
Some checks failed
release / build-release (push) Has been cancelled
v0.2: All videos folder, shared watched state, release-order sorting, official icon, OAuth plumbing, docs
- per-creator "All videos" folder (release order across sub-channels); sub-channel copies use
  cpost: ids and UserDataMirror keeps played/resume state in sync
- SortNameUpdater forces release-order sort names so every client lists newest first by default
- official Floatplane icon as channel image (Primary only — a channel Thumb hid video thumbnails
  in Continue Watching) and as 16:9 plugin thumbnail; one-time image replacement on upgrade
- OAuth device-flow login (FloatplaneAuthService + settings UI); needs a Floatplane client id;
  Turnstile verified domain-bound so password login inside Jellyfin is impossible
- generic install.sh (linuxserver / official image / native), thumb.png in package + manifest
- README rewritten for a general audience, doc/usage.md with screenshots, 60 tests

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-25 16:36:32 +01:00

151 lines
7.0 KiB
Markdown

# Floatplane for Jellyfin
A [Jellyfin](https://jellyfin.org) server plugin that brings your
[Floatplane](https://www.floatplane.com) subscriptions into Jellyfin.
Creators, their sub-channels and every video appear as a **Floatplane**
channel under *My Media* in the web client and in all Jellyfin apps, and
play through the normal Jellyfin player — with watched state, resume,
"Continue Watching", "Recently Added" and search, like any other library.
![Home screen with the Floatplane tile, Continue Watching and Recently Added](doc/img/home.png)
## Features
- **Creators → All videos → sub-channels.** Each creator you subscribe to
gets an *All videos* folder (every sub-channel in release order, newest
first) plus one folder per sub-channel (TechLinked, ShortCircuit, …).
- **Real metadata**: thumbnail, description, duration, release date,
sub-channel as *Genre*, creator as *Studio*.
- **Newest first by default** in every Jellyfin client, without touching
the sort menu.
- **Watched/resume state is shared** between the *All videos* copy and the
sub-channel copy of a video.
- **Low-CPU playback**: the server remuxes Floatplane's H.264/AAC stream
(stream copy, no re-encode). Quality levels show up as *Versions*.
- **Home screen integration**: "Recently Added in Floatplane" and
"Continue Watching" work out of the box.
- **Browse without logging in**: public creators (e.g. `linustechtips`)
can be listed by url-name; playback needs a logged-in session.
- **Search test tool** for Floatplane's own search API on the settings
page, and a scheduled task that refreshes the catalogue.
![Creator folder: All videos first, then the sub-channels](doc/img/creator-folder.png)
## Requirements
| | |
|---|---|
| Jellyfin | **10.10.x** (plugin targetAbi `10.10.0.0`, .NET 8). Jellyfin 12.x needs a separate build (not available yet). |
| Architecture | one AnyCPU DLL — runs unchanged on x64 and arm64 (Raspberry Pi 4/5 etc.). |
| Floatplane | an account with an active subscription for playback. |
## Install
**From the plugin repository (recommended)**
1. Dashboard → Plugins → **Repositories** → **+**. Name it anything and use
this URL:
```
https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/releases/download/latest/manifest.json
```
2. Dashboard → Plugins → **Catalog** → section *Channels* → **Floatplane**
→ **Install**.
3. Restart Jellyfin. The plugin shows as *Active* under *My Plugins*.
Updates then appear in the catalog like any other plugin.
**With the install script** (Docker — linuxserver.io or official image — or
a native install; detects the right plugin directory, verifies the checksum,
restarts Jellyfin):
```bash
curl -fsSL https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/releases/download/latest/install.sh | sh -s -- --dry-run
curl -fsSL https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/releases/download/latest/install.sh | sh
```
Environment overrides: `TAG` (`latest` or `vX.Y.Z`), `JELLYFIN_CONTAINER`
(default `jellyfin`, empty = native), `JELLYFIN_CONFIG_DIR`, `PLUGINS_DIR`,
`PUID`/`PGID`.
**Manually**: download `floatplane_<version>.zip` from the
[releases](https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/releases),
unzip it into `<jellyfin data>/plugins/Floatplane_<version>/` and restart.
## Log in
Floatplane's password login requires a Cloudflare captcha that only works on
floatplane.com, so the plugin cannot ask for your username and password.
Two options, both on **Dashboard → Plugins → Floatplane**:
1. **Session cookie** (works today): log in at floatplane.com in a browser,
copy the value of the `sails.sid` cookie (DevTools → Application/Storage
→ Cookies), paste it into the settings page, press **Validate cookie**
(shows your username and subscriptions) and **Save**.
2. **Login with Floatplane** (OAuth device flow — the way Floatplane's own
apps and clients like Hydravion or Wasserflug log in). This needs a
client id issued by Floatplane; without one the button reports
`invalid_client`.
Step-by-step instructions, every setting explained and troubleshooting:
**[doc/usage.md](doc/usage.md)**.
## How it works (short)
- The channel lists creators → *All videos* / sub-channels → posts from
Floatplane's public listing API (ids `creator:…`, `all:…`, `channel:…`,
`post:…`, `cpost:…`).
- On play, the plugin fetches the post details with your session and hands
Jellyfin signed URLs to its own `Floatplane/Stream/…` endpoints.
- The stream endpoint asks Floatplane for the stream info (cached 6 h,
throttled to the ~2/min the API allows), downloads the HLS playlist and
rewrites it: the AES-128 key is fetched through the plugin with your
session, the video segments go straight to Floatplane's CDN. Jellyfin's
ffmpeg then stream-copies the result to the client.
- A scheduled task refreshes the catalogue and bumps the channel cache key
so Jellyfin re-lists the folders.
## Development
```bash
git clone https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane.git
cd jellyfin-plugin-floatplane
dotnet test # 59 unit tests (models, HLS rewriter, API client, catalogue)
scripts/package.sh # → build/Floatplane_<ver>/ (DLL, meta.json, thumb.png), build/floatplane_<ver>.zip (+ .md5)
scripts/package.sh 1.2.3.0 https://example.com/dl # versioned package + build/manifest.json
```
- Needs the .NET 8 SDK; the test host also needs the ASP.NET Core 8 shared
runtime (Arch: `sudo pacman -S dotnet-sdk-8.0 aspnet-runtime-8.0`).
- The VS Code `build` task (`Ctrl+Shift+B`) runs `scripts/package.sh`.
- Local end-to-end test against a throw-away Jellyfin of the right version:
```bash
mkdir -p .jellyfin-test/config/data/plugins
cp -r build/Floatplane_0.2.0.0 .jellyfin-test/config/data/plugins/ # writable copy
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
```
- Every push to `master` runs the tests and publishes the rolling `latest`
release (zip, md5, `manifest.json`, `install.sh`); a `vX.Y.Z` tag publishes
a versioned release.
More: [`doc/plan.md`](doc/plan.md) (milestones, roadmap),
[`doc/floatplane-api-notes.md`](doc/floatplane-api-notes.md) (the API as
observed), [`doc/research/`](doc/research/) (Jellyfin plugin + Floatplane
API research and reference sources), and the
[project wiki](https://gitea.brasse-pc.eu/brasse/jellyfin-plugin-floatplane/wiki).
## Credits & disclaimer
Unofficial, not affiliated with or endorsed by Floatplane Media Inc.
The plugin uses Floatplane's unofficial API documented by the community
([jamamp/FloatplaneAPI](https://github.com/jamamp/FloatplaneAPI)) and
borrows the channel + signed-proxy pattern from
[chaosflix-jellyfin](https://github.com/praetorianer777/chaosflix-jellyfin).
Use it with your own subscription, for personal viewing. The Floatplane
name and logo belong to Floatplane Media Inc.