fix(catalog): give external subtitles their combined-space indexes
buildVersionSubtitleTracks never set Index on external subtitle entries, so every external sub in a version's subtitle_tracks serialized the zero value. Any file with two external subs (or one external plus an embedded stream index 0) published duplicate indexes; clients keying subtitle rows on index crashed (Compose LazyColumn duplicate key) or resolved selections against the wrong track. Externals now carry their combined-space ordinal (externals occupy 0..n-1 in the playback selection space — the same identity session subtitle_urls and ResolveSubtitlePolicyV3 use); embedded entries keep their ffprobe stream indexes unchanged.
This commit is contained in:
@@ -3453,8 +3453,13 @@ func buildVersionSubtitleTracks(file *models.MediaFile) []VersionSubtitleTrack {
|
||||
FileName: sub.FileName,
|
||||
})
|
||||
}
|
||||
for _, sub := range file.ExternalSubtitles {
|
||||
for i, sub := range file.ExternalSubtitles {
|
||||
tracks = append(tracks, VersionSubtitleTrack{
|
||||
// Combined-index identity: externals occupy 0..n-1 in the playback
|
||||
// selection space (session subtitle_urls, ResolveSubtitlePolicyV3).
|
||||
// Without this every external serialized index 0 and clients keying
|
||||
// on index got duplicates.
|
||||
Index: i,
|
||||
Language: sub.Language,
|
||||
Codec: sub.Format,
|
||||
Title: firstNonEmpty(sub.Title, filepath.Base(sub.Path)),
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package catalog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Silo-Server/silo-server/internal/models"
|
||||
)
|
||||
|
||||
// External subtitles must carry their combined-index identity (externals
|
||||
// occupy 0..n-1 in the playback selection space; see
|
||||
// ResolveSubtitlePolicyV3 / session subtitle_urls). Before this test they all
|
||||
// serialized the zero value, so any file with two external subs — or one
|
||||
// external plus an embedded stream index 0 — published duplicate indexes and
|
||||
// clients keying rows on index crashed or selected the wrong track.
|
||||
func TestBuildVersionSubtitleTracksAssignsUniqueExternalIndexes(t *testing.T) {
|
||||
file := &models.MediaFile{
|
||||
SubtitleTracks: []models.SubtitleTrack{
|
||||
{Index: 2, Codec: "subrip", Language: "en"},
|
||||
{Index: 3, Codec: "hdmv_pgs_subtitle", Language: "de"},
|
||||
},
|
||||
ExternalSubtitles: []models.ExternalSubtitle{
|
||||
{Path: "/media/movie.en.srt", Format: "srt", Language: "en"},
|
||||
{Path: "/media/movie.nl.srt", Format: "srt", Language: "nl"},
|
||||
},
|
||||
}
|
||||
|
||||
tracks := buildVersionSubtitleTracks(file)
|
||||
if len(tracks) != 4 {
|
||||
t.Fatalf("tracks len = %d, want 4", len(tracks))
|
||||
}
|
||||
|
||||
// Embedded entries keep their ffprobe stream indexes (existing contract).
|
||||
if tracks[0].Index != 2 || tracks[1].Index != 3 {
|
||||
t.Fatalf("embedded indexes = %d,%d, want 2,3", tracks[0].Index, tracks[1].Index)
|
||||
}
|
||||
|
||||
// Externals carry their combined-space ordinal, not the zero value.
|
||||
if tracks[2].Index != 0 || !tracks[2].External {
|
||||
t.Fatalf("first external = index %d external %v, want 0/true", tracks[2].Index, tracks[2].External)
|
||||
}
|
||||
if tracks[3].Index != 1 || !tracks[3].External {
|
||||
t.Fatalf("second external = index %d external %v, want 1/true", tracks[3].Index, tracks[3].External)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user