Commit Graph

2177 Commits

Author SHA1 Message Date
unkin-agent 56919b9565 fix(devices): read devices and device options through to the database
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/pr/ci Pipeline was successful
The device cache was filled once at construction, so a token minted by one
replica was unknown to every other replica already running and a token revoked
on one replica stayed valid on the others until they restarted.

- drop the eager device and device options dictionaries
- read devices and device options from the database on every query
- push the device query filters and ordering into SQL
- open the request's database context only for the api key fallback
- cover both directions against real PostgreSQL with two manager instances
2026-09-13 13:08:47 +10:00
unkin-agent baa16b6586 fix: make transcode leases ownership-checked and cleanup-aware
Cleanup never matched a live session because the controller registered empty
manifest and segment paths, renewal was a read-modify-write that could revert a
takeover, and the takeover script compared an ISO date to a number, so it errored.

- populate the session record's manifest and segment paths from the playlist path
- renew the lease via a Lua compare-and-set on the owning pod
- store the lease expiry as unix milliseconds so the scripts can compare it
- retain the session record past its lease so an orphan can still be taken over
- test the Redis store against a real Redis, including the renew-vs-takeover race
- drop the live stream record nothing ever read back
2026-09-12 10:19:29 +10:00
unkin-agent 6ccabd4c72 feat(hls): register transcode sessions and renew their lease
A transcode that is not in the store is invisible to the other replicas, so the
HLS entry points have to publish and hold the lease themselves.

- register the play session in the store when ffmpeg starts
- renew the lease on a background loop and delete the session when it ends
- shorten segments and bound the playlist window when resuming a stored session
- add RecoverySegmentLengthSeconds and RecoverySegmentBufferCount encoding options
2026-09-11 23:56:35 +10:00
Cody Robibero 3e7d1158da Merge pull request #17794 from Shadowghost/plugin-install-fixes
Better handle timeouts on plugin operations
2026-09-06 12:47:45 -04:00
Cody Robibero 34feb3c04a Merge pull request #17763 from Shadowghost/fix-refresh-queue-and-directory-cache
Fix items being lost from the refresh queue and bound the directory service caches
2026-09-06 07:36:13 -04:00
Shadowghost 344a6dcd2c Apply review suggestions 2026-09-06 08:38:43 +02:00
gnattu a1910a7b2e Enforce dolby vision transfer check
Dolby vision files having unexpected transfers now also marked as invalid, and it will now get its base video range from its base layer color transfer, as not all invalid dolby vision files are HDR now.
2026-09-06 02:53:52 +08:00
Shadowghost 9221e22498 Do not resolve bundled plugins via repos 2026-09-05 20:01:09 +02:00
Shadowghost 46dd7d8e99 Invalidate the singleton DirectoryService cache on filesystem changes 2026-09-04 19:28:59 +02:00
Shadowghost b724e57458 Reduce comments 2026-09-03 11:51:02 +02:00
Shadowghost d73e3d964e Optimize Caches
Co-Authored-By: Cody Robibero <cody@robibe.ro>
2026-09-02 07:06:08 +02:00
zerafachris 20678c9a8c fix: return fallback gracefully when requested fallback font is missing
GetFallbackFont() called .First() on the font file sequence, which throws
System.InvalidOperationException when no file matched the requested name,
causing HTTP 500. Change to .FirstOrDefault() so a missing font falls
through to the existing null guard and returns HTTP 200 OK (the empty
response is intentional to avoid breaking SubtitlesOctopus).

Fixes #17683.

