diff --git a/subtitles.go b/subtitles.go index e661799..e79fa90 100644 --- a/subtitles.go +++ b/subtitles.go @@ -6,6 +6,7 @@ import ( "math" "os" "path/filepath" + "reflect" "strconv" "strings" "time" @@ -595,6 +596,76 @@ func (s *Subtitles) Order() { } } +// ClipFrom clip items from input time +func (s *Subtitles) ClipFrom(cf time.Duration) { + newIndex := 0 + var items []*Item + for index := 0; index < len(s.Items); index++ { + s.Items[index].StartAt -= cf + s.Items[index].EndAt -= cf + s.Items[index].Index = newIndex + if s.Items[index].StartAt < 0 { + s.Items[index].StartAt = 0 + } + if s.Items[index].EndAt > 0 { + items = append(items, s.Items[index]) + } + } + s.Items = items +} + +func copy(source interface{}, destin interface{}) { + x := reflect.ValueOf(source) + if x.Kind() == reflect.Ptr { + starX := x.Elem() + y := reflect.New(starX.Type()) + starY := y.Elem() + starY.Set(starX) + reflect.ValueOf(destin).Elem().Set(y.Elem()) + } +} + +// Clone subtitles +func (s *Subtitles) Clone() *Subtitles { + sub := &Subtitles{} + copy(s.Metadata, sub.Metadata) + for k, r := range s.Regions { + copy(r, sub.Regions[k]) + } + for k, r := range s.Styles { + copy(r, sub.Styles[k]) + } + for i := 0; i < len(s.Items); i++ { + n := &Item{} + copy(s.Items[i], n) + sub.Items = append(sub.Items, n) + } + return sub +} + +// ClipFrom clip items until input time +func (s *Subtitles) ClipTo(ct time.Duration) { + lastIndex := 0 + for index := 0; index < len(s.Items); index++ { + lastIndex = index + if s.Items[index].StartAt > ct { + break + } + if s.Items[index].EndAt > ct { + s.Items[index].EndAt = ct + break + } + } + s.Items = s.Items[:lastIndex+1] +} + +// FixIndex fix item index +func (s *Subtitles) FixIndex() { + for i := 0; i < len(s.Items); i++ { + s.Items[i].Index = i + 1 + } +} + // RemoveStyling removes the styling from the subtitles func (s *Subtitles) RemoveStyling() { s.Regions = map[string]*Region{} diff --git a/subtitles_test.go b/subtitles_test.go index 35b573f..3803005 100644 --- a/subtitles_test.go +++ b/subtitles_test.go @@ -276,3 +276,29 @@ func TestSubtitles_RemoveStyling(t *testing.T) { Styles: map[string]*astisub.Style{}, }, s) } + +func TestSubtitles_FixIndex(t *testing.T) { + var s = mockSubtitles() + s.FixIndex() + for i := 0; i < len(s.Items); i++ { + assert.Equal(t, i+1, s.Items[i].Index) + } +} + +func TestSubtitles_ClipTo(t *testing.T) { + var s = mockSubtitles() + s.ClipTo(2 * time.Second) + assert.Equal(t, 1, len(s.Items)) + assert.Equal(t, 1*time.Second, s.Items[0].StartAt) + assert.Equal(t, 2*time.Second, s.Items[0].EndAt) +} + +func TestSubtitles_ClipFrom(t *testing.T) { + var s = mockSubtitles() + s.ClipFrom(2 * time.Second) + assert.Equal(t, 2, len(s.Items)) + assert.Equal(t, 0*time.Second, s.Items[0].StartAt) + assert.Equal(t, 1*time.Second, s.Items[0].EndAt) + assert.Equal(t, 1*time.Second, s.Items[1].StartAt) + assert.Equal(t, 5*time.Second, s.Items[1].EndAt) +} diff --git a/webvtt.go b/webvtt.go index ebbaec8..d982f11 100644 --- a/webvtt.go +++ b/webvtt.go @@ -277,7 +277,26 @@ func formatDurationWebVTT(i time.Duration) string { } // WriteToWebVTT writes subtitles in .vtt format -func (s Subtitles) WriteToWebVTT(o io.Writer) (err error) { +// if set true in second args write index as item index +func (s Subtitles) WriteToWebVTT(args ...interface{}) (err error) { + var o io.Writer + writeWithIndex := false + for i, arg := range args { + switch i { + case 0: // default output writer + out, ok := arg.(io.Writer) + if !ok { + return fmt.Errorf("first input argument must be io.Writer") + } + o = out + case 1: + b, ok := arg.(bool) + if !ok { + return fmt.Errorf("second input argument must be boolean") + } + writeWithIndex = b + } + } // Do not write anything if no subtitles if len(s.Items) == 0 { err = ErrNoSubtitlesToWrite @@ -350,7 +369,11 @@ func (s Subtitles) WriteToWebVTT(o io.Writer) (err error) { } // Add time boundaries - c = append(c, []byte(strconv.Itoa(index+1))...) + if writeWithIndex { + c = append(c, []byte(strconv.Itoa(item.Index))...) + } else { + c = append(c, []byte(strconv.Itoa(index+1))...) + } c = append(c, bytesLineSeparator...) c = append(c, []byte(formatDurationWebVTT(item.StartAt))...) c = append(c, bytesWebVTTTimeBoundariesSeparator...)