refactor: address Tolriq feedback on roles and cue timing

- Drop x- prefix from role values (x-bg → bg, x-voice1 → voice1, x-group → group)
- Clarify voiceN has no upper bound (voice1, voice100, voice1000 all valid)
- Make cue.start required (non-pointer int64) in API response
- Keep cue.end optional with defined fallback semantics
- Strip x- prefix from TTML role values when mapping to API output
This commit is contained in:
ranokay 2026-02-22 22:13:22 +02:00
parent 1d78373b77
commit 944401cae3
No known key found for this signature in database
4 changed files with 20 additions and 15 deletions

View File

@ -493,6 +493,11 @@ func mapExplicitStatus(explicitStatus string) string {
return ""
}
// sanitizeRole strips the TTML x- prefix from role values for the API.
func sanitizeRole(role string) string {
return strings.TrimPrefix(role, "x-")
}
func buildStructuredLyric(mf *model.MediaFile, lyrics model.Lyrics, enhanced bool) responses.StructuredLyric {
lines := make([]responses.Line, len(lyrics.Line))
var cueLines []responses.CueLine
@ -510,12 +515,16 @@ func buildStructuredLyric(mf *model.MediaFile, lyrics model.Lyrics, enhanced boo
roleOrder := make([]string, 0, 2)
cuesByRole := make(map[string][]responses.LyricCue)
for _, cue := range line.Cue {
role := cue.Role
role := sanitizeRole(cue.Role)
if _, exists := cuesByRole[role]; !exists {
roleOrder = append(roleOrder, role)
}
var start int64
if cue.Start != nil {
start = *cue.Start
}
cuesByRole[role] = append(cuesByRole[role], responses.LyricCue{
Start: cue.Start,
Start: start,
End: cue.End,
Value: cue.Value,
})

View File

@ -279,11 +279,7 @@ var _ = Describe("MediaRetrievalController", func() {
for k, realCue := range realCueLine.Cue {
expectedCue := expectedCueLine.Cue[k]
Expect(realCue.Value).To(Equal(expectedCue.Value))
if expectedCue.Start == nil {
Expect(realCue.Start).To(BeNil())
} else {
Expect(*realCue.Start).To(Equal(*expectedCue.Start))
}
Expect(realCue.Start).To(Equal(expectedCue.Start))
if expectedCue.End == nil {
Expect(realCue.End).To(BeNil())
} else {
@ -521,12 +517,12 @@ var _ = Describe("MediaRetrievalController", func() {
Value: "konni",
Cue: []responses.LyricCue{
{
Start: &tokenStartA,
Start: tokenStartA,
End: &tokenEndA,
Value: "ko",
},
{
Start: &tokenStartB,
Start: tokenStartB,
End: &tokenEndB,
Value: "nni",
},
@ -607,7 +603,7 @@ var _ = Describe("MediaRetrievalController", func() {
Value: "Hello echo",
Cue: []responses.LyricCue{
{
Start: &tokenStartA,
Start: tokenStartA,
End: &tokenEndA,
Value: "Hello",
},
@ -618,10 +614,10 @@ var _ = Describe("MediaRetrievalController", func() {
Start: &lineStart,
End: &lineEnd,
Value: "Hello echo",
Role: "x-bg",
Role: "bg",
Cue: []responses.LyricCue{
{
Start: &tokenStartB,
Start: tokenStartB,
End: &tokenEndB,
Value: "echo",
},

View File

@ -538,7 +538,7 @@ type Line struct {
}
type LyricCue struct {
Start *int64 `xml:"start,attr,omitempty" json:"start,omitempty"`
Start int64 `xml:"start,attr" json:"start"`
End *int64 `xml:"end,attr,omitempty" json:"end,omitempty"`
Value string `xml:"value,attr" json:"value"`
}

View File

@ -219,7 +219,7 @@ describe('lyrics helpers', () => {
start: 1000,
end: 3000,
value: 'Hello world',
role: 'x-bg',
role: 'bg',
cue: [{ start: 2000, end: 2500, value: 'world' }],
},
],
@ -233,7 +233,7 @@ describe('lyrics helpers', () => {
value: 'Hello world',
tokens: [
{ start: 1000, end: 1500, value: 'Hello', role: '' },
{ start: 2000, end: 2500, value: 'world', role: 'x-bg' },
{ start: 2000, end: 2500, value: 'world', role: 'bg' },
],
},
])