Prepared with AI assistance (Claude Code, Anthropic), reviewed for correctness before submission.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-01 16:25:59 +02:00
Cody Robibero 80324b19fb Merge pull request #17724 from Shadowghost/fix-by-name-item-counts
Fix item counts on the by-name endpoints
2026-08-31 15:19:08 -04:00
Cody Robibero 420d44f638 Merge commit from fork
Fix broken access control in session management
2026-08-30 14:40:25 -04:00
Cody Robibero 9fe5a53e47 Merge commit from fork
Secure library paths
2026-08-30 14:40:16 -04:00
Shadowghost ceeeaaab8e Fix By-Name item count handling 2026-08-27 10:19:36 +02:00
Shadowghost 0c560b22ce Secure library paths 2026-08-25 09:28:45 +02:00
Shadowghost 911ac3769c Fix GHSA-9x85-gx46-6522 2026-08-23 19:20:58 -04:00
Shadowghost 090b610eb1 Fix person metadata not being fetched on demand or by the people task 2026-08-23 09:27:26 +02:00
Cody Robibero 49112163eb Merge pull request #17584 from Shadowghost/safeguard-invalid-provider-ids
Safeguard against invalid provider ids
2026-08-22 08:49:07 -04:00
Shadowghost 42c70fba63 Additional fixes
Co-Authored-By: Cody Robibero <cody@robibe.ro>
2026-08-22 08:50:14 +02:00
Cody Robibero 9ba91d4583 Normalize fix, apply in more places 2026-08-20 18:10:50 -04:00
Shadowghost 4de43d36dd Require session ownership for additional users, capabilities and viewing reports 2026-08-14 14:50:07 +02:00
Cody Robibero f9b7f2edf7 Merge pull request #17536 from gnattu/fix-concurrent-racing
Fix concurrent ffmpeg segment racing
2026-08-07 21:38:45 -04:00
Cody Robibero 17b0453cfb Merge pull request #17466 from Shadowghost/fix-byname-queries
Improve People deduplication, fix search and restrict ItemByName responses
2026-08-05 18:39:55 -04:00
vdatanet 3578e9a332 Fix PCM audio transcoding to wav returning HTTP 500 and headerless output
`GetProgressiveAudioFullCommandLine` forced the raw PCM muxer and a bogus
sample rate whenever the audio encoder was `pcm_*`, regardless of the
container the client asked for. Two separate failures came out of it:

- `-ar ` + `state.BaseRequest.AudioBitRate` used a *bitrate* as a *sample
  rate*, and `AudioBitRate` is optional. When it is absent the argument
  degrades to a bare `-ar`, ffmpeg aborts with `Expected number for ar but
  found: -ar` / `Error opening output files: Invalid argument` (exit 234)
  and the request fails with HTTP 500. Every `GET /Audio/{id}/stream.wav`
  that does not carry an explicit `AudioBitRate` hits this.
  The sample rate was already being set correctly a few lines below from
  `OutputAudioSampleRate`, so the line is dropped rather than repaired.

- `-f s16le` overrode the muxer even for a real container. A request that
  did supply a bitrate (`/Audio/{id}/universal` passes
  `MaxStreamingBitrate`) survived the first bug but produced raw headerless
  samples served under an `audio/wav` content type, so clients saw a body
  with no RIFF header. The raw muxer is now only forced when the requested
  container is actually raw PCM, which keeps the I2S/MCU route from #10321
  working.

Also drop the `containerInternal = ".pcm"` assignment in
`StreamingHelpers.GetStreamingState`: it is written after
`state.OutputContainer` has already been read from the same variable and is
never read again, so it has no effect and only obscures where the output
container comes from.

Verified against ffmpeg 8.1.2 with a 96 kHz FLAC source: before, the wav
command line exits 234; after, it produces a valid `RIFF/WAVE` 48 kHz stereo
`pcm_s16le` file, while the raw `.pcm` route still yields exactly
2 s x 48000 x 2ch x 2 B = 384000 bytes of headerless samples.
2026-08-04 19:52:29 +02:00
gnattu e2586eed9b Fix concurrent ffmpeg segment racing
This is a nasty one. The failure mode is:

1. Request A started FFmpeg and waited for a segment.
2. Request B requested an earlier or far away segment.
3. Jellyfin thought FFmpeg should to restart at a different position.
4. Request B killed the existing transcoding job.
5. Killing that job cancelled the same token request A was using.
6. The cancellation produced http 500 to request A.

To fix this:

