diff --git a/app/Http/Controllers/VideoController.php b/app/Http/Controllers/VideoController.php index 9498dbd..0b1efd5 100644 --- a/app/Http/Controllers/VideoController.php +++ b/app/Http/Controllers/VideoController.php @@ -956,16 +956,24 @@ class VideoController extends Controller : $slideMap['0']; $allLangData = \App\Data\Languages::all(); - $audioTracks = $video->audioTracks->map(fn ($t) => [ - 'id' => $t->id, - 'language' => $t->language, - 'label' => $t->label, - 'flag' => $allLangData[$t->language]['flag'] ?? null, - 'stream_url' => route('videos.audio-track', ['video' => $video, 'track' => $t->id]) . '?v=' . $t->updated_at->timestamp, - 'title' => $t->title ?? '', - 'description' => $t->description ?? '', - 'dl_url' => route('videos.audio-track', ['video' => $video, 'track' => $t->id]) . '?download=1&v=' . $t->updated_at->timestamp, - ])->values()->all(); + // Dedupe the language picker by (language + label). A video with two + // tracks sharing the same language (e.g. "ar" uploaded twice while + // retrying) used to list both and leave the viewer guessing. Keeping + // the first occurrence preserves the primary when it exists; using + // (lang, label) as the key still lets legit variants coexist (e.g. + // "en — Original" and "en — Director's cut"). + $audioTracks = $video->audioTracks + ->unique(fn ($t) => mb_strtolower((string) $t->language) . '|' . mb_strtolower((string) ($t->label ?? ''))) + ->map(fn ($t) => [ + 'id' => $t->id, + 'language' => $t->language, + 'label' => $t->label, + 'flag' => $allLangData[$t->language]['flag'] ?? null, + 'stream_url' => route('videos.audio-track', ['video' => $video, 'track' => $t->id]) . '?v=' . $t->updated_at->timestamp, + 'title' => $t->title ?? '', + 'description' => $t->description ?? '', + 'dl_url' => route('videos.audio-track', ['video' => $video, 'track' => $t->id]) . '?download=1&v=' . $t->updated_at->timestamp, + ])->values()->all(); // Synced lyrics embedded inline (no separate request), keyed by track id; "0" = primary. // Local mirror only — must not block this hot path on NAS I/O.