Skip to content

Commit

Permalink
1. Fixed improper spacing between captions while converting TTML -> VTT
Browse files Browse the repository at this point in the history
2. Added String To Pointer utility.

3. Converted TTML style attributes to pointers

4. Fixed Webvtt not using parent style attributes in region
  • Loading branch information
discovery-avishekgulshan committed Jun 10, 2021
1 parent 7452768 commit badeecd
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 100 deletions.
64 changes: 38 additions & 26 deletions subtitles.go
Expand Up @@ -3,6 +3,7 @@ package astisub
import (
"errors"
"fmt"
"github.com/asticode/go-astisub/util"
"math"
"os"
"path/filepath"
Expand Down Expand Up @@ -207,30 +208,30 @@ type StyleAttributes struct {
TeletextSpacesAfter *int
TeletextSpacesBefore *int
// TODO Use pointers with real types below
TTMLBackgroundColor string // https://htmlcolorcodes.com/fr/
TTMLColor string
TTMLDirection string
TTMLDisplay string
TTMLDisplayAlign string
TTMLExtent string
TTMLFontFamily string
TTMLFontSize string
TTMLFontStyle string
TTMLFontWeight string
TTMLLineHeight string
TTMLOpacity string
TTMLOrigin string
TTMLOverflow string
TTMLPadding string
TTMLShowBackground string
TTMLTextAlign string
TTMLTextDecoration string
TTMLTextOutline string
TTMLUnicodeBidi string
TTMLVisibility string
TTMLWrapOption string
TTMLWritingMode string
TTMLZIndex int
TTMLBackgroundColor *string // https://htmlcolorcodes.com/fr/
TTMLColor *string
TTMLDirection *string
TTMLDisplay *string
TTMLDisplayAlign *string
TTMLExtent *string
TTMLFontFamily *string
TTMLFontSize *string
TTMLFontStyle *string
TTMLFontWeight *string
TTMLLineHeight *string
TTMLOpacity *string
TTMLOrigin *string
TTMLOverflow *string
TTMLPadding *string
TTMLShowBackground *string
TTMLTextAlign *string
TTMLTextDecoration *string
TTMLTextOutline *string
TTMLUnicodeBidi *string
TTMLVisibility *string
TTMLWrapOption *string
TTMLWritingMode *string
TTMLZIndex *int
WebVTTAlign string
WebVTTItalics bool
WebVTTLine string
Expand Down Expand Up @@ -261,11 +262,22 @@ func (sa *StyleAttributes) propagateSTLAttributes() {

func (sa *StyleAttributes) propagateTeletextAttributes() {
if sa.TeletextColor != nil {
sa.TTMLColor = "#" + sa.TeletextColor.TTMLString()
sa.TTMLColor = util.StringToPointer("#" + sa.TeletextColor.TTMLString())
}
}

func (sa *StyleAttributes) propagateTTMLAttributes() {}
func (sa *StyleAttributes) propagateTTMLAttributes() {
if sa.TTMLTextAlign != nil {
sa.WebVTTAlign = *sa.TTMLTextAlign
}
}

func (sa *StyleAttributes) propagateTTMLRegionAttributes() {
if sa.TTMLExtent != nil {
dimensions := strings.Split(*sa.TTMLExtent, " ")
sa.WebVTTWidth = dimensions[0]
}
}

func (sa *StyleAttributes) propagateWebVTTAttributes() {}

Expand Down
25 changes: 13 additions & 12 deletions teletext_test.go
@@ -1,6 +1,7 @@
package astisub

import (
"github.com/asticode/go-astisub/util"
"testing"
"time"

Expand Down Expand Up @@ -79,64 +80,64 @@ func TestParseTeletextRow(t *testing.T) {
TeletextColor: ColorBlack,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#000000",
TTMLColor: util.StringToPointer("#000000"),
}},
{Text: "red", InlineStyle: &StyleAttributes{
TeletextColor: ColorRed,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ff0000",
TTMLColor: util.StringToPointer("#ff0000"),
}},
{Text: "green", InlineStyle: &StyleAttributes{
TeletextColor: ColorGreen,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#008000",
TTMLColor: util.StringToPointer("#008000"),
}},
{Text: "yellow", InlineStyle: &StyleAttributes{
TeletextColor: ColorYellow,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ffff00",
TTMLColor: util.StringToPointer("#ffff00"),
}},
{Text: "blue", InlineStyle: &StyleAttributes{
TeletextColor: ColorBlue,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#0000ff",
TTMLColor: util.StringToPointer("#0000ff"),
}},
{Text: "magenta", InlineStyle: &StyleAttributes{
TeletextColor: ColorMagenta,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ff00ff",
TTMLColor: util.StringToPointer("#ff00ff"),
}},
{Text: "cyan", InlineStyle: &StyleAttributes{
TeletextColor: ColorCyan,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#00ffff",
TTMLColor: util.StringToPointer("#00ffff"),
}},
{Text: "white", InlineStyle: &StyleAttributes{
TeletextColor: ColorWhite,
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ffffff",
TTMLColor: util.StringToPointer("#ffffff"),
}},
{Text: "double height", InlineStyle: &StyleAttributes{
TeletextColor: ColorWhite,
TeletextDoubleHeight: astikit.BoolPtr(true),
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ffffff",
TTMLColor: util.StringToPointer("#ffffff"),
}},
{Text: "double width", InlineStyle: &StyleAttributes{
TeletextColor: ColorWhite,
TeletextDoubleHeight: astikit.BoolPtr(true),
TeletextDoubleWidth: astikit.BoolPtr(true),
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ffffff",
TTMLColor: util.StringToPointer("#ffffff"),
}},
{Text: "double size", InlineStyle: &StyleAttributes{
TeletextColor: ColorWhite,
Expand All @@ -145,7 +146,7 @@ func TestParseTeletextRow(t *testing.T) {
TeletextDoubleSize: astikit.BoolPtr(true),
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ffffff",
TTMLColor: util.StringToPointer("#ffffff"),
}},
{Text: "reset", InlineStyle: &StyleAttributes{
TeletextColor: ColorWhite,
Expand All @@ -154,7 +155,7 @@ func TestParseTeletextRow(t *testing.T) {
TeletextDoubleSize: astikit.BoolPtr(false),
TeletextSpacesAfter: astikit.IntPtr(0),
TeletextSpacesBefore: astikit.IntPtr(0),
TTMLColor: "#ffffff",
TTMLColor: util.StringToPointer("#ffffff"),
}},
}, i.Lines[0].Items)
}
Expand Down
126 changes: 73 additions & 53 deletions ttml.go
Expand Up @@ -70,35 +70,48 @@ type TTMLInMetadata struct {

// TTMLInStyleAttributes represents input TTML style attributes
type TTMLInStyleAttributes struct {
BackgroundColor string `xml:"backgroundColor,attr,omitempty"`
Color string `xml:"color,attr,omitempty"`
Direction string `xml:"direction,attr,omitempty"`
Display string `xml:"display,attr,omitempty"`
DisplayAlign string `xml:"displayAlign,attr,omitempty"`
Extent string `xml:"extent,attr,omitempty"`
FontFamily string `xml:"fontFamily,attr,omitempty"`
FontSize string `xml:"fontSize,attr,omitempty"`
FontStyle string `xml:"fontStyle,attr,omitempty"`
FontWeight string `xml:"fontWeight,attr,omitempty"`
LineHeight string `xml:"lineHeight,attr,omitempty"`
Opacity string `xml:"opacity,attr,omitempty"`
Origin string `xml:"origin,attr,omitempty"`
Overflow string `xml:"overflow,attr,omitempty"`
Padding string `xml:"padding,attr,omitempty"`
ShowBackground string `xml:"showBackground,attr,omitempty"`
TextAlign string `xml:"textAlign,attr,omitempty"`
TextDecoration string `xml:"textDecoration,attr,omitempty"`
TextOutline string `xml:"textOutline,attr,omitempty"`
UnicodeBidi string `xml:"unicodeBidi,attr,omitempty"`
Visibility string `xml:"visibility,attr,omitempty"`
WrapOption string `xml:"wrapOption,attr,omitempty"`
WritingMode string `xml:"writingMode,attr,omitempty"`
ZIndex int `xml:"zIndex,attr,omitempty"`
BackgroundColor *string `xml:"backgroundColor,attr,omitempty"`
Color *string `xml:"color,attr,omitempty"`
Direction *string `xml:"direction,attr,omitempty"`
Display *string `xml:"display,attr,omitempty"`
DisplayAlign *string `xml:"displayAlign,attr,omitempty"`
Extent *string `xml:"extent,attr,omitempty"`
FontFamily *string `xml:"fontFamily,attr,omitempty"`
FontSize *string `xml:"fontSize,attr,omitempty"`
FontStyle *string `xml:"fontStyle,attr,omitempty"`
FontWeight *string `xml:"fontWeight,attr,omitempty"`
LineHeight *string `xml:"lineHeight,attr,omitempty"`
Opacity *string `xml:"opacity,attr,omitempty"`
Origin *string `xml:"origin,attr,omitempty"`
Overflow *string `xml:"overflow,attr,omitempty"`
Padding *string `xml:"padding,attr,omitempty"`
ShowBackground *string `xml:"showBackground,attr,omitempty"`
TextAlign *string `xml:"textAlign,attr,omitempty"`
TextDecoration *string `xml:"textDecoration,attr,omitempty"`
TextOutline *string `xml:"textOutline,attr,omitempty"`
UnicodeBidi *string `xml:"unicodeBidi,attr,omitempty"`
Visibility *string `xml:"visibility,attr,omitempty"`
WrapOption *string `xml:"wrapOption,attr,omitempty"`
WritingMode *string `xml:"writingMode,attr,omitempty"`
ZIndex *int `xml:"zIndex,attr,omitempty"`
}

// StyleAttributes converts TTMLInStyleAttributes into a StyleAttributes
func (s TTMLInStyleAttributes) styleAttributes() (o *StyleAttributes) {
o = &StyleAttributes{
o = getStyleAttributes(s)
o.propagateTTMLAttributes()
return
}

// StyleAttributes converts TTMLInStyleAttributes for region into a StyleAttributes
func (s TTMLInStyleAttributes) regionStyleAttributes() (o *StyleAttributes) {
o = getStyleAttributes(s)
o.propagateTTMLRegionAttributes()
return
}

func getStyleAttributes(s TTMLInStyleAttributes) *StyleAttributes {
return &StyleAttributes{
TTMLBackgroundColor: s.BackgroundColor,
TTMLColor: s.Color,
TTMLDirection: s.Direction,
Expand All @@ -124,8 +137,6 @@ func (s TTMLInStyleAttributes) styleAttributes() (o *StyleAttributes) {
TTMLWritingMode: s.WritingMode,
TTMLZIndex: s.ZIndex,
}
o.propagateTTMLAttributes()
return
}

// TTMLInHeader represents an input TTML header
Expand Down Expand Up @@ -330,7 +341,7 @@ func ReadFromTTML(i io.Reader) (o *Subtitles, err error) {
for _, tr := range ttml.Regions {
var r = &Region{
ID: tr.ID,
InlineStyle: tr.TTMLInStyleAttributes.styleAttributes(),
InlineStyle: tr.TTMLInStyleAttributes.regionStyleAttributes(),
}
if len(tr.Style) > 0 {
if _, ok := o.Styles[tr.Style]; !ok {
Expand Down Expand Up @@ -394,7 +405,7 @@ func ReadFromTTML(i io.Reader) (o *Subtitles, err error) {
// New line decoded as a line break. This can happen if there's a "br" tag within the text since
// since the go xml unmarshaler will unmarshal a "br" tag as a line break if the field has the
// chardata xml tag.
for idx, li := range strings.Split(tt.Text, "\n") {
for idx, li := range strings.Split(tt.Text, "\\n") {
// New line
if idx > 0 {
s.Lines = append(s.Lines, *l)
Expand All @@ -421,6 +432,15 @@ func ReadFromTTML(i io.Reader) (o *Subtitles, err error) {
}

}
//if multiple items in `l` are present without new line then adding space at end so it can become readable after concatenation
if len(l.Items) > 0 {
for idx, item := range l.Items {
if idx == len(l.Items)-1 {
continue
}
l.Items[idx].Text = item.Text + " "
}
}
s.Lines = append(s.Lines, *l)

// Append subtitle
Expand Down Expand Up @@ -450,30 +470,30 @@ type TTMLOutMetadata struct {

// TTMLOutStyleAttributes represents output TTML style attributes
type TTMLOutStyleAttributes struct {
BackgroundColor string `xml:"tts:backgroundColor,attr,omitempty"`
Color string `xml:"tts:color,attr,omitempty"`
Direction string `xml:"tts:direction,attr,omitempty"`
Display string `xml:"tts:display,attr,omitempty"`
DisplayAlign string `xml:"tts:displayAlign,attr,omitempty"`
Extent string `xml:"tts:extent,attr,omitempty"`
FontFamily string `xml:"tts:fontFamily,attr,omitempty"`
FontSize string `xml:"tts:fontSize,attr,omitempty"`
FontStyle string `xml:"tts:fontStyle,attr,omitempty"`
FontWeight string `xml:"tts:fontWeight,attr,omitempty"`
LineHeight string `xml:"tts:lineHeight,attr,omitempty"`
Opacity string `xml:"tts:opacity,attr,omitempty"`
Origin string `xml:"tts:origin,attr,omitempty"`
Overflow string `xml:"tts:overflow,attr,omitempty"`
Padding string `xml:"tts:padding,attr,omitempty"`
ShowBackground string `xml:"tts:showBackground,attr,omitempty"`
TextAlign string `xml:"tts:textAlign,attr,omitempty"`
TextDecoration string `xml:"tts:textDecoration,attr,omitempty"`
TextOutline string `xml:"tts:textOutline,attr,omitempty"`
UnicodeBidi string `xml:"tts:unicodeBidi,attr,omitempty"`
Visibility string `xml:"tts:visibility,attr,omitempty"`
WrapOption string `xml:"tts:wrapOption,attr,omitempty"`
WritingMode string `xml:"tts:writingMode,attr,omitempty"`
ZIndex int `xml:"tts:zIndex,attr,omitempty"`
BackgroundColor *string `xml:"tts:backgroundColor,attr,omitempty"`
Color *string `xml:"tts:color,attr,omitempty"`
Direction *string `xml:"tts:direction,attr,omitempty"`
Display *string `xml:"tts:display,attr,omitempty"`
DisplayAlign *string `xml:"tts:displayAlign,attr,omitempty"`
Extent *string `xml:"tts:extent,attr,omitempty"`
FontFamily *string `xml:"tts:fontFamily,attr,omitempty"`
FontSize *string `xml:"tts:fontSize,attr,omitempty"`
FontStyle *string `xml:"tts:fontStyle,attr,omitempty"`
FontWeight *string `xml:"tts:fontWeight,attr,omitempty"`
LineHeight *string `xml:"tts:lineHeight,attr,omitempty"`
Opacity *string `xml:"tts:opacity,attr,omitempty"`
Origin *string `xml:"tts:origin,attr,omitempty"`
Overflow *string `xml:"tts:overflow,attr,omitempty"`
Padding *string `xml:"tts:padding,attr,omitempty"`
ShowBackground *string `xml:"tts:showBackground,attr,omitempty"`
TextAlign *string `xml:"tts:textAlign,attr,omitempty"`
TextDecoration *string `xml:"tts:textDecoration,attr,omitempty"`
TextOutline *string `xml:"tts:textOutline,attr,omitempty"`
UnicodeBidi *string `xml:"tts:unicodeBidi,attr,omitempty"`
Visibility *string `xml:"tts:visibility,attr,omitempty"`
WrapOption *string `xml:"tts:wrapOption,attr,omitempty"`
WritingMode *string `xml:"tts:writingMode,attr,omitempty"`
ZIndex *int `xml:"tts:zIndex,attr,omitempty"`
}

// ttmlOutStyleAttributesFromStyleAttributes converts StyleAttributes into a TTMLOutStyleAttributes
Expand Down
15 changes: 8 additions & 7 deletions ttml_test.go
Expand Up @@ -2,6 +2,7 @@ package astisub_test

import (
"bytes"
"github.com/asticode/go-astisub/util"
"io/ioutil"
"testing"

Expand All @@ -18,20 +19,20 @@ func TestTTML(t *testing.T) {
assert.Equal(t, &astisub.Metadata{Framerate: 25, Language: astisub.LanguageFrench, Title: "Title test", TTMLCopyright: "Copyright test"}, s.Metadata)
// Styles
assert.Equal(t, 3, len(s.Styles))
assert.Equal(t, astisub.Style{ID: "style_0", InlineStyle: &astisub.StyleAttributes{TTMLColor: "white", TTMLExtent: "100% 10%", TTMLFontFamily: "sansSerif", TTMLFontStyle: "normal", TTMLOrigin: "0% 90%", TTMLTextAlign: "center"}, Style: s.Styles["style_2"]}, *s.Styles["style_0"])
assert.Equal(t, astisub.Style{ID: "style_1", InlineStyle: &astisub.StyleAttributes{TTMLColor: "white", TTMLExtent: "100% 13%", TTMLFontFamily: "sansSerif", TTMLFontStyle: "normal", TTMLOrigin: "0% 87%", TTMLTextAlign: "center"}}, *s.Styles["style_1"])
assert.Equal(t, astisub.Style{ID: "style_2", InlineStyle: &astisub.StyleAttributes{TTMLColor: "white", TTMLExtent: "100% 20%", TTMLFontFamily: "sansSerif", TTMLFontStyle: "normal", TTMLOrigin: "0% 80%", TTMLTextAlign: "center"}}, *s.Styles["style_2"])
assert.Equal(t, astisub.Style{ID: "style_0", InlineStyle: &astisub.StyleAttributes{TTMLColor: util.StringToPointer("white"), TTMLExtent: util.StringToPointer("100% 10%"), TTMLFontFamily: util.StringToPointer("sansSerif"), TTMLFontStyle: util.StringToPointer("normal"), TTMLOrigin: util.StringToPointer("0% 90%"), TTMLTextAlign: util.StringToPointer("center")}, Style: s.Styles["style_2"]}, *s.Styles["style_0"])
assert.Equal(t, astisub.Style{ID: "style_1", InlineStyle: &astisub.StyleAttributes{TTMLColor: util.StringToPointer("white"), TTMLExtent: util.StringToPointer("100% 13%"), TTMLFontFamily: util.StringToPointer("sansSerif"), TTMLFontStyle: util.StringToPointer("normal"), TTMLOrigin: util.StringToPointer("0% 87%"), TTMLTextAlign: util.StringToPointer("center")}}, *s.Styles["style_1"])
assert.Equal(t, astisub.Style{ID: "style_2", InlineStyle: &astisub.StyleAttributes{TTMLColor: util.StringToPointer("white"), TTMLExtent: util.StringToPointer("100% 20%"), TTMLFontFamily: util.StringToPointer("sansSerif"), TTMLFontStyle: util.StringToPointer("normal"), TTMLOrigin: util.StringToPointer("0% 80%"), TTMLTextAlign: util.StringToPointer("center")}}, *s.Styles["style_2"])
// Regions
assert.Equal(t, 3, len(s.Regions))
assert.Equal(t, astisub.Region{ID: "region_0", Style: s.Styles["style_0"], InlineStyle: &astisub.StyleAttributes{TTMLColor: "blue"}}, *s.Regions["region_0"])
assert.Equal(t, astisub.Region{ID: "region_0", Style: s.Styles["style_0"], InlineStyle: &astisub.StyleAttributes{TTMLColor: util.StringToPointer("blue")}}, *s.Regions["region_0"])
assert.Equal(t, astisub.Region{ID: "region_1", Style: s.Styles["style_1"], InlineStyle: &astisub.StyleAttributes{}}, *s.Regions["region_1"])
assert.Equal(t, astisub.Region{ID: "region_2", Style: s.Styles["style_2"], InlineStyle: &astisub.StyleAttributes{}}, *s.Regions["region_2"])
// Items
assert.Equal(t, s.Regions["region_1"], s.Items[0].Region)
assert.Equal(t, s.Styles["style_1"], s.Items[0].Style)
assert.Equal(t, &astisub.StyleAttributes{TTMLColor: "red"}, s.Items[0].InlineStyle)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{Style: s.Styles["style_1"], InlineStyle: &astisub.StyleAttributes{TTMLColor: "black"}, Text: "(deep rumbling)"}}}}, s.Items[0].Lines)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Text: "MAN:"}}}, {Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Text: "How did we"}, {InlineStyle: &astisub.StyleAttributes{TTMLColor: "green"}, Style: s.Styles["style_1"], Text: "end up"}, {InlineStyle: &astisub.StyleAttributes{}, Text: "here?"}}}}, s.Items[1].Lines)
assert.Equal(t, &astisub.StyleAttributes{TTMLColor: util.StringToPointer("red")}, s.Items[0].InlineStyle)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{Style: s.Styles["style_1"], InlineStyle: &astisub.StyleAttributes{TTMLColor: util.StringToPointer("black")}, Text: "(deep rumbling)"}}}}, s.Items[0].Lines)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Text: "MAN:"}}}, {Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Text: "How did we"}, {InlineStyle: &astisub.StyleAttributes{TTMLColor: util.StringToPointer("green")}, Style: s.Styles["style_1"], Text: "end up"}, {InlineStyle: &astisub.StyleAttributes{}, Text: "here?"}}}}, s.Items[1].Lines)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Style: s.Styles["style_1"], Text: "This place is horrible."}}}}, s.Items[2].Lines)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Style: s.Styles["style_1"], Text: "Smells like balls."}}}}, s.Items[3].Lines)
assert.Equal(t, []astisub.Line{{Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Style: s.Styles["style_2"], Text: "We don't belong"}}}, {Items: []astisub.LineItem{{InlineStyle: &astisub.StyleAttributes{}, Style: s.Styles["style_1"], Text: "in this shithole."}}}}, s.Items[4].Lines)
Expand Down

0 comments on commit badeecd

Please sign in to comment.