Skip to content

Commit

Permalink
Add support to extract voicename (#29)
Browse files Browse the repository at this point in the history
* Add support to extract voicename

* Add more tests and Add Custom voice tag parser logic

* Fix comments

* Fix test fail due to incorrect end tag

* Improve test coverage

* Fix names

* Add test

* Use html tokenizer for parsing voice tags

* Unexport the ParseTextWebVTT and use internal test
  • Loading branch information
arun1587 committed Sep 22, 2020
1 parent ebf4389 commit fe67dc6
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 2 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ require (
github.com/asticode/go-astikit v0.8.0
github.com/asticode/go-astits v1.3.0
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20200904194848-62affa334b73
golang.org/x/text v0.3.2
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/pkg/profile v1.4.0/go.mod h1:NWz/XGvpEW1FyYQ7fCx4dqYBLlfTcE+A9FLAkNKqjFE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
Expand Down
50 changes: 48 additions & 2 deletions webvtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import (
"bufio"
"fmt"
"io"
"regexp"
"sort"
"strconv"
"strings"
"time"

"golang.org/x/net/html"
)

// https://www.w3.org/TR/webvtt1/
Expand All @@ -24,6 +27,7 @@ const (
// Vars
var (
bytesWebVTTTimeBoundariesSeparator = []byte(webvttTimeBoundariesSeparator)
webVTTRegexpStartTag = regexp.MustCompile(`(<v([\.\w]*)([\s\w]+)+>)`)
)

// parseDurationWebVTT parses a .vtt duration
Expand All @@ -34,7 +38,6 @@ func parseDurationWebVTT(i string) (time.Duration, error) {
// ReadFromWebVTT parses a .vtt content
// TODO Tags (u, i, b)
// TODO Class
// TODO Speaker name
func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
// Init
o = NewSubtitles()
Expand Down Expand Up @@ -193,7 +196,8 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
case webvttBlockNameStyle:
// TODO Do something with the style
case webvttBlockNameText:
item.Lines = append(item.Lines, Line{Items: []LineItem{{Text: line}}})
// Voice Tag to extract Speaker Name
item.Lines = append(item.Lines, parseTextWebVTT(line))
default:
// This is the ID
index, _ = strconv.Atoi(line)
Expand All @@ -203,6 +207,48 @@ func ReadFromWebVTT(i io.Reader) (o *Subtitles, err error) {
return
}

// parseTextWebVTT parses the input line to fill the Line
func parseTextWebVTT(i string) (o Line) {
tr := html.NewTokenizer(strings.NewReader(i))
var voiceName, endTag, text string
for {
t := tr.Next()
if err := tr.Err(); err != nil {
break
}

switch t {
case html.StartTagToken:
matches := webVTTRegexpStartTag.FindStringSubmatch(string(tr.Raw()))
if matches == nil {
return
}

if len(matches[1]) == 0 {
return
}

voiceName = matches[3]

case html.EndTagToken:
endTag = string(tr.Raw())

case html.TextToken:
text = string(tr.Raw())
}
}

// should be either no tag, or match voice tag
if endTag != "" && endTag != "</v>" {
return
}

o.VoiceName = strings.TrimSpace(voiceName)
o.Items = []LineItem{{Text: strings.TrimSpace(text)}}

return
}

// formatDurationWebVTT formats a .vtt duration
func formatDurationWebVTT(i time.Duration) string {
return formatDuration(i, ".", 3)
Expand Down
36 changes: 36 additions & 0 deletions webvtt_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package astisub

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestParseTextWebVTT(t *testing.T) {

t.Run("When both voice tags are available", func(t *testing.T) {
testData := `<v Bob>Correct tag</v>`

s := parseTextWebVTT(testData)
assert.Equal(t, "Bob", s.VoiceName)
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "Correct tag", s.Items[0].Text)
})

t.Run("When there is no end tag", func(t *testing.T) {
testData := `<v Bob> Text without end tag`

s := parseTextWebVTT(testData)
assert.Equal(t, "Bob", s.VoiceName)
assert.Equal(t, 1, len(s.Items))
assert.Equal(t, "Text without end tag", s.Items[0].Text)
})

t.Run("When the end tag is correct", func(t *testing.T) {
testData := `<v Bob>Incorrect end tag</vi>`

s := parseTextWebVTT(testData)
assert.Equal(t, "", s.VoiceName)
assert.Equal(t, 0, len(s.Items))
})
}
35 changes: 35 additions & 0 deletions webvtt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package astisub_test
import (
"bytes"
"io/ioutil"
"strings"
"testing"

"github.com/asticode/go-astisub"
Expand Down Expand Up @@ -44,3 +45,37 @@ func TestBroken1WebVTT(t *testing.T) {
_, err := astisub.OpenFile("./testdata/broken-1-in.vtt")
assert.Nil(t, err)
}

func TestWebVTTWithVoiceName(t *testing.T) {
voiceName1 := "Roger Bingham"
voiceName2 := "Bingham"
voiceName3 := "Lee"
testData := `WEBVTT
NOTE this a example with voicename
1
00:02:34.00 --> 00:02:35.00
<v.first.local Roger Bingham> I'm the fist speaker
2
00:02:34.00 --> 00:02:35.00
<v Bingham> I'm the second speaker
3
00:00:04.000 --> 00:00:08.000
<v Lee>What are you doing here?</v>
4
00:00:04.000 --> 00:00:08.000
<v Bob>Incorrect tag?</vi>`

s, err := astisub.ReadFromWebVTT(strings.NewReader(testData))
assert.NoError(t, err)

assert.Len(t, s.Items, 4)
assert.Equal(t, voiceName1, s.Items[0].Lines[0].VoiceName)
assert.Equal(t, voiceName2, s.Items[1].Lines[0].VoiceName)
assert.Equal(t, voiceName3, s.Items[2].Lines[0].VoiceName)
assert.Equal(t, "", s.Items[3].Lines[0].VoiceName)
}

0 comments on commit fe67dc6

Please sign in to comment.