Skip to content

Commit

Permalink
Merge 8296728 into 88639b8
Browse files Browse the repository at this point in the history
  • Loading branch information
inremen committed Aug 18, 2020
2 parents 88639b8 + 8296728 commit 5ad84cd
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 31 deletions.
60 changes: 50 additions & 10 deletions stl.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,19 +215,32 @@ func ReadFromSTL(i io.Reader) (o *Subtitles, err error) {
continue
}

var starttime = g.timecodeStartOfProgramme
if starttime > t.timecodeIn {
starttime = 0
}
// Create item
var i = &Item{
EndAt: t.timecodeOut - g.timecodeStartOfProgramme,
StartAt: t.timecodeIn - g.timecodeStartOfProgramme,
EndAt: t.timecodeOut - starttime,
StartAt: t.timecodeIn - starttime,
}

// Loop through rows
for _, text := range bytes.Split(t.text, []byte{0x8a}) {
parseTeletextRow(i, ch, func() styler { return newSTLStyler() }, text)
}

if i.InlineStyle == nil {
i.InlineStyle = &StyleAttributes{}
}

i.InlineStyle.STLVerticalPostion = t.verticalPosition
i.InlineStyle.STLJustificationCode = t.justificationCode
i.InlineStyle.propagateSTLAttributes()

