mirror of
https://github.com/navidrome/navidrome.git
synced 2026-05-03 06:51:16 +00:00
fix(lyrics): avoid derived TTML agent id collisions
This commit is contained in:
parent
d6a684e60e
commit
177e7089ee
@ -52,7 +52,7 @@ A share of the revenue helps fund the development of Navidrome at no additional
|
||||
- **Multi-platform**, runs on macOS, Linux and Windows. **Docker** images are also provided
|
||||
- Ready to use binaries for all major platforms, including **Raspberry Pi**
|
||||
- Automatically **monitors your library** for changes, importing new files and reloading new metadata
|
||||
- Supports synchronized lyrics from sidecar **.lrc** and **.ttml** files (via `lyricspriority`)
|
||||
- Supports lyrics from sidecar **.ttml**, **.elrc**, **.lrc**, **.srt**, **.txt** files and embedded tags (via `lyricspriority`)
|
||||
- **Themeable**, modern and responsive **Web interface** based on [Material UI](https://material-ui.com)
|
||||
- **Compatible** with all Subsonic/Madsonic/Airsonic [clients](https://www.navidrome.org/docs/overview/#apps)
|
||||
- **Transcoding** on the fly. Can be set per user/player. **Opus encoding is supported**
|
||||
|
||||
@ -24,6 +24,7 @@ const (
|
||||
ttmlLyricKindMain = "main"
|
||||
ttmlLyricKindTranslation = "translation"
|
||||
ttmlLyricKindPronunciation = "pronunciation"
|
||||
ttmlBackgroundAgentPrefix = "__nd_bg__|"
|
||||
)
|
||||
|
||||
var offsetTimeRegex = regexp.MustCompile(`^([0-9]+(?:\.[0-9]+)?)(h|m|s|ms|f|t)$`)
|
||||
@ -623,7 +624,7 @@ func (p *ttmlParser) baseRoleForAgent(agentID string) string {
|
||||
|
||||
func (p *ttmlParser) agentNameForID(agentID string) string {
|
||||
if isBackgroundAgentID(agentID) {
|
||||
baseID := strings.TrimSuffix(agentID, "__bg")
|
||||
baseID := strings.TrimPrefix(agentID, ttmlBackgroundAgentPrefix)
|
||||
if baseID == "main" {
|
||||
return ""
|
||||
}
|
||||
@ -641,11 +642,11 @@ func (p *ttmlParser) agentNameForID(agentID string) string {
|
||||
}
|
||||
|
||||
func backgroundAgentID(agentID string) string {
|
||||
return agentID + "__bg"
|
||||
return ttmlBackgroundAgentPrefix + agentID
|
||||
}
|
||||
|
||||
func isBackgroundAgentID(agentID string) bool {
|
||||
return strings.HasSuffix(agentID, "__bg")
|
||||
return strings.HasPrefix(agentID, ttmlBackgroundAgentPrefix)
|
||||
}
|
||||
|
||||
func contextHasRole(roles string, role string) bool {
|
||||
|
||||
@ -131,7 +131,7 @@ var _ = Describe("parseTTML", func() {
|
||||
Expect(list).To(HaveLen(1))
|
||||
Expect(list[0].Agents).To(Equal([]model.Agent{
|
||||
{ID: "main", Role: "main"},
|
||||
{ID: "main__bg", Role: "bg"},
|
||||
{ID: "__nd_bg__|main", Role: "bg"},
|
||||
}))
|
||||
Expect(list[0].Line).To(HaveLen(1))
|
||||
|
||||
@ -143,7 +143,7 @@ var _ = Describe("parseTTML", func() {
|
||||
|
||||
Expect(line.Cue[0]).To(Equal(model.Cue{Start: gg.P(int64(1000)), End: gg.P(int64(1400)), Value: "He", AgentID: "main"}))
|
||||
Expect(line.Cue[1]).To(Equal(model.Cue{Start: gg.P(int64(1400)), End: gg.P(int64(1800)), Value: "llo", AgentID: "main"}))
|
||||
Expect(line.Cue[2]).To(Equal(model.Cue{Start: gg.P(int64(2000)), End: gg.P(int64(2500)), Value: "echo", AgentID: "main__bg"}))
|
||||
Expect(line.Cue[2]).To(Equal(model.Cue{Start: gg.P(int64(2000)), End: gg.P(int64(2500)), Value: "echo", AgentID: "__nd_bg__|main"}))
|
||||
})
|
||||
|
||||
It("should parse named TTML agents into main, voice, and group roles", func() {
|
||||
@ -177,6 +177,44 @@ var _ = Describe("parseTTML", func() {
|
||||
Expect(list[0].Line[1].Cue[0].AgentID).To(Equal("v2"))
|
||||
Expect(list[0].Line[2].Cue[0].AgentID).To(Equal("v1000"))
|
||||
})
|
||||
|
||||
It("should avoid collisions between derived background agents and explicit TTML agent ids", func() {
|
||||
content := []byte(`<?xml version="1.0" encoding="UTF-8"?>
|
||||
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:ttm="http://www.w3.org/ns/ttml#metadata">
|
||||
<head>
|
||||
<metadata>
|
||||
<ttm:agent xml:id="lead" type="person"><ttm:name>Lead</ttm:name></ttm:agent>
|
||||
<ttm:agent xml:id="lead__bg" type="person"><ttm:name>Existing Background Id</ttm:name></ttm:agent>
|
||||
</metadata>
|
||||
</head>
|
||||
<body xml:lang="eng">
|
||||
<div>
|
||||
<p begin="1s" end="2s" ttm:agent="lead">
|
||||
<span begin="1s" end="1.4s">Lead</span>
|
||||
<span ttm:role="x-bg"><span begin="1.5s" end="1.8s">Echo</span></span>
|
||||
</p>
|
||||
<p begin="2s" end="3s" ttm:agent="lead__bg">
|
||||
<span begin="2s" end="2.5s">Named</span>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</tt>`)
|
||||
|
||||
list, err := parseTTML(content)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(list).To(HaveLen(1))
|
||||
Expect(list[0].Agents).To(Equal([]model.Agent{
|
||||
{ID: "lead", Role: "main", Name: "Lead"},
|
||||
{ID: "__nd_bg__|lead", Role: "bg", Name: "Lead"},
|
||||
{ID: "lead__bg", Role: "voice", Name: "Existing Background Id"},
|
||||
}))
|
||||
Expect(list[0].Line).To(HaveLen(2))
|
||||
Expect(list[0].Line[0].Cue).To(HaveLen(2))
|
||||
Expect(list[0].Line[0].Cue[0].AgentID).To(Equal("lead"))
|
||||
Expect(list[0].Line[0].Cue[1].AgentID).To(Equal("__nd_bg__|lead"))
|
||||
Expect(list[0].Line[1].Cue).To(HaveLen(1))
|
||||
Expect(list[0].Line[1].Cue[0].AgentID).To(Equal("lead__bg"))
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Ambiguous decimal timing", func() {
|
||||
|
||||
@ -543,7 +543,7 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
lyricsJson, err := json.Marshal(model.LyricList{
|
||||
{
|
||||
Lang: "eng",
|
||||
Agents: []model.Agent{{ID: "lead", Role: "main"}, {ID: "lead__bg", Role: "bg"}},
|
||||
Agents: []model.Agent{{ID: "lead", Role: "main"}, {ID: "__nd_bg__|lead", Role: "bg"}},
|
||||
Synced: true,
|
||||
Line: []model.Line{
|
||||
{
|
||||
@ -561,7 +561,7 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
Start: &tokenStartB,
|
||||
End: &tokenEndB,
|
||||
Value: "echo",
|
||||
AgentID: "lead__bg",
|
||||
AgentID: "__nd_bg__|lead",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -591,7 +591,7 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
Synced: true,
|
||||
Agents: []responses.Agent{
|
||||
{ID: "lead", Role: "main"},
|
||||
{ID: "lead__bg", Role: "bg"},
|
||||
{ID: "__nd_bg__|lead", Role: "bg"},
|
||||
},
|
||||
Line: []responses.Line{
|
||||
{
|
||||
@ -619,7 +619,7 @@ var _ = Describe("MediaRetrievalController", func() {
|
||||
Start: &lineStart,
|
||||
End: &lineEnd,
|
||||
Value: "Hello echo",
|
||||
AgentID: "lead__bg",
|
||||
AgentID: "__nd_bg__|lead",
|
||||
Cue: []responses.LyricCue{
|
||||
{
|
||||
Start: tokenStartB,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user