we lock transcoding job state changes and segment handling per playlist, and use a thread safe counter to track how many http responses are still using each job’s segments. A job is only stopped or replaced once that counter reaches zero.
2026-08-05 00:33:42 +08:00
Shadowghost 8044534774 Merge remote-tracking branch 'upstream/master' into fix-byname-queries 2026-08-02 22:12:57 +02:00
Cody Robibero f865910a90 Merge pull request #17298 from WizardOfYendor1/fix/livetv-published-stream-urls
Fix Live TV returning unreachable "server-local" streaming URLs to clients.
2026-08-02 14:23:49 -04:00
Shadowghost 705368ee49 Merge remote-tracking branch 'upstream/master' into fix-byname-queries
# Conflicts:
#	src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs
2026-08-01 21:41:16 +02:00
Cody Robibero c55fde25a5 Merge pull request #17501 from alchemyyy/fix/skip-sidx-fmp4-hls
Skip SIDX in fMP4 HLS segments
2026-08-01 08:07:42 -04:00
alchemyyy 893662ba50 Skip SIDX in fMP4 HLS segments
Prevent FFmpeg's SIDX path from rewriting open-GOP boundary packet timestamps. HLS uses the media playlist for segment indexing and does not require the SIDX box.
2026-07-30 17:19:45 -07:00
Shadowghost 9a258c089d Restrict people, genres, studios and artists to names backed by an item the user can access 2026-07-28 21:28:56 +02:00
Shadowghost 046225654a Queue person metadata refresh instead of blocking the item request and fix ItemCounts 2026-07-27 23:09:30 +02:00
Cody Robibero 526f4051e9 Merge pull request #16980 from TheMelmacian/feature/library_specific_language_filter_values
Improve language filters to only fetch language codes that match the requested items/libraries (follow up to #9787)
2026-07-21 20:43:31 -04:00
Cody Robibero 635fd0433d Merge pull request #17370 from zerafachris/fix/item-update-null-optional-fields
fix: don't throw ArgumentNullException on partial UpdateItem payloads (#17366)
2026-07-21 18:17:22 -04:00
Cody Robibero 370170bab0 Merge pull request #17369 from Shadowghost/harden-startup-wizard
Prevent unauthenticated re-run of the startup wizard on misconfiguration
2026-07-21 18:17:08 -04:00
zerafachris 53e58d8b1b Make ItemUpdateController.UpdateItem internal instead of reflection
Addresses review feedback from @Bond-009 on PR #17370: the test helper
InvokeUpdateItem was invoking the private UpdateItem(BaseItemDto, BaseItem)
method via reflection. Jellyfin.Api.csproj already grants
InternalsVisibleTo("Jellyfin.Api.Tests"), so the method is changed to
internal and the test now calls it directly, removing the
GetMethod/Invoke boilerplate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 08:51:30 +02:00
Shadowghost b99703301f Merge remote-tracking branch 'upstream/master' into security-path-traversal-fixes
# Conflicts:
#	Jellyfin.Api/Controllers/HlsSegmentController.cs
#	Jellyfin.Api/Controllers/PluginsController.cs
2026-07-21 07:14:47 +02:00
Cody Robibero fae1e4c556 Merge pull request #17324 from damienmeur/refactor/generic-getorderby
Make RequestHelpers.GetOrderBy generic and reuse it in ActivityLogController
2026-07-20 19:52:10 -04:00
Bond-009 abb35571ef Merge pull request #17252 from theguymadmax/fix-alubms-and-artists
Fix artists being displayed with albums
2026-07-20 12:20:49 +02:00
TheMelmacian 7d83779b6f fix code style 2026-07-18 17:56:38 +02:00
Bond-009 9b5f830462 Merge pull request #17326 from theguymadmax/update-series-name
Update season and episode SeriesName when renaming a series
2026-07-17 22:06:26 +02:00
Bond-009 42f9ed76c0 Merge pull request #17280 from Shadowghost/remove-image-override-hack
Remove episode image override hack
2026-07-17 22:06:07 +02:00
Bond-009 69faa6c583 Merge pull request #17191 from IDisposable/fix/handler-path-traversal
Fix path transversal exposure in Plugins
2026-07-17 21:52:22 +02:00
WizardOfYendor1 97e666c566 Append base URL if the published server URL override omits it. Fleshed out unit tests to cover that and https->http reverse proxy scenario(s). 2026-07-17 14:59:46 -04:00
zerafachris 5cd3d7ebb7 fix: don't throw ArgumentNullException on partial UpdateItem payloads (#17366)
BaseItemDto.Genres, .Tags, and .ProviderIds are plain auto-properties with
no default initializer, so they deserialize to null when a client omits
them from a partial POST /Items/{itemId} body. The OpenAPI spec documents
every BaseItemDto field as optional, but ItemUpdateController.UpdateItem
fed these three properties straight into Distinct()/Select()/ToList()
without a null check, so a request that (for example) only sets Tags
throws ArgumentNullException("source") once it reaches the unguarded
Genres line, before Tags is even processed.

Guard all three assignments with the same "if (request.X is not null)"
pattern already used for the neighboring Studios/Taglines/ProductionLocations
fields in this method, so omitted fields are left unchanged instead of
crashing the request.

Adds ItemUpdateControllerTests covering the reported repro (only Tags
supplied) and a companion case asserting existing Genres/ProviderIds are
preserved when omitted from the payload.

Signed-off-by: zerafachris <christopher.zerafa@blocklabs.io>
2026-07-17 17:20:30 +02:00
Shadowghost 62a5ded920 Prevent unauthenticated re-run of the startup wizard on misconfiguration 2026-07-17 17:14:27 +02:00
Shadowghost 21801e8ba1 Harden remaining path-construction sinks against traversal 2026-07-17 17:08:59 +02:00
theguymadmax fa4626c080 Revert setting default BaseItemKind for CollectionType 2026-07-16 18:15:54 -04:00