// Append item
o.Items = append(o.Items, i)
o.TTIBlocks = append(o.TTIBlocks, t)

}
return
Expand Down Expand Up @@ -362,15 +375,15 @@ func parseGSIBlock(b []byte) (g *gsiBlock, err error) {
if v := strings.TrimSpace(string(b[224:230])); len(v) > 0 {
if g.creationDate, err = time.Parse("060102", v); err != nil {
err = fmt.Errorf("astisub: parsing date %s failed: %w", v, err)
return
g.creationDate = time.Now()
}
}

// Revision date
if v := strings.TrimSpace(string(b[230:236])); len(v) > 0 {
if g.revisionDate, err = time.Parse("060102", v); err != nil {
err = fmt.Errorf("astisub: parsing date %s failed: %w", v, err)
return
g.revisionDate = time.Now()
}
}

Expand Down Expand Up @@ -640,6 +653,22 @@ func (t *ttiBlock) bytes(g *gsiBlock) (o []byte) {
return
}

func (t *ttiBlock) bytesSTLToSTL(g *gsiBlock) (o []byte) {
o = append(o, byte(uint8(t.subtitleGroupNumber))) // Subtitle group number
var b = make([]byte, 2)
binary.LittleEndian.PutUint16(b, uint16(t.subtitleNumber))
o = append(o, b...) // Subtitle number
o = append(o, byte(uint8(t.extensionBlockNumber))) // Extension block number
o = append(o, t.cumulativeStatus) // Cumulative status
o = append(o, formatDurationSTLBytes(t.timecodeIn, g.framerate)...) // Timecode in
o = append(o, formatDurationSTLBytes(t.timecodeOut, g.framerate)...) // Timecode out
o = append(o, byte(uint8(t.verticalPosition))) // Vertical position
o = append(o, t.justificationCode) // Justification code
o = append(o, t.commentFlag) // Comment flag
o = append(o, t.text...)
return
}

// formatDurationSTLBytes formats a STL duration in bytes
func formatDurationSTLBytes(d time.Duration, framerate int) (o []byte) {
// Add hours
Expand Down Expand Up @@ -774,12 +803,23 @@ func (s Subtitles) WriteToSTL(o io.Writer) (err error) {
return
}

// Loop through items
for idx, item := range s.Items {
// Write tti block
if _, err = o.Write(newTTIBlock(item, idx+1).bytes(g)); err != nil {
err = fmt.Errorf("astisub: writing tti block #%d failed: %w", idx+1, err)
return
if s.TTIBlocks != nil && len(s.TTIBlocks) == len(s.Items) {
// Loop through items
for idx, ttiblock := range s.TTIBlocks {
// Write tti block
if _, err = o.Write(ttiblock.bytesSTLToSTL(g)); err != nil {
err = fmt.Errorf("astisub: writing tti stl to stl block #%d failed: %w", idx+1, err)
return
}
}
} else {
// Loop through items
for idx, item := range s.Items {
// Write tti block
if _, err = o.Write(newTTIBlock(item, idx+1).bytes(g)); err != nil {
err = fmt.Errorf("astisub: writing tti block #%d failed: %w", idx+1, err)
return
}
}
}
return
Expand Down
77 changes: 72 additions & 5 deletions subtitles.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var (
BytesBOM = []byte{239, 187, 191}
bytesLineSeparator = []byte("\n")
bytesSpace = []byte(" ")
bytesClosectag = []byte("</c>")
)

// Colors
Expand Down Expand Up @@ -92,10 +93,11 @@ func OpenFile(filename string) (*Subtitles, error) {

// Subtitles represents an ordered list of items with formatting
type Subtitles struct {
Items []*Item
Metadata *Metadata
Regions map[string]*Region
Styles map[string]*Style
Items []*Item
Metadata *Metadata
Regions map[string]*Region
Styles map[string]*Style
TTIBlocks []*ttiBlock
}

// NewSubtitles creates new subtitles
Expand Down Expand Up @@ -158,6 +160,54 @@ func (c *Color) TTMLString() string {
return fmt.Sprintf("%.6x", uint32(c.Red)<<16|uint32(c.Green)<<8|uint32(c.Blue))
}

// WebVTTColorString expresses the color as a webvtt string
func (c *Color) WebVTTColorString() string {
switch c {
case ColorBlack:
return "<c.black>" //rgba(0,0,0,1)
case ColorRed:
return "<c.red>" //rgba(255,0,0,1)
case ColorGreen:
return "<c.lime>" //rgba(0,255,0,1)
case ColorYellow:
return "<c.yellow>" //rgba(255,255,0,1)
case ColorBlue:
return "<c.blue>" //rgba(0,0,255,1)
case ColorMagenta:
return "<c.magenta>" //rgba(255,0,255,1)
case ColorCyan:
return "<c.cyan>" //rgba(0,255,255,1)
case ColorWhite:
return "<c.white>" //rgba(255,255,255,1)
default:
return ""
}

}

// WebVTTPositionFromSTL Webvtt Justification From STL
func (sa *StyleAttributes) WebVTTPositionFromSTL() string {
switch sa.STLJustificationCode {
case stlJustificationCodeLeftJustifiedText:
return "20%" //left
case stlJustificationCodeRightJustifiedText:
return "80%" //right
default:
return ""
}
}

// WebVTTLineFromSTL WebVTT Line Vertical Position from STL
func (sa *StyleAttributes) WebVTTLineFromSTL() string {
if sa.STLVerticalPostion < 3 { //top
return "20%"
} else if sa.STLVerticalPostion <= 12 { //(23/2)+1 //middle
return "50%"
} else {
return ""
}
}

// StyleAttributes represents style attributes
type StyleAttributes struct {
SSAAlignment *int
Expand Down Expand Up @@ -189,6 +239,8 @@ type StyleAttributes struct {
STLBoxing *bool
STLItalics *bool
STLUnderline *bool
STLVerticalPostion int
STLJustificationCode byte
TeletextColor *Color
TeletextDoubleHeight *bool
TeletextDoubleSize *bool
Expand Down Expand Up @@ -230,15 +282,20 @@ type StyleAttributes struct {
WebVTTVertical string
WebVTTViewportAnchor string
WebVTTWidth string
WebVTTColor string
}

func (sa *StyleAttributes) propagateSSAAttributes() {}

func (sa *StyleAttributes) propagateSTLAttributes() {}
func (sa *StyleAttributes) propagateSTLAttributes() {
sa.WebVTTLine = sa.WebVTTLineFromSTL()
sa.WebVTTPosition = sa.WebVTTPositionFromSTL()
}

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

Expand Down Expand Up @@ -313,11 +370,21 @@ func (s *Subtitles) Add(d time.Duration) {
for idx := 0; idx < len(s.Items); idx++ {
s.Items[idx].EndAt += d
s.Items[idx].StartAt += d
if s.TTIBlocks != nil && idx < len(s.TTIBlocks) {
s.TTIBlocks[idx].timecodeIn = s.Items[idx].StartAt
s.TTIBlocks[idx].timecodeOut = s.Items[idx].EndAt
}
if s.Items[idx].EndAt <= 0 && s.Items[idx].StartAt <= 0 {
s.Items = append(s.Items[:idx], s.Items[idx+1:]...)
if s.TTIBlocks != nil && idx < len(s.TTIBlocks) {
s.TTIBlocks = append(s.TTIBlocks[:idx], s.TTIBlocks[idx+1:]...)
}
idx--
} else if s.Items[idx].StartAt <= 0 {
s.Items[idx].StartAt = time.Duration(0)
if s.TTIBlocks != nil && idx < len(s.TTIBlocks) {
s.TTIBlocks[idx].timecodeIn = s.Items[idx].StartAt
}
}
}
}
Expand Down
26 changes: 10 additions & 16 deletions teletext.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ func parseTeletextRow(i *Item, d decoder, fs func() styler, row []byte) {
// Loop through columns
var l = Line{}
var li = LineItem{InlineStyle: &StyleAttributes{}}
var started bool

var s styler
for _, v := range row {
// Create specific styler
Expand Down Expand Up @@ -887,10 +887,6 @@ func parseTeletextRow(i *Item, d decoder, fs func() styler, row []byte) {
color = ColorCyan
case 0x7:
color = ColorWhite
case 0xa:
started = false
case 0xb:
started = true
case 0xc:
doubleHeight = astikit.BoolPtr(false)
doubleSize = astikit.BoolPtr(false)
Expand All @@ -913,16 +909,14 @@ func parseTeletextRow(i *Item, d decoder, fs func() styler, row []byte) {
if color != li.InlineStyle.TeletextColor || doubleHeight != li.InlineStyle.TeletextDoubleHeight ||
doubleSize != li.InlineStyle.TeletextDoubleSize || doubleWidth != li.InlineStyle.TeletextDoubleWidth ||
(s != nil && s.hasChanged(li.InlineStyle)) {
// Line has started
if started {
// Append line item
appendTeletextLineItem(&l, li, s)

// Create new line item
sa := &StyleAttributes{}
*sa = *li.InlineStyle
li = LineItem{InlineStyle: sa}
}

// Append line item
appendTeletextLineItem(&l, li, s)

// Create new line item
sa := &StyleAttributes{}
*sa = *li.InlineStyle
li = LineItem{InlineStyle: sa}

// Update style attributes
if color != nil && color != li.InlineStyle.TeletextColor {
Expand All @@ -941,7 +935,7 @@ func parseTeletextRow(i *Item, d decoder, fs func() styler, row []byte) {
s.update(li.InlineStyle)
}
}
} else if started {
} else {
// Append text
li.Text += string(d.decode(v))
}
Expand Down
9 changes: 9 additions & 0 deletions webvtt.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,16 @@ func (s Subtitles) WriteToWebVTT(o io.Writer) (err error) {

// Loop through lines
for _, l := range item.Lines {
var closectag bool
if l.Items != nil && len(l.Items) > 0 && l.Items[0].InlineStyle != nil &&
l.Items[0].InlineStyle.WebVTTColor != "" {
c = append(c, []byte(l.Items[0].InlineStyle.WebVTTColor)...)
closectag = true
}
c = append(c, []byte(l.String())...)
if closectag {
c = append(c, bytesClosectag...)
}
c = append(c, bytesLineSeparator...)
}

Expand Down

0 comments on commit 5ad84cd

Please sign in to comment.