113 lines
2.5 KiB
Go
113 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
var (
|
|
IdentifierLine = regexp.MustCompile("^\ufeff?\\d+$")
|
|
TimeStampLine = regexp.MustCompile(`^((?:\d{2}:){2}\d{2},\d{3}) --> ((?:\d{2}:){2}\d{2},\d{3})$`)
|
|
)
|
|
|
|
type Entry struct {
|
|
Start string `yaml:"start"`
|
|
End string `yaml:"end"`
|
|
Speaker string `yaml:"speaker"`
|
|
Line1 string `yaml:"line"`
|
|
Line2 string `yaml:"line2"`
|
|
}
|
|
|
|
func parseSrt(r io.Reader) (entries []Entry, err error) {
|
|
srtScan := bufio.NewScanner(r)
|
|
for {
|
|
if !srtScan.Scan() {
|
|
break
|
|
}
|
|
firstLine := strings.TrimSpace(srtScan.Text())
|
|
if !IdentifierLine.MatchString(firstLine) {
|
|
err = fmt.Errorf("invalid identifier %q", string(firstLine))
|
|
return
|
|
}
|
|
|
|
if !srtScan.Scan() {
|
|
err = fmt.Errorf("unexpected end of file after identifier")
|
|
return
|
|
}
|
|
secondLine := strings.TrimSpace(srtScan.Text())
|
|
extractedValues := TimeStampLine.FindAllStringSubmatch(secondLine, -1)
|
|
if extractedValues == nil || len(extractedValues) != 1 {
|
|
err = fmt.Errorf("invalid timestamp line: %q", secondLine)
|
|
return
|
|
}
|
|
startTime := extractedValues[0][1]
|
|
endTime := extractedValues[0][2]
|
|
|
|
if !srtScan.Scan() {
|
|
err = fmt.Errorf("unexpected end of file after timestamps")
|
|
return
|
|
}
|
|
thirdLine := strings.TrimSpace(srtScan.Text())
|
|
if thirdLine == "" {
|
|
err = fmt.Errorf("unexpected empty line after timestamp")
|
|
return
|
|
}
|
|
|
|
fourthLine := ""
|
|
if srtScan.Scan() {
|
|
fourthLine = strings.TrimSpace(srtScan.Text())
|
|
if fourthLine != "" {
|
|
_ = srtScan.Scan()
|
|
if srtScan.Text() != "" {
|
|
err = fmt.Errorf("unexpected non empty line after the second line of text")
|
|
return
|
|
}
|
|
}
|
|
}
|
|
entry := Entry{
|
|
Start: startTime,
|
|
End: endTime,
|
|
Line1: thirdLine,
|
|
Line2: fourthLine,
|
|
}
|
|
entries = append(entries, entry)
|
|
}
|
|
return
|
|
}
|
|
|
|
func main() {
|
|
srtFile := flag.String("srt", "", "File path to the srt file to convert")
|
|
outFile := flag.String("out", "", "File path to the yaml file")
|
|
flag.Parse()
|
|
|
|
srtFd, err := os.Open(*srtFile)
|
|
if err != nil {
|
|
log.Fatalf("failed to open SRT file: %q", err.Error())
|
|
}
|
|
defer srtFd.Close()
|
|
|
|
entries, err := parseSrt(srtFd)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
yamlContent, err := yaml.Marshal(&entries)
|
|
if err != nil {
|
|
log.Fatalf("failed to marshal content, %q", err.Error())
|
|
}
|
|
|
|
outFd, err := os.OpenFile(*outFile, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o600)
|
|
if err != nil {
|
|
log.Fatalf("failed to open YAML file: %q", err.Error())
|
|
}
|
|
defer outFd.Close()
|
|
outFd.Write(yamlContent)
|
|
}
|