Skip to content

Allows selecting the audio language in the MPD manifest proxy. - #283

Open
andrestardito wants to merge 1 commit into
mhdzumair:mainfrom
andrestardito:feature/select-audio-language-mpd
Open

Allows selecting the audio language in the MPD manifest proxy.#283
andrestardito wants to merge 1 commit into
mhdzumair:mainfrom
andrestardito:feature/select-audio-language-mpd

Conversation

@andrestardito

@andrestardito andrestardito commented Jun 18, 2026

Copy link
Copy Markdown

This change was introduced to avoid the need for users to repeatedly select their preferred audio track in the player. This is especially useful when English is not the users' primary language.

Summary by CodeRabbit

  • New Features

    • Added audio language selection for DASH manifests using BCP 47 language tags with automatic fallback to highest-bandwidth audio when exact match unavailable.
    • Added audio language input field to the URL generator tool.
  • Documentation

    • Added "DASH Stream with Audio Selection" example demonstrating language selection.
    • Documented the new audio language parameter with default behavior and supported endpoints.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds an audio_lang BCP 47 query parameter to the MPD manifest proxy. MPDManifestParams gains the field; process_manifest and build_hls are updated to accept and apply it, replacing hardcoded English preference with a prefix-match filter and highest-bandwidth fallback. Both DRM and non-DRM branches in get_manifest pass the value through. The URL generator UI and docs are updated accordingly.

Changes

audio_lang selection for DASH/MPD proxying

Layer / File(s) Summary
Schema field and audio selection logic
mediaflow_proxy/schemas.py, mediaflow_proxy/mpd_processor.py
MPDManifestParams adds audio_lang (default "en"). process_manifest accepts and forwards the parameter. build_hls replaces the hardcoded English filter with a lang-prefix match against audio_lang, falling back to highest-bandwidth audio when no profiles match.
Handler wiring, URL generator UI, and docs
mediaflow_proxy/handlers.py, mediaflow_proxy/static/url_generator.html, docs/usage/url-params-and-encoding.md, docs/usage/examples.md
Both DRM and non-DRM branches of get_manifest pass manifest_params.audio_lang to process_manifest. The MPD proxy form gains an audio language text input that appends audio_lang to generated URLs. Docs add the parameter reference and an mpv DASH audio selection example.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A language to pick, not just "en" by default,
Now Spanish or French won't be lost in the vault.
The BCP tag hops in with a prefix-matched cheer,
Falls back to bandwidth if no match appears here.
One param to rule all the audio tracks — hooray!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Allows selecting the audio language in the MPD manifest proxy' directly and clearly describes the main feature addition, matching the primary change across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@mediaflow_proxy/mpd_processor.py`:
- Around line 492-493: The language matching logic at line 492 uses a simple
startswith comparison that fails to handle case-insensitive matching and
hierarchical BCP-47 language tag matching. To fix this, normalize both the
audio_lang parameter and the profile language code to lowercase for comparison,
then implement a three-tier matching strategy: first filter default_audio to
include profiles that exactly match the normalized audio_lang, then also include
profiles whose primary language component (before the hyphen) matches the
audio_lang primary component, and finally fall back to bandwidth selection from
the combined list. This ensures that a request for audio_lang like "es-AR"
properly matches both exact "es-ar" tracks and generic "es" tracks before using
bandwidth as a tiebreaker.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d6374e9d-8b34-4449-9313-a105d5c73ca3

📥 Commits

Reviewing files that changed from the base of the PR and between e88bf61 and 94d4538.

📒 Files selected for processing (6)
  • docs/usage/examples.md
  • docs/usage/url-params-and-encoding.md
  • mediaflow_proxy/handlers.py
  • mediaflow_proxy/mpd_processor.py
  • mediaflow_proxy/schemas.py
  • mediaflow_proxy/static/url_generator.html

Comment on lines +492 to +493
default_audio = [(p, u) for p, u in all_audio if (p.get("lang") or "").startswith(audio_lang)]
default_profile, _ = max(default_audio or all_audio, key=lambda pu: pu[0].get("bandwidth", 0))

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Regional language requests can select the wrong default audio.

Line 492 only checks profile_lang.startswith(audio_lang), so audio_lang=es-AR will not match a generic es track and may fall back to a different language by bandwidth. Normalize case and implement hierarchical BCP-47 matching (exact → primary-language compatible → bandwidth fallback).

💡 Suggested fix
-    default_audio = [(p, u) for p, u in all_audio if (p.get("lang") or "").startswith(audio_lang)]
+    req_lang = (audio_lang or "en").strip().lower()
+    req_primary = req_lang.split("-")[0]
+
+    def _lang_match(profile_lang: str) -> tuple[int, int]:
+        # score: 2 exact, 1 primary-language compatible, 0 no match
+        pl = (profile_lang or "").strip().lower()
+        if pl == req_lang:
+            return (2, 0)
+        pl_primary = pl.split("-")[0] if pl else ""
+        if pl and (pl.startswith(req_lang + "-") or req_lang.startswith(pl + "-") or pl_primary == req_primary):
+            return (1, 0)
+        return (0, 0)
+
+    scored = [
+        (p, u, _lang_match(p.get("lang")))
+        for p, u in all_audio
+    ]
+    matched = [(p, u) for p, u, score in scored if score[0] > 0]
+    default_audio = matched
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@mediaflow_proxy/mpd_processor.py` around lines 492 - 493, The language
matching logic at line 492 uses a simple startswith comparison that fails to
handle case-insensitive matching and hierarchical BCP-47 language tag matching.
To fix this, normalize both the audio_lang parameter and the profile language
code to lowercase for comparison, then implement a three-tier matching strategy:
first filter default_audio to include profiles that exactly match the normalized
audio_lang, then also include profiles whose primary language component (before
the hyphen) matches the audio_lang primary component, and finally fall back to
bandwidth selection from the combined list. This ensures that a request for
audio_lang like "es-AR" properly matches both exact "es-ar" tracks and generic
"es" tracks before using bandwidth as a tiebreaker.

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.

1 participant