nsfwapp/backend/preview_m3u8_rewrite.go
2026-02-20 18:18:59 +01:00

101 lines
2.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bufio"
"bytes"
"net/url"
"path"
"strings"
)
func rewriteM3U8(raw []byte, id string) []byte {
// Wir bauen alle URIs so um, dass sie wieder über /api/record/preview laufen.
// Wichtig: play=1 bleibt dran, damit Folge-Requests (segments, chunklists) auch ohne Hover gehen.
base := "/api/record/preview?id=" + url.QueryEscape(id) + "&file="
var out bytes.Buffer
sc := bufio.NewScanner(bytes.NewReader(raw))
// Scanner default token limit 64K m3u8 ist normalerweise klein, passt.
// Wenn du riesige Playlists hast, kannst du Buffer erhöhen.
for sc.Scan() {
line := sc.Text()
trim := strings.TrimSpace(line)
if trim == "" {
out.WriteByte('\n')
continue
}
// Kommentare/Tags: ggf. URI="..." in Tags rewriten
if strings.HasPrefix(trim, "#") {
// EXT-X-KEY:URI="..."
line = rewriteAttrURI(line, base)
out.WriteString(line)
out.WriteByte('\n')
continue
}
// Nicht-Tag => URI (segment oder child-playlist)
u := trim
// Absolut? dann lassen
if strings.HasPrefix(u, "http://") || strings.HasPrefix(u, "https://") {
out.WriteString(line)
out.WriteByte('\n')
continue
}
// Wenn es schon unser API ist, lassen
if strings.Contains(u, "/api/record/preview") {
out.WriteString(line)
out.WriteByte('\n')
continue
}
// Nur basename nehmen (ffmpeg schreibt i.d.R. keine Subdirs)
name := path.Base(u)
// Hier play=1 mitschicken:
out.WriteString(base + url.QueryEscape(name) + "&play=1")
out.WriteByte('\n')
}
if err := sc.Err(); err != nil {
// Wenn Scanner aus irgendeinem Grund scheitert: lieber raw zurück (besser als kaputt)
return raw
}
return out.Bytes()
}
func rewriteAttrURI(line, base string) string {
// Rewritet URI="xyz" in EXT-X-KEY / EXT-X-MAP / EXT-X-MEDIA / EXT-X-I-FRAME-STREAM-INF etc.
// Nur relative URIs werden angefasst.
const key = `URI="`
i := strings.Index(line, key)
if i < 0 {
return line
}
j := strings.Index(line[i+len(key):], `"`)
if j < 0 {
return line
}
start := i + len(key)
end := start + j
val := line[start:end]
valTrim := strings.TrimSpace(val)
// absolut oder schon preview => nix tun
if strings.HasPrefix(valTrim, "http://") || strings.HasPrefix(valTrim, "https://") || strings.Contains(valTrim, "/api/record/preview") {
return line
}
name := path.Base(valTrim)
repl := base + url.QueryEscape(name) + "&play=1"
return line[:start] + repl + line[end:]
}