Skip to content

feat(player): discover external audio tracks - #67

Merged
ModerRAS merged 1 commit into
masterfrom
codex/feat-external-audio
Aug 13, 2026
Merged

feat(player): discover external audio tracks#67
ModerRAS merged 1 commit into
masterfrom
codex/feat-external-audio

Conversation

@ModerRAS

@ModerRAS ModerRAS commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • scan the current video directory once for matching external subtitles and audio tracks
  • merge external audio into standard Exo playback and load it with embedded mpv
  • return explicit playback errors for selected backends that cannot inject external audio; never switch backends silently
  • bump the release base to 2.8.0

Backend behavior

  • Standard Exo: external tracks are merged with Media3 MergingMediaSource
  • Embedded mpv: external tracks are loaded with audio-add and exposed through the existing audio menu
  • IJKPlayer: explicit unsupported error
  • External mpv-android intent: explicit unsupported error
  • Embedded mpv with WebDAV: explicit unsupported error instead of falling back to Exo

Verification

  • ./gradlew test lint :app:assembleDebug
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added support for external audio tracks alongside video playback.
    • Automatically detects matching audio files, identifies languages, and displays track titles.
    • Added audio track selection for supported playback modes.
    • External subtitles and audio are now resolved together during playback setup.
  • Bug Fixes

    • Added clear errors for unsupported external-audio playback combinations.
    • Improved track updates and cleanup when media changes or playback ends.
  • Chores

    • Updated the application version to 2.8.0.

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds external audio sidecar discovery, modeling, resolution, and playback. Standard Exo merges external audio sources. Embedded mpv loads and exposes external audio tracks. Unsupported backend combinations now return explicit errors. The application version changes to 2.8.0.

Changes

External audio playback

Layer / File(s) Summary
Audio track model and discovery
core/model/src/main/kotlin/com/miruplay/tv/model/ExternalAudioTracks.kt, core/model/src/main/kotlin/com/miruplay/tv/model/FileModels.kt, core/model/src/main/kotlin/com/miruplay/tv/model/PlaybackSource.kt, core/model/src/test/kotlin/com/miruplay/tv/model/ExternalAudioTracksTest.kt
Adds ExternalAudioTrack, external audio collections on PlaybackSource, sidecar matching, path normalization, language inference, filename decoding, and model tests.
Sidecar resolution
repository-api/src/main/kotlin/com/miruplay/tv/repository/PlaybackSidecarResolver.kt, repository-api/src/test/kotlin/com/miruplay/tv/repository/PlaybackSidecarResolverTest.kt, ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerViewModel.kt
Renames the resolver and extends source resolution to merge external subtitle and audio tracks. The player startup flow uses the renamed resolver and tests cover FLAC and AC3 sidecars.
Embedded mpv audio tracks
player-mpv-android/src/main/kotlin/is/xyz/mpv/MiruMpvSurfaceView.kt
Generalizes track handling, accepts external audio paths, attaches them after media loading, exposes audio tracks, supports audio selection, and reports audio and subtitle changes.
Backend playback integration
player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt, player-core/src/test/kotlin/com/miruplay/tv/player/ExternalAudioBackendSupportTest.kt
Adds backend validation, standard Exo source merging, embedded mpv wiring, backend-specific audio selection, track state cleanup, subtitle-aware media-source configuration, and support tests.
Application version update
app/build.gradle.kts
Updates the default application base version name from 2.7.0 to 2.8.0.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PlayerViewModel
  participant PlaybackSidecarResolver
  participant ExoPlaybackController
  participant MiruMpvSurfaceView

  PlayerViewModel->>PlaybackSidecarResolver: Resolve playback source
  PlaybackSidecarResolver->>PlayerViewModel: Return source with externalAudioTracks
  PlayerViewModel->>ExoPlaybackController: Start playback
  ExoPlaybackController->>MiruMpvSurfaceView: Load media with externalAudioPaths
  MiruMpvSurfaceView->>MiruMpvSurfaceView: Attach paths with audio-add
  MiruMpvSurfaceView->>ExoPlaybackController: Report audio and subtitle track changes
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: discovering and supporting external audio tracks.
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.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/feat-external-audio

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.

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

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 `@player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt`:
- Around line 289-297: Preserve sidecar language and title metadata across both
playback backends: in ExoPlaybackController at
player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt:289-297,
populate the external track’s Format metadata when creating its MediaSource; at
player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt:1561-1561,
pass full external-audio metadata rather than paths to embedded MPV; and in
MiruMpvSurfaceView at
player-mpv-android/src/main/kotlin/is/xyz/mpv/MiruMpvSurfaceView.kt:276-278,
apply or merge the supplied language and title when creating or publishing the
native audio track. Add a backend test covering a language-suffixed sidecar with
no embedded audio tags.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 165a3673-b18a-4efd-9ca6-e852e2d32d9b

📥 Commits

Reviewing files that changed from the base of the PR and between ddcff73 and 6ed59ec.

📒 Files selected for processing (11)
  • app/build.gradle.kts
  • core/model/src/main/kotlin/com/miruplay/tv/model/ExternalAudioTracks.kt
  • core/model/src/main/kotlin/com/miruplay/tv/model/FileModels.kt
  • core/model/src/main/kotlin/com/miruplay/tv/model/PlaybackSource.kt
  • core/model/src/test/kotlin/com/miruplay/tv/model/ExternalAudioTracksTest.kt
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt
  • player-core/src/test/kotlin/com/miruplay/tv/player/ExternalAudioBackendSupportTest.kt
  • player-mpv-android/src/main/kotlin/is/xyz/mpv/MiruMpvSurfaceView.kt
  • repository-api/src/main/kotlin/com/miruplay/tv/repository/PlaybackSidecarResolver.kt
  • repository-api/src/test/kotlin/com/miruplay/tv/repository/PlaybackSidecarResolverTest.kt
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerViewModel.kt

Comment on lines +289 to +297
source.externalAudioTracks.forEach { track ->
add(
mediaSourceFactory.createMediaSource(
MediaItem.Builder()
.setUri(track.path)
.setMediaMetadata(MediaMetadata.Builder().setTitle(track.title).build())
.build(),
),
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Preserve sidecar language and title metadata through both playback backends.

ExternalAudioTrack.language is derived during discovery but does not reach the displayed backend track. Exo reads Format.language, and embedded MPV reads native track metadata. A file named Episode.en.ac3 without embedded tags will therefore appear as und or unnamed in the audio menu.

  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt#L289-L297: preserve each external track language and title in the Exo audio-track representation.
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt#L1561-L1561: pass external-audio metadata, not only paths, to embedded MPV.
  • player-mpv-android/src/main/kotlin/is/xyz/mpv/MiruMpvSurfaceView.kt#L276-L278: apply the supplied language and title when adding the native audio track, or merge the metadata when publishing TrackInfo.

Add a backend test for a sidecar with a language suffix and no embedded audio tags.

📍 Affects 2 files
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt#L289-L297 (this comment)
  • player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt#L1561-L1561
  • player-mpv-android/src/main/kotlin/is/xyz/mpv/MiruMpvSurfaceView.kt#L276-L278
🤖 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 `@player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt`
around lines 289 - 297, Preserve sidecar language and title metadata across both
playback backends: in ExoPlaybackController at
player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt:289-297,
populate the external track’s Format metadata when creating its MediaSource; at
player-core/src/main/kotlin/com/miruplay/tv/player/ExoPlaybackController.kt:1561-1561,
pass full external-audio metadata rather than paths to embedded MPV; and in
MiruMpvSurfaceView at
player-mpv-android/src/main/kotlin/is/xyz/mpv/MiruMpvSurfaceView.kt:276-278,
apply or merge the supplied language and title when creating or publishing the
native audio track. Add a backend test covering a language-suffixed sidecar with
no embedded audio tags.

@ModerRAS
ModerRAS merged commit aa45a56 into master Aug 13, 2026
13 checks passed
@ModerRAS
ModerRAS deleted the codex/feat-external-audio branch August 13, 2026 01:51
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