better subtitles
Marco Andronaco andronacomarco@gmail.com
Fri, 18 Oct 2024 10:00:52 +0200
4 files changed,
39 insertions(+),
20 deletions(-)
M
src/app/handlers.go
→
src/app/handlers.go
@@ -49,7 +49,7 @@
func indexHandler(w http.ResponseWriter, r *http.Request) { err := g.XT.ExecuteTemplate(w, "index.tmpl", nil) if err != nil { - log.Println("indexHandler ERROR: ", err) + log.Println("indexHandler ERROR:", err) http.Error(w, err500, http.StatusInternalServerError) return }@@ -66,7 +66,7 @@ }
} if !videoRegex.MatchString(videoID) { - log.Println("Invalid video ID: ", videoID) + log.Println("Invalid video ID:", videoID) http.Error(w, err404, http.StatusNotFound) return }@@ -108,7 +108,7 @@ }
err = g.XT.ExecuteTemplate(w, "video.tmpl", data) if err != nil { - log.Println("indexHandler ERROR: ", err) + log.Println("indexHandler ERROR:", err) http.Error(w, err500, http.StatusInternalServerError) return }@@ -134,7 +134,7 @@
data := map[string]interface{}{"Videos": videos} err := g.XT.ExecuteTemplate(w, "cache.tmpl", data) if err != nil { - log.Println("cacheHandler ERROR: ", err) + log.Println("cacheHandler ERROR:", err) http.Error(w, err500, http.StatusInternalServerError) return }
M
src/app/proxy.go
→
src/app/proxy.go
@@ -88,7 +88,8 @@ return
} captions := getCaptions(*video) - caption, ok := captions[strings.TrimSuffix(r.PathValue("language"), ".vtt")] + language := strings.TrimSuffix(r.PathValue("language"), ".vtt") + caption, ok := captions[language] if !ok { http.Error(w, err404, http.StatusNotFound) return@@ -101,9 +102,16 @@ return
} defer res.Body.Close() + buffer, err := subs.Convert(res.Body) + if err != nil { + http.Error(w, err500, http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", "text/vtt") + w.Header().Set("Content-Length", strconv.Itoa(buffer.Len())) - err = subs.Convert(res.Body, w) + _, err = buffer.WriteTo(w) if err != nil { http.Error(w, err500, http.StatusInternalServerError) return
M
src/app/video.go
→
src/app/video.go
@@ -27,7 +27,7 @@ func parseExpiration(url string) time.Duration {
expireString := expireRegex.FindStringSubmatch(url) expireTimestamp, err := strconv.ParseInt(expireString[1], 10, 64) if err != nil { - log.Println("parseExpiration ERROR: ", err) + log.Println("parseExpiration ERROR:", err) return defaultCacheDuration }@@ -94,7 +94,7 @@
func getFromYT(videoID string, formatID int) (video *youtube.Video, format *youtube.Format, err error) { url := getURL(videoID) - log.Println("Requesting video ", url) + log.Println("Requesting video", url) video, err = g.YT.GetVideo(url) if err != nil || video == nil { return
M
src/subs/subs.go
→
src/subs/subs.go
@@ -1,6 +1,7 @@
package subs import ( + "bytes" "encoding/xml" "fmt" "io"@@ -29,8 +30,8 @@ Text string `xml:",chardata"` // Text inside the <s> tag
Time int `xml:"t,attr"` // Optional start time (not always present) } -func writeVTT(output io.Writer, i, startTime, endTime int, sentence string) { - output.Write( +func writeVTT(output *bytes.Buffer, i, startTime, endTime int, sentence string) (int, error) { + return output.Write( []byte( fmt.Sprintf( "%d\n%s --> %s\n%s\n\n",@@ -49,28 +50,35 @@ milliseconds := ms % 1000
return fmt.Sprintf("%02d:%02d:%02d.%03d", seconds/3600, (seconds%3600)/60, seconds%60, milliseconds) } -func Convert(reader io.Reader, output io.Writer) error { +func Convert(reader io.Reader) (buffer bytes.Buffer, err error) { content, err := io.ReadAll(reader) if err != nil { - return err + return } var timedText TimedText err = xml.Unmarshal(content, &timedText) if err != nil { log.Println("Error unmarshalling XML:", err) - return err + return } - output.Write([]byte("WEBVTT\n\n")) + n, err := buffer.Write([]byte("WEBVTT\n\n")) + if err != nil { + return + } - var lastEndTime int + l := len(timedText.Body.Paragraphs) - 1 + var m int for i, p := range timedText.Body.Paragraphs { startTimeMS := p.Start endTimeMS := p.Start + p.Length - if startTimeMS < lastEndTime { - startTimeMS = lastEndTime + if i < l { + nextStartTimeMS := timedText.Body.Paragraphs[i+1].Start + if nextStartTimeMS < endTimeMS { + endTimeMS = nextStartTimeMS + } } var sentence string@@ -87,9 +95,12 @@ if sentence == "" {
continue } - lastEndTime = endTimeMS - writeVTT(output, i+1, startTimeMS, endTimeMS, sentence) + m, err = writeVTT(&buffer, i+1, startTimeMS, endTimeMS, sentence) + n += m + if err != nil { + return + } } - return nil + return }