Skip to content

Add support for transcoding plex streams before playback#4615

Open
chicco-carone wants to merge 3 commits into
music-assistant:devfrom
chicco-carone:dev
Open

Add support for transcoding plex streams before playback#4615
chicco-carone wants to merge 3 commits into
music-assistant:devfrom
chicco-carone:dev

Conversation

@chicco-carone

Copy link
Copy Markdown
Contributor

What does this implement/fix?

Add support into the plex provider to let the server transcode audio before sending it to MA to reduce streaming bandwidth limits. Plex supports calling its api from a different endpoint and specifying the bitrate and codec to stream from the server to avoid always streaming the original file, this pr adds into the provider settings an option to choose either the original quality or opus at a specific bitrate. To avoid issues when updating it defaults to original which was the previous behavior and then the user if needed can change it.

Related issue (if applicable):

This issue was discussed in the MA discord server in the following thread Thread Link

Types of changes

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • New feature (non-breaking change which adds functionality) — new-feature
  • Enhancement to an existing feature — enhancement
  • New music/player/metadata/plugin provider — new-provider
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) — breaking-change
  • Refactor (no behaviour change) — refactor
  • Documentation only — documentation
  • Maintenance / chore — maintenance
  • CI / workflow change — ci
  • Dependencies bump — dependencies

Checklist

  • The code change is tested and works locally.
  • pre-commit run --all-files passes.
  • pytest passes, and tests have been added/updated under tests/ where applicable.
  • For changes to shared models, the companion PR in music-assistant/models is linked.
  • For changes affecting the UI, the companion PR in music-assistant/frontend is linked.
  • I have read and complied with the project's AI Policy for any AI-assisted contributions.
  • I have raised a PR against the documentation repository targeting the main or beta branch as appropriate.

Copilot AI review requested due to automatic review settings July 6, 2026 10:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an optional Plex-side transcoding mode so Plex streams can be delivered to Music Assistant as bandwidth-capped Opus/HLS instead of always direct-streaming the original file, plus a small HLS sub-playlist URL resolution fix.

Changes:

  • Add a Plex provider config entry (stream_quality) to choose original vs. fixed Opus bitrates (96/128/192/320 kbps).
  • Implement Plex HLS transcode URL generation and use it for music tracks, podcast episodes, and single-part audiobooks when configured.
  • Improve HLS child-playlist URL resolution (root-relative paths) and add unit tests covering the new behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/providers/plex/test_provider_methods.py Adds coverage for original vs transcoded stream details across track/podcast/audiobook cases.
tests/providers/plex/test_config_entries.py Verifies the new stream quality config entry appears (and options/defaults) across library types.
tests/controllers/streams/test_hls_substream.py Adds tests for resolving root-relative and directory-relative HLS child playlists.
music_assistant/translations/en.json Adds English translations for the new Plex stream quality config entry (generated output).
music_assistant/providers/plex/strings.json Adds localized strings/options for the new stream_quality config entry.
music_assistant/providers/plex/constants.py Introduces constants for stream quality config key and option values.
music_assistant/providers/plex/init.py Implements stream quality handling and Plex HLS transcode URL generation in stream detail methods.
music_assistant/controllers/streams/audio.py Switches HLS substream URL stitching to urljoin for correct root-relative handling.

stream_type=StreamType.HTTP,
audio_format=audio_format,
stream_type=stream_type,
duration=plex_track.duration,
@OzGav

OzGav commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@anatosun

@anatosun

anatosun commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Are you aware of this thread?

@MarvinSchenkel
MarvinSchenkel marked this pull request as draft July 7, 2026 17:37
@chicco-carone
chicco-carone marked this pull request as ready for review July 10, 2026 12:13
Copilot AI review requested due to automatic review settings July 10, 2026 12:13
@chicco-carone

Copy link
Copy Markdown
Contributor Author

I updated the pr so that if plex has the metadata to support transcoding the file it will transcode it else it will fallback the the previous behaviour for files that are not yet fully processed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

},
"stream_quality": {
"label": "Stream quality",
"description": "Audio quality to request from Plex for music tracks. Original streams the source file directly. Lower bitrates ask Plex Media Server to transcode before sending audio to Music Assistant.",
@anatosun

Copy link
Copy Markdown
Contributor

Good, have you tested the behavior on a newly added track that was not analyzed?

@chicco-carone

Copy link
Copy Markdown
Contributor Author

I haven't been able since if I add new tracks plex process them instantly and I don't even have the time to go I mass to test it. I'll see if I can slow it down somehow on my server to test

@chicco-carone

Copy link
Copy Markdown
Contributor Author

I'm completely out of ideas on how I could test it, I gave my plex container half cpu and imported a whole series with some music to hopefully slow it down but it doesn't even appear in mass in time. If you have any ideas on how I could test this I would be happy to try it to then close this but currently i'm not sure

@anatosun

Copy link
Copy Markdown
Contributor

you should defer the analysis to a scheduled task...

image

@chicco-carone

Copy link
Copy Markdown
Contributor Author

That analysis setting is only for the features used in plexamp like loudness normalization and djs and it doesn't change anything for mass since it requests the whole track the metadata that plex needs for transcoding is basically only missing when the track has no metadata (so like no album cover etc) so even with that turned off it still analyzes the metadata needed for transcoding and as such it isn't a reliable way to test it. with those 2 things disabled though it plays back fine even without analysis.
image

@anatosun

Copy link
Copy Markdown
Contributor

This task also populates the size of the track, which the streaming process requires. Without it, you'll see that it raises an error and this is where it should fallback on downloading the track.

@chicco-carone

Copy link
Copy Markdown
Contributor Author

This track i played it after disabling the analysis and adding it and it played back fine

@anatosun

Copy link
Copy Markdown
Contributor

... and it works because you have download=1 in the arguments

@chicco-carone

chicco-carone commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

In the provided example mass is playing back the track in opus which is correct per the settings that I set in the provider settings to transcode and its not falling back to download=1 since in that case it should have gotten from the server the original flac file and the playback should have been in flac not opus.
Regarding the analysis in plex like its mentioned here in the support articles https://support.plex.tv/articles/200289336-analyze-media/

Analysis is automatically performed when content is added to your Library.

And its separate from the sonic analysis that you can disable in the settings For what this pr covers the transcode works fine and if there is no metadata it fallbacks to the original file works fine

@anatosun

Copy link
Copy Markdown
Contributor

My server does not behave this way. The size of the file is populated only after the scheduled analysis.

But you seem to say that the fallback to the original could be tested?

@chicco-carone

Copy link
Copy Markdown
Contributor Author

I'm not sure how to test this in my current environment since I can't reproduce the edge case that would cause this problem. That said here in the code where it decides to transcode or not if any of the checks in the if fail for any possible reason (like plex not having the metadata) it will fallback to using download=1 which is already proven by #3561 to work in those specific cases.

if (quality_bitrate := self._get_stream_quality_bitrate()) and audio_stream:
    stream_details.path = self._get_transcode_url(plex_track, quality_bitrate)
    stream_details.stream_type = StreamType.HLS
    stream_details.audio_format.content_type = ContentType.OPUS
    stream_details.audio_format.bit_rate = quality_bitrate
    return stream_details

download_url = self._plex_server.url(f"{media_part.key}?download=1", True)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants