Skip to content

fix: refactor playback #69

Merged
lostb1t merged 16 commits into
mainfrom
#67
Jun 29, 2026
Merged

fix: refactor playback #69
lostb1t merged 16 commits into
mainfrom
#67

Conversation

@lostb1t

@lostb1t lostb1t commented Jun 28, 2026

Copy link
Copy Markdown
Owner

fixes #67

@github-actions

Copy link
Copy Markdown
Contributor

Docker image built for this PR and pushed to GitHub Container Registry.

docker pull ghcr.io/lostb1t/remux:pr-69

Image will be removed when this PR is closed or merged.

@lostb1t lostb1t changed the title fix: transcode video on unsupported embedded subtitles fix: transcode video on unsupported embedded subtitles (#67) Jun 28, 2026
@lostb1t lostb1t changed the title fix: transcode video on unsupported embedded subtitles (#67) fix: refactor playback Jun 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes web-client playback behavior where selected audio/subtitle tracks don’t stick by stabilizing stream resolution (especially for StreamGroups), improving codec normalization, and refining embedded-subtitle handling/delivery.

Changes:

  • Introduces a StreamResolver service to consistently map client-facing IDs (item/stream/group UUIDs) to the correct playable db::Media.
  • Normalizes audio/video/subtitle codec handling via typed enums and updates probing/transcode logic accordingly.
  • Adds configurable embedded subtitle handling (Burn/Extract/Strip), plus background subtitle pre-extraction and cache usage to reduce on-demand FFmpeg contention.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
Makefile.toml Lowers remux_server::request log verbosity from debug to info.
crates/remux-server/src/transcode/probing.rs Uses typed codec enums for display and stream classification (text vs image subtitles).
crates/remux-server/src/transcode/engine.rs Replaces ad-hoc codec matching with typed codec checks for HEVC and AAC ADTS handling; adds subtitle burn-in comments.
crates/remux-server/src/services/stream_resolve.rs Adds centralized stream/group resolution and device preference persistence.
crates/remux-server/src/services/mod.rs Exposes StreamResolver in the services module.
crates/remux-server/src/device_profile.rs Adds typed AudioCodec/VideoCodec enums, expands SubtitleCodec, and consolidates codec matching.
crates/remux-server/src/conversions.rs Populates default_audio_stream_index / default_subtitle_stream_index from probe data in MediaSourceInfo.
crates/remux-server/src/api/subtitles.rs Adds subtitle pre-extraction + cache coordination to reduce competing FFmpeg work and improve subtitle delivery.
crates/remux-server/src/api/playback.rs Refactors playbackinfo/stream endpoints to use StreamResolver, adds subtitle-mode handling, and adjusts subtitle delivery decisions.
crates/remux-server/src/api/hls.rs Minor refactor to reuse computed burn_subtitle flag.
crates/remux-sdks/src/remux/mod.rs Adds EmbeddedSubtitleHandling setting with defaults and tests.
crates/remux-dashboard/src/pages/settings.rs Adds UI to configure unsupported embedded subtitle handling mode.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +176 to +194
// -y: overwrite without prompting (hangs forever waiting for stdin otherwise)
// -nostdin: don't read from stdin at all
// -c:s copy: copy subtitle packets as-is (same as Jellyfin, much faster than re-encoding)
cmd.args(["-y", "-nostdin", "-i", &input_url]);
for (idx, path) in &to_extract {
if let Some(p) = path.to_str() {
cmd.args([
"-map",
&format!("0:{idx}"),
"-an",
"-vn",
"-c:s",
"copy",
"-flush_packets",
"1",
p,
]);
}
}
Comment thread crates/remux-server/src/api/playback.rs Outdated
.data_dir
.clone();
let url = input_url.clone();
let msid = sm.id;
Comment thread crates/remux-server/src/api/playback.rs Outdated
Comment on lines +707 to +708
.any(|f| f.eq_ignore_ascii_case(codec))
})
Comment on lines +872 to +875
let client_can_handle_image = is_image_sub
&& (profile_supports(SubtitleCodec::Pgs)
|| profile_embeds(SubtitleCodec::Pgs));
if !stream.is_external
@lostb1t lostb1t merged commit 5d96e80 into main Jun 29, 2026
9 checks passed
@lostb1t lostb1t deleted the #67 branch June 29, 2026 10:22
@lostb1t lostb1t restored the #67 branch June 29, 2026 10:25
github-actions Bot pushed a commit to jsanderstechnologies/remux that referenced this pull request Jun 29, 2026
# 1.0.0 (2026-06-29)

### Bug Fixes

* add default tmdb key ([501e6b8](501e6b8))
* add music kinds to the media refresh task ([d62f2ea](d62f2ea))
* add playback percentage to userdata ([6ef206a](6ef206a))
* add vaapi docker packages and give qsv higher prio then vaapi ([1be17ab](1be17ab))
* always re-encode audio to AAC in HLS transcoding ([aa1444e](aa1444e))
* android tv playback ([df23949](df23949))
* apply release filter to nextup ([lostb1t#35](https://github.com/jsanderstechnologies/remux/issues/35)) ([lostb1t#38](https://github.com/jsanderstechnologies/remux/issues/38)) ([78472b3](78472b3))
* auth for jellyfin desktop ([0f644e6](0f644e6))
* client fixes ([lostb1t#12](https://github.com/jsanderstechnologies/remux/issues/12)) ([3dea5ec](3dea5ec))
* deezer track numbers ([133f099](133f099))
* delete shows ([073bc76](073bc76))
* deleted segments regardless of extension ([7052375](7052375))
* docker hw packages ([ab7ad5c](ab7ad5c))
* duplicate persons ([ad35109](ad35109))
* enable download flag ([3ddf38d](3ddf38d))
* external id field serialization ([c314013](c314013))
* external subtitles for web ([aa335f1](aa335f1))
* fix corrupted external_ids case ([15a7e40](15a7e40))
* fix optional fields ([f970df4](f970df4))
* fix userdata not saving correctly and implement resume endpoints ([1c3daef](1c3daef))
* force h264 for encoding ([2619ead](2619ead))
* force meta refresh on catalog import so configured meta providers are always applied ([deb167e](deb167e))
* force nextup active-series join order ([lostb1t#26](https://github.com/jsanderstechnologies/remux/issues/26)) ([fefccdf](fefccdf))
* give catalog filter its onw field ([9331d3f](9331d3f))
* handle progress reports without play session id ([lostb1t#29](https://github.com/jsanderstechnologies/remux/issues/29)) ([5833a3f](5833a3f))
* hide catalog tags ([7a04651](7a04651))
* hide recent theatrical-only movies until digital release confirmed ([e4f7eb1](e4f7eb1))
* **hls:** serve ffmpeg playlist for resumed ts-hls ([lostb1t#43](https://github.com/jsanderstechnologies/remux/issues/43)) ([66c1ed1](66c1ed1))
* **hls:** use EXT-X-START for resumed TS-HLS instead of ffmpeg playlist ([lostb1t#51](https://github.com/jsanderstechnologies/remux/issues/51)) ([8ca8fd3](8ca8fd3))
* **images:** proxy external image URLs instead of redirecting ([6076c56](6076c56))
* implement tree trait to tmdb addon ([a56c8ba](a56c8ba))
* import local TV when source advertises an Episode catalog ([lostb1t#64](https://github.com/jsanderstechnologies/remux/issues/64)) ([bce45dd](bce45dd))
* infuse fixes ([4c0cf2e](4c0cf2e))
* inherit runtime from ([a7a53cb](a7a53cb))
* libraries not showing when a user has filters ([4422031](4422031))
* loosen up digital release date filter ([5662a85](5662a85))
* lower upsert chunk limit ([3437d92](3437d92))
* make sure to load streams on audio endpoints ([0865b82](0865b82))
* missing channel guides ([e9bf908](e9bf908))
* missing enum variants ([336f0f4](336f0f4))
* missing intro endpoint ([11cf16d](11cf16d))
* missing streams for local episodes ([722244f](722244f))
* music genres  ([#78](https://github.com/jsanderstechnologies/remux/issues/78)) ([eaa88ec](eaa88ec))
* nextup images ([3426268](3426268))
* nextup was missing imported nedia [lostb1t#14](https://github.com/jsanderstechnologies/remux/issues/14) ([5ec7471](5ec7471))
* nissing migrations ([26fb94e](26fb94e))
* **opendal:** derive episode series title from directory when filename starts with episode code ([5af1f62](5af1f62))
* optimize iptv purge ([4c64a89](4c64a89))
* order continue watching by play date ([lostb1t#19](https://github.com/jsanderstechnologies/remux/issues/19)) ([17ac545](17ac545))
* override collection sort when SortName appears anywhere in sort list ([c1231d4](c1231d4))
* pass --repo to gh release create to avoid missing git context ([99ad721](99ad721))
* people metadata ([80738ab](80738ab))
* persist probe data between stream refresh ([f4212dd](f4212dd))
* playlist crud ([7bb0d7b](7bb0d7b))
* prevent squash migration from re-running on every restart ([lostb1t#36](https://github.com/jsanderstechnologies/remux/issues/36)) ([7c80a12](7c80a12))
* query paramaters wrongly encoded resulting in wrong tmdb calls ([ef0ef77](ef0ef77))
* quickconnect ([3e541a7](3e541a7))
* refactor playback  ([lostb1t#69](https://github.com/jsanderstechnologies/remux/issues/69)) ([5d96e80](5d96e80))
* remove country code from parental rating ([df88ea6](df88ea6))
* report transcode info for remux sessions ([4b9d640](4b9d640))
* respect enable_user_data and normalize NextUp cutoff handling ([lostb1t#21](https://github.com/jsanderstechnologies/remux/issues/21)) ([9270125](9270125))
* return empty when includeItemTypes doesn't match collection content type ([a7f0d5b](a7f0d5b))
* revert item creation to 0.25 ([5278589](5278589))
* scheduler not triggering ([2d00040](2d00040))
* **sessions:** populate SeriesName and SeasonName in NowPlayingItem ([lostb1t#62](https://github.com/jsanderstechnologies/remux/issues/62)) ([d526ebd](d526ebd))
* set DeliveryUrl on subtitle streams, respect device profile ([ac6c83b](ac6c83b))
* several EPG fixes ([42ce21c](42ce21c))
* skip unreleased episodes when marking season/series played with release filter enabled ([lostb1t#41](https://github.com/jsanderstechnologies/remux/issues/41)) ([lostb1t#42](https://github.com/jsanderstechnologies/remux/issues/42)) ([e0ecd2d](e0ecd2d))
* stream group lookup ([34ecf5e](34ecf5e))
* **subtitles:** honor codec aliases in playback decisions ([lostb1t#44](https://github.com/jsanderstechnologies/remux/issues/44)) ([5c72159](5c72159))
* test ([9c336d3](9c336d3))
* **transcode:** only apply dovi_rpu bsf for confirmed Dolby Vision streams ([lostb1t#50](https://github.com/jsanderstechnologies/remux/issues/50)) ([20a3071](20a3071))
* use source bitrate as encoding target, cap at max_streaming_bitrate ([d17203e](d17203e))
* **web:** fix stream loading flicker on playback ([e0e4cc0](e0e4cc0))
* **web:** race conditions in async stream handling ([5fd3f2f](5fd3f2f))
* **web:** strip Recently Added inu prefix from homescreen row titles ([4413464](4413464))
* wip ([28cd9b2](28cd9b2))
* wip ([fda6e10](fda6e10))
* wip ([328107f](328107f))
* wip ([a506219](a506219))
* wip ([df3ba0f](df3ba0f))
* wip ([bf2e817](bf2e817))
* wip ([22a3f2a](22a3f2a))
* wip ([0a4604d](0a4604d))
* wip ([b33d11d](b33d11d))
* wip ([9e25d89](9e25d89))
* wip ([5b6f649](5b6f649))
* wip ([6af5e1a](6af5e1a))
* wip ([abc00df](abc00df))
* wip ([2a5f986](2a5f986))
* wip ([88b116e](88b116e))
* wip ([3919ec3](3919ec3))
* wip ([041fa19](041fa19))
* wip ([a16e0eb](a16e0eb))
* wip ([db0f091](db0f091))
* wip ([c0673b7](c0673b7))
* wip ([0b35965](0b35965))
* wrong timestamps for date fields ([865a189](865a189))
* wrongly returning zero on items list with results ([d1125f1](d1125f1))

### Features

* add clear cache task ([afcff08](afcff08))
* add clear image cache task ([62834be](62834be))
* add Deezer SDK to remux-sdks ([ae90995](ae90995))
* add descriptions to tasks ([2f4f655](2f4f655))
* add destructive flag to Task trait with confirmation modal for purge tasks ([3541250](3541250))
* add dual web-client flow and Anfiteatro release installer ([lostb1t#24](https://github.com/jsanderstechnologies/remux/issues/24)) ([a7fea9a](a7fea9a))
* Add eclipse spotiFLAC and Monochrome addons ([#77](https://github.com/jsanderstechnologies/remux/issues/77)) ([2cf26b8](2cf26b8))
* add filter rule groups with AND/OR nesting ([lostb1t#55](https://github.com/jsanderstechnologies/remux/issues/55)) ([3bbadb9](3bbadb9))
* add Jellyfin SDK-compatible user config route ([#89](https://github.com/jsanderstechnologies/remux/issues/89)) ([02414e9](02414e9))
* add max stream and remote search settings to user ([cdfeb90](cdfeb90))
* Add option to disable video transcoding ([#76](https://github.com/jsanderstechnologies/remux/issues/76)) ([8ea1f71](8ea1f71))
* add recommendations endpoints ([#83](https://github.com/jsanderstechnologies/remux/issues/83)) ([57b8226](57b8226))
* add sort and filter options for latest endpoints ([lostb1t#75](https://github.com/jsanderstechnologies/remux/issues/75)) ([424e3b0](424e3b0))
* add support for mixed (movie and shows) collections ([lostb1t#54](https://github.com/jsanderstechnologies/remux/issues/54)) ([620c6c3](620c6c3))
* add support for rtsp streams ([19013f7](19013f7))
* add TMDB popular, top rated and trending catalogs ([f5c5820](f5c5820))
* add TMDB watch provider tags to movie and series metadata ([737fb03](737fb03))
* add tonemapping packages for intel and more robust hw device detection ([62df8f7](62df8f7))
* adding remote control endpoints and subtitle search endpoints ([#82](https://github.com/jsanderstechnologies/remux/issues/82)) ([8c31373](8c31373))
* clear addon indexes on purge ([1985249](1985249))
* **deezer:** surface playlists as real Jellyfin playlists ([lostb1t#60](https://github.com/jsanderstechnologies/remux/issues/60)) ([906cc36](906cc36))
* downloads uses filename if avaiable ([1afc5f9](1afc5f9))
* extend TMDB search addon to support Movie and Series kinds ([fc6e62e](fc6e62e))
* extend user filters form ([95bbc5a](95bbc5a))
* fallback to tmdb id if imdb does not resolve for stremio ([12c6ac4](12c6ac4))
* force plezy to reload versions ([4855d56](4855d56))
* HW acceleration ([lostb1t#61](https://github.com/jsanderstechnologies/remux/issues/61)) ([fe7c0ac](fe7c0ac))
* image support including avatars and auto generated collection images ([lostb1t#62](https://github.com/jsanderstechnologies/remux/issues/62)) ([6bee985](6bee985))
* implement /Items/{id}/Similar endpoint ([#87](https://github.com/jsanderstechnologies/remux/issues/87)) ([e765b3e](e765b3e))
* Implement AudioLanguagePreference and RememberAudioSelections user settings ([46d1284](46d1284))
* implement client log endpoint ([b884edc](b884edc))
* import media during jellyfin favorites sync ([#79](https://github.com/jsanderstechnologies/remux/issues/79)) ([bf3d44b](bf3d44b))
* intro support ([lostb1t#32](https://github.com/jsanderstechnologies/remux/issues/32)) ([lostb1t#39](https://github.com/jsanderstechnologies/remux/issues/39)) ([ba23b31](ba23b31))
* Mark parents played if all episodes are played and vice versa ([lostb1t#71](https://github.com/jsanderstechnologies/remux/issues/71)) ([9e515d4](9e515d4))
* **meta:** Added language, studios and production locations including filters ([lostb1t#52](https://github.com/jsanderstechnologies/remux/issues/52)) ([9b779d4](9b779d4))
* migrate to FFmpeg-based probing and transcoding, fix seeking ([b261008](b261008))
* Music ([lostb1t#26](https://github.com/jsanderstechnologies/remux/issues/26)) ([2729992](2729992))
* per user stream filter ([718135b](718135b))
* popularity metrics ([lostb1t#57](https://github.com/jsanderstechnologies/remux/issues/57)) ([2b8df7b](2b8df7b))
* seek ([lostb1t#19](https://github.com/jsanderstechnologies/remux/issues/19)) ([59667be](59667be))
* set default internet quality for jellyfin web to auto ([4c7bc9c](4c7bc9c))
* set sane homescreen defaults ([9acb85d](9acb85d))
* stream fallback ([lostb1t#63](https://github.com/jsanderstechnologies/remux/issues/63)) ([dd9c1ad](dd9c1ad))
* stream groups ([lostb1t#64](https://github.com/jsanderstechnologies/remux/issues/64)) ([1854c4a](1854c4a))
* support multiple paths in opendal addons ([6e6995e](6e6995e))
* trakt addon with metrics ([lostb1t#65](https://github.com/jsanderstechnologies/remux/issues/65)) ([ed6ee58](ed6ee58))
* use proper parsing library for local files and support external id markers ([b24162f](b24162f))
* user avatar support ([dbb76f2](dbb76f2))

### Performance Improvements

* add composite index on media_relations(left_media_id, weight) ([0aa7077](0aa7077))
* **images:** use sized TMDB image variants and populate ImageTags.Thumb ([9f6c4a5](9f6c4a5))
* load streams async on item details page for web ([lostb1t#47](https://github.com/jsanderstechnologies/remux/issues/47)) ([9fcbd8d](9fcbd8d))
* skip relations batch-load when Fields doesn't include People/Genres/Studios ([b5d6775](b5d6775))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to change audio track or subtitles in web client

2 participants