-
JellyTau v0.7.0
StablePublish Documentation / Build & publish docs to gitea-pages (push) Canceled after 0s🏗️ Build and Test JellyTau / Run Tests (push) Successful in 21m50sTraceability Validation / Check Requirement Traces (push) Successful in 44s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m50sBuild & Release / Run Tests (push) Successful in 18m46sBuild & Release / Build Linux (push) Successful in 30m52sBuild & Release / Build Windows (push) Successful in 15m13sBuild & Release / Build Android (push) Successful in 31m53sBuild & Release / Create Release (push) Successful in 12sreleased this
2026-08-16 20:28:16 +00:00 | 173 commits to master since this release✨ Changes
- Native Android video is now the default. Video decodes on the device's
hardware decoder instead of the built-in web player, which is easier on the
battery and lets picture-in-picture show the video rather than the app. The
default had been held back deliberately since the picture defects were fixed,
because returning from background audio left playback dead on that path; both
blockers below are fixed and verified on a device, which is the standard this
default has been held to since it last shipped early. The Settings toggle
remains, now as the fallback to the web player, and an explicit choice still
wins in both directions — anyone who turned it off keeps it off.
(UR-003, UR-004 → DR-188)
🐛 Fixes
-
The letterbox bars stop showing things that are no longer there. With
native video on, the padding around the picture kept whatever had last been
drawn in it: the previous frame flashing on rotation, a ghost copy of the
control bar stranded at the top of the screen, each new clock digit drawn over
the one before it, and the sleep-timer and quality menus leaving their imprint
after closing. One cause under all of it — nothing painted those bars. The
window surface is opaque, and for an opaque surface Android's renderer skips
clearing the damaged region and assumes the view hierarchy covers every pixel;
the video view covers only the letterboxed rect, so the bars were the window
background's alone to paint, and enabling compositing had cleared that
background to transparent. Three earlier attempts missed because they aimed at
the window's rotation animation and at video-frame retention — which is also
why the artefact reproduced standing still, with no rotation involved.
(UR-003, UR-066 → DR-194) -
Returning from background audio brings the picture back. On the native
path, coming back from the lockscreen left a black screen: a play overlay
pinned at 0:00 and a play button that did nothing. Nothing had crashed — the
transition was simply dropped. The two render paths resume by different means,
and only one of them was performed: the web player reloads from its stream URL,
while the native player owns no element and nothing watches that URL on its
behalf, so it has to be handed the item again explicitly. It now is, at the
position the audio reached. (UR-040, UR-003 → DR-196) -
Next Up stops repeating what Continue Watching already shows. The same
episode could occupy both home rows at once. (UR-023 → DR-197)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.7.0_amd64.deb—sudo dpkg -iWindows jellytau_0.7.0_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
- Native Android video is now the default. Video decodes on the device's
-
JellyTau v0.6.0
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 22m57sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m50sTraceability Validation / Check Requirement Traces (push) Successful in 24sBuild & Release / Run Tests (push) Successful in 7m21s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m3sBuild & Release / Build Linux (push) Successful in 20m32sBuild & Release / Build Windows (push) Successful in 14m29sBuild & Release / Build Android (push) Successful in 31m5sBuild & Release / Create Release (push) Successful in 12sreleased this
2026-08-16 19:24:34 +00:00 | 179 commits to master since this release🐛 Fixes
-
Android native video actually shows a picture. It shipped once as audio
with no picture and was reverted with the compositing named as the suspect
(DR-172). The compositing was not at fault; five independent defects sat
between ExoPlayer and the screen, each able to produce that symptom alone. The
app shell painted over the video surface through a CSS rule targeting
[data-app-shell], an attribute no component had ever set in any commit
(DR-185). The poster/title card had no way to lift on a path that renders no
<video>element, so a black card covered the surface for the whole session
(DR-182). The JavaScript bridges were installed by a 500 ms tree walk that
raced the page load — and lost permanently when it lost, because the
re-injection guard then declined to retry — sosetTransparent(true)could
never arrive (DR-183). TheSurfaceViewwas never detached, leaking one per
video and leaving picture-in-picture's gate stuck open (DR-184). Verified on a
device: logcat now carriesWebView transparent = trueand
Marking media readywith video on screen, the pair the original
investigation went looking for and could not find.
(UR-003, UR-004, UR-041 → DR-182, DR-183, DR-184, DR-185) -
Play and pause reach the player that is actually rendering. Transport did
nothing on the native video path — from the on-screen tap, from the control
bar, and from a direct command invocation — while seek and skip kept working,
because those decide elsewhere. Rust routes play/pause to the webview<video>
whenever it believes one is active, and the player route mirrored element state
into that belief unconditionally, including from a ten-second progress
interval. So on the native path the frontend re-declared every ten seconds that
an element was playing when none existed, and every intent was emitted at
something that was not there. The mirror now lives whereuseHtml5Elementis
known. This also explains the flashing transport controls, since they key off
the play state that was being contradicted on every tick.
(UR-005, UR-003 → DR-193, DR-195) -
The player's controls hide themselves on a touchscreen. The auto-hide timer
was armed only frommousemove, which a touch device never fires, so the
control bar stayed over the video for the whole film. It is now armed on entry
and on every touch, and pinned open while paused, seeking, or with a menu open.
(UR-003, UR-066 → DR-189) -
The system bars go away with the player. Immersive mode had exactly one
caller — the fullscreen button — so opening a video left the status and
navigation bars painted over it until the user pressed a control most never
press. (UR-066, UR-003 → DR-187)
🔬 Internal
-
Native video presents through a
TextureViewrather than aSurfaceView. A
SurfaceView renders on its own layer outside the app window and punches a
transparent region through it, and Android's own graphics documentation warns
that overlays do not composite reliably above one. (UR-003, UR-004 → DR-192) -
Native Android video remains opt-in, and is not yet the default. Turning it
on surfaced a further unverified path: returning from background audio is
implemented only for the webview element, so playback stays dead on the native
path (DR-190, proposed). Rotation still needs device confirmation (DR-194).
(UR-003 → DR-188)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.6.0_amd64.deb—sudo dpkg -iWindows jellytau_0.6.0_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
-
-
JellyTau v0.5.2
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 10m7sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m28sTraceability Validation / Check Requirement Traces (push) Successful in 19sBuild & Release / Run Tests (push) Successful in 7m35s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 3m2sBuild & Release / Build Linux (push) Successful in 20m0sBuild & Release / Build Windows (push) Successful in 8m36sBuild & Release / Build Android (push) Successful in 30m30sBuild & Release / Create Release (push) Successful in 21sreleased this
2026-08-13 05:48:01 +00:00 | 217 commits to master since this release🔧 Internal
- Gradle ships in the builder image instead of being downloaded per build.
The release APK job died at the Gradle wrapper step after the 11-minute Rust
compile had already succeeded, on a socket exception mid-transfer.
tauri android initregenerates a wrapper pointing at services.gradle.org, so
every Android job re-downloaded ~130MB — slow on a good day, a hard build
failure when the CDN drops the connection, and a standing violation of the rule
that every build tool already lives in the image. The sync script now repoints
the regenerated wrapper at the local distribution, parsing the version the
wrapper actually requests so a future Tauri bump logs a miss instead of pointing
at a missing file. Dev machines are untouched.
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.5.2_amd64.deb—sudo dpkg -iWindows jellytau_0.5.2_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
- Gradle ships in the builder image instead of being downloaded per build.
-
JellyTau v0.5.0
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 6m55sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m21sTraceability Validation / Check Requirement Traces (push) Successful in 15sBuild & Release / Run Tests (push) Successful in 7m36s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 2m57sBuild & Release / Build Linux (push) Successful in 20m4sBuild & Release / Build Windows (push) Successful in 8m42sBuild & Release / Build Android (push) Successful in 30m30sBuild & Release / Create Release (push) Successful in 17sreleased this
2026-08-11 19:22:21 +00:00 | 229 commits to master since this release✨ Features
-
Android video can render on the device's own video surface. Settings →
Video Playback → Native Video (experimental, off by default) hands
decoding to ExoPlayer, which draws into a surface composited behind a
transparent WebView, with the player controls layered on top of it.The backend had reported "this platform has a native video surface" on Android
all along, but the frontend threw that answer away in two separate places, so
the path had never actually run. Both are lifted. The setting can only ever
suppress the backend's choice, never override it upward: turning it off
forces the web player even where native is available, and turning it on does
nothing on platforms whose backend never offered it — Linux cannot composite
behind its webview, so it stays on the web player either way.Verified playing on a physical device. Still unverified: the mini-player
transition, audio-track switching on the native path, and whether hardware
decoding measurably improves battery or CPU — so the toggle stays off by
default. (UR-003, UR-004 → DR-150)
🐛 Fixes
-
The video surface now reaches the screen at all. The player built its
video surface, handed it to ExoPlayer, and then never added it to the view
hierarchy, because the Activity reference it needed was never supplied — so
native video would have decoded to a surface nobody could see, whatever else
was fixed. This also silently disabled picture-in-picture for video, which
gated on that same never-attached surface. (UR-003, UR-041 → DR-151) -
Platform playback support is no longer guessed from the browser user
agent. The frontend re-derived "does this platform decode audio natively" by
string-matchingnavigator.userAgent— a second copy of a decision the
backend already makes, free to drift out of step with the backends it was
describing. The backend now reports its own capabilities and the frontend
consumes them. (UR-003, UR-005 → DR-152)
🔧 Internal
- The git tag is now the single source of truth for a release version. The
version lived in four files that had to be edited in lockstep, and the release
workflow rewrote exactly one of them — so a tagged build produced an installer
named for the tag wrapped around package metadata naming the previous
release, and the Linux job, which had no version step at all, shipped whatever
happened to be committed.scripts/set-version.shnow writes all four from
one argument and every release job calls it with the tag. The Android
versionCodeis derived in the same place, guarded by tests for the property
that actually matters: it must increase monotonically and stay above the value
already installed in the field, or Android silently refuses the update.
(DR-153)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.5.0_amd64.deb—sudo dpkg -iWindows jellytau_0.5.0_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
-
-
JellyTau v0.4.8
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 19m31sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m28sTraceability Validation / Check Requirement Traces (push) Successful in 22sBuild & Release / Run Tests (push) Successful in 6m47s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m6sBuild & Release / Build Linux (push) Successful in 19m57sBuild & Release / Build Windows (push) Successful in 14m14sBuild & Release / Build Android (push) Successful in 30m26sBuild & Release / Create Release (push) Successful in 19sreleased this
2026-08-11 18:11:42 +00:00 | 235 commits to master since this release🐛 Fixes
- Video with an undecodable soundtrack now transcodes instead of playing
silent. Advertising a webview-shaped profile (v0.4.7) turned out not to be
enough: Jellyfin 10.11.5 enforces a direct-play profile's container and video
codec but ignores its audio codec, offering an E-AC-3 track for direct play
against a profile listing only AAC — and noCodecProfileor channel limit
changes that. The client now checks the track it would actually be served
against what its renderer can decode and forces the h264/AAC HLS transcode
when it cannot, rather than trusting the negotiation.
(UR-004 → DR-149)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.4.8_amd64.deb—sudo dpkg -iWindows jellytau_0.4.8_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
- Video with an undecodable soundtrack now transcodes instead of playing
-
JellyTau v0.4.6
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 20m34sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 6m6sTraceability Validation / Check Requirement Traces (push) Successful in 18sBuild & Release / Run Tests (push) Successful in 20m26s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 10m3sBuild & Release / Build Linux (push) Successful in 37m59sBuild & Release / Build Windows (push) Successful in 23m0sBuild & Release / Build Android (push) Successful in 40m26sBuild & Release / Create Release (push) Successful in 1m20sreleased this
2026-08-09 14:38:47 +00:00 | 240 commits to master since this release✨ Features
-
Downloaded video plays offline. Four separate defects each stopped it on
their own. A completed download'sfile_pathis already absolute — the worker
rewrites it on completion — but the player rooted it a second time and handed
the webview/data/user/0/app//data/user/0/app/videos/x.mp4; audio was
unaffected because it resolves the same column through Rust, which is why this
read as a video-only fault (DR-133). The asset protocol was never enabled at
all:convertFileSrcrewrites a path toasset.localhostunconditionally, but
Tauri only answers that origin when the cargo feature and the config are both
present, and neither was — which also silently defeated the cached-thumbnail
path, whose soft fallback to the server copy hid the breakage whenever the
server was reachable (DR-134). Tauri's asset protocol then answers a range-less
request by reading the whole file into memory and only advertises
Accept-Rangesfrom inside its range branch, so the first request never learns
ranges exist and Chromium gave up after ~31s; local media now comes from a
loopback HTTP server streaming bounded 4 MiB chunks, confined by a per-session
token and to the app data directory, because loopback is shared between apps on
Android (DR-137). And release builds setusesCleartextTraffic=false, so
Android rejected the request before any I/O — a network-security config now
exempts 127.0.0.1 only, and a remote server must still be HTTPS (DR-138).Known limitation: a download taken at
originalquality is a byte copy, so it
can be any container — an AVI holding XVID is served correctly and refused by
the webview regardless.
🐛 Fixes
-
A video queued from a media card no longer downloads as audio.
download_itemnever recordedmedia_type, and the reconnect resolver read
that NULL as'audio', so a movie's URL was resolved by the audio builder and
completed as an audio-only transcode. The item's own type now decides, and rows
already downloaded that way are requeued on reconnect — prevention alone leaves
them reading "downloaded" and still unplayable. (DR-135, DR-136) -
Some videos no longer play with no sound. Jellyfin's
MediaStream.Indexis
global across every stream in a media source, so index 0 is the video stream on
virtually all files — andAudioStreamIndex=0was sent as "the first audio
track" on the HLS transcode URL, the background-audio handoff URL, the
direct-play fallback and the negotiation body, asking the server to use the
video stream as audio. Servers that honour it produce a picture with no sound;
only those that silently correct the index hid it, which is why it surfaced as
"some videos have no audio". The parameter is now omitted unless a track was
actually chosen. (DR-140) -
A multichannel track is no longer direct-played to a two-channel sink.
MediaCodecListanswers "can this device decode 5.1", which is not the question
that decides whether anything is audible: a phone decodes AC-3 5.1 happily and
still has two channels to play it out of. The profile carried no
MaxAudioChannels, so the server was free to hand over the multichannel track —
silence, or dialogue folded into surround channels that go nowhere. The route's
actual channel count now bounds the profile; no codec is ever removed, so a
device with genuine surround output keeps direct-playing it. (DR-141) -
Video waits for audio focus instead of rolling silently. Video manages focus
by hand, and all three outcomes of the request were treated as success —
includingREQUEST_DELAYED, which means the system is withholding our audio
until it calls back. The picture rolled with no sound, indistinguishable from a
broken stream. (DR-145) -
The no-audio fallback picks a track the device can decode. When ExoPlayer
selected no audio track, recovery forced group 0 / track 0 unconditionally — but
the most likely reason nothing was selected is that this very track cannot be
decoded here, so the override reinstated the silence it was meant to fix.
(DR-146)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.4.6_amd64.deb—sudo dpkg -iWindows jellytau_0.4.6_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
-
-
JellyTau v0.4.1
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 18m39sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m40sTraceability Validation / Check Requirement Traces (push) Successful in 16sBuild & Release / Run Tests (push) Successful in 6m1s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 9m26sBuild & Release / Build Linux (push) Successful in 19m41sBuild & Release / Build Windows (push) Successful in 13m57sBuild & Release / Build Android (push) Successful in 30m6sBuild & Release / Create Release (push) Successful in 24sreleased this
2026-08-05 10:31:16 +00:00 | 246 commits to master since this release🐛 Fixes
- The lockscreen pause works while a video's audio plays in the background.
The handoff starts native audio and only then tears the WebView<video>
down — and that teardown fires a DOMpausethe frontend reports like any
other, which left the controller believing webview media was still the
player. Transport stayed aimed at it: pressing pause on the lockscreen sent a
control command to a<video>that no longer existed while the native player
carried on, and the element's parting position report dragged the displayed
time backwards. A handoff is now tracked explicitly, so it hands transport to
the native backend and ignores what the dying element still reports. A pause
made from the lockscreen also survives the return to the app, instead of being
undone by the play state captured when the handoff began.
(UR-040, UR-005 → DR-052, DR-097)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.4.1_amd64.deb—sudo dpkg -iWindows jellytau_0.4.1_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
- The lockscreen pause works while a video's audio plays in the background.
-
JellyTau v0.4.0
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 17m21sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m46sTraceability Validation / Check Requirement Traces (push) Successful in 16sBuild & Release / Run Tests (push) Successful in 5m38s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 8m54sBuild & Release / Build Linux (push) Successful in 19m22sBuild & Release / Build Windows (push) Successful in 13m55sBuild & Release / Build Android (push) Successful in 30m12sBuild & Release / Create Release (push) Successful in 15sreleased this
2026-08-04 18:22:01 +00:00 | 248 commits to master since this release✨ Features
-
Favourites, across libraries. A
/library/favoritespage renders
favourites from every library with All / Movies / Shows / Music scope tabs,
reusing the standard grid so card shape still follows the media — a mixed All
tab reads as posters, squares and thumbnails side by side. Home carries
favourite rows below Recently Added, and a row with no items does not render
at all, so a fresh install shows no empty rows. Server favourite state is
mirrored into the local database as results are cached, so offline browsing
sees the same favourites as the server; a toggle made offline is never
overwritten by a stale server value before it has been pushed.
(UR-067, UR-069 → DR-113, DR-114, DR-115, DR-117, DR-118) -
Search answers from the local index. The instant leg read only downloaded
items, so with no downloads it returned nothing and every keystroke fell
through to a fullRecursive=trueserver query. It now reads the whole synced
catalog through the same availability CTEget_itemsuses, gated on the same
include_catalog_browseflag, so search and browse cannot diverge. The index
also gained MusicArtist, Playlist and People — the very groups search sorts
results into. Re-indexing moved from a frontend startup call to a Rust
background task with a 6h TTL, so a long session no longer searches a stale
catalog. (UR-065 → DR-108, DR-110, DR-111)
🐛 Fixes
-
Playback no longer restarts an episode at random on a flaky connection.
Background audio-only playback of a video streams a progressive mp3 transcode
over plain HTTP, which is chunked and so declares no length: when the
connection dropped mid-episode, ExoPlayer saw end-of-input and reported
STATE_ENDED, indistinguishable from the real end. The app ran its
end-of-episode logic mid-episode and playback parked inSTATE_ENDED, where
the next play intent from the lockscreen, notification or a Bluetooth
reconnect seeks an ended player to position 0 — surfacing as "the episode
randomly restarted". The item's runtime is now what decides: an end reported
well short of it re-opens the stream where it stopped. (UR-040 → DR-129) -
A network hiccup no longer kills playback outright. Music and video
declare a length, so a cut connection reaches them as an error rather than a
phantom end — and every error stopped the player. A recoverable error now gets
one bounded attempt at re-opening the stream where it stopped, with a growing
backoff, leaving the rest of the queue intact. On Linux, MPV additionally
reconnects inside the demuxer so ordinary blips never surface at all, and
EndFile(ERROR)— previously a bare log line that left playback halted while
the UI still showed "playing" — is now reported and recovered.
(UR-004, UR-040 → DR-129, DR-130) -
The player no longer reads 0:00 as a track ends on Linux. MPV exposes
time-posanddurationas properties of the loaded file, so at EOF it
unloads and both stop resolving — reporting zero at exactly the moment
end-of-file handling asks where playback reached. The last reading seen while
media was loaded is now kept and used as the fallback. (UR-005 → DR-130) -
Server-side deletions propagate to the local catalog.
DELETE FROM items
existed nowhere, so items removed on the server lingered locally forever. A
post-crawl mark-and-sweep now removes them, scoped to crawled types, skipping
downloaded items, and refusing to run after a partial crawl. Separately,
items_ftsgrew a full duplicate index on every catalog pass; it is now a
real upsert, with a migration rebuilding existing indexes. (DR-110) -
Android system bars and display cutout are handled correctly. (UR-066)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.4.0_amd64.deb—sudo dpkg -iWindows jellytau_0.4.0_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
-
-
JellyTau v0.3.0
Stable🏗️ Build and Test JellyTau / Run Tests (push) Successful in 16m59sPublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m36sTraceability Validation / Check Requirement Traces (push) Successful in 18sBuild & Release / Run Tests (push) Successful in 5m9s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 8m54sBuild & Release / Build Linux (push) Successful in 18m49sBuild & Release / Build Windows (push) Successful in 14m4sBuild & Release / Build Android (push) Successful in 30m17sBuild & Release / Create Release (push) Successful in 18sreleased this
2026-08-03 18:37:49 +00:00 | 254 commits to master since this release✨ Features
- Opening a series lands on the current episode, not season 1. The viewer was
dumped at the top of season 1, and the Play button played nothing at all: it
resolved the first season by SortName and navigated to/player/<seasonId>,
which the player route bounced straight back to the library. The backend could
already answer "where is this viewer in this show" —get_next_up_episodeshad
accepted aseries_idsince it was written and no caller had ever passed one.
pick_current_episodenow resolves in progress → Next Up → first unwatched →
the premiere, with the third rung serving offline where Next Up is always empty,
and specials sorted after the numbered seasons. Seasons collapse to the current
one, the current episode is badged and scrolled into view, and the hero button
readsResume S2E4/Play S1E1. Seasons stop being a destination — a season
URL redirects into the series — and the "More Episodes" strip spans the whole
series, so a finale offers the next premiere instead of dead-ending. Six video
routes collapse to two via?view=tabs. Clear-history is wired to Jellyfin's
recursive mark-unplayed, and refuses to run offline rather than diverging state
the next sync would undo. (UR-062, UR-063, UR-064 → DR-101, DR-102, DR-103,
DR-104, DR-105, DR-106, DR-107)
🐛 Fixes
- Re-entering a video no longer opens the audio player. Closing a
webview-rendered video deliberately emits no "stopped" state — that would break
the autoplay handoff — and the direct-play path does not stop the backend on
unmount, so the controller still reported that item as its loaded media.
Re-entering took the "already playing, just show the UI" shortcut, which returns
before a stream URL is fetched, and the render fell through to the audio
surface. Mostly visible on Android, where video direct-plays; Linux transcodes
and stops the backend on unmount. (DR-100)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.3.0_amd64.deb—sudo dpkg -iWindows jellytau_0.3.0_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
- Opening a series lands on the current episode, not season 1. The viewer was
-
JellyTau v0.2.9
StablePublish Documentation / Build & publish docs to gitea-pages (push) Successful in 5m33sTraceability Validation / Check Requirement Traces (push) Successful in 25s🏗️ Build and Test JellyTau / Run Tests (push) Successful in 17m25sBuild & Release / Run Tests (push) Successful in 6m7s🏗️ Build and Test JellyTau / Android Compile Check (push) Successful in 8m38sBuild & Release / Build Linux (push) Successful in 19m23sBuild & Release / Build Windows (push) Successful in 13m43sBuild & Release / Build Android (push) Successful in 29m47sBuild & Release / Create Release (push) Successful in 19sreleased this
2026-08-02 16:10:37 +00:00 | 256 commits to master since this release🐛 Fixes
- A backgrounded audio-only episode advances instead of stalling. It stopped
at the episode boundary and ExoPlayer parked inSTATE_ENDED, where any later
play intent — lockscreen, headset, Bluetooth reconnect — replays the ended item,
surfacing as the episode randomly restarting. End-of-playback is dispatched from
two places and they disagreed: the Android JNI callback carried the
background-audio branch but can never reach it, because every load sets
EndReason::NewTrackLoadedand nothing clears it, so the first real end consumes
it and the decision is always Stop. The path that actually decides is the
frontend's echo, which had no background-audio case at all and started a
countdown whose advance is agoto()that cannot start audio while
backgrounded. Both dispatchers now share oneauto_advance_to_next_episode.
(UR-040)
Downloads
Platform File Android jellytau-release.apk— sideload oradb installWindows (portable) jellytau.exeLinux (Debian/Ubuntu) jellytau_0.2.9_amd64.deb—sudo dpkg -iWindows jellytau_0.2.9_x64-setup.exe(NSIS installer)
Report a problem: https://gitea.tourolle.paris/dtourolle/jellytau/issues
Downloads
- A backgrounded audio-only episode advances instead of stalling. It stopped