From cf369e3f28d20d1b42b61586f5a8884b051e5a09 Mon Sep 17 00:00:00 2001 From: Laptop Date: Sat, 21 Jun 2025 12:34:45 +0300 Subject: [PATCH] fix skill issues w/ restream --- lib/restream/init.go | 62 ++++++++++++++++++------------------------ lib/restream/reader.go | 11 ++++---- lib/sc/track.go | 14 ++++++---- templates/track.templ | 3 +- 4 files changed, 43 insertions(+), 47 deletions(-) diff --git a/lib/restream/init.go b/lib/restream/init.go index 9ab4012..d9de321 100644 --- a/lib/restream/init.go +++ b/lib/restream/init.go @@ -70,7 +70,7 @@ func Load(r *fiber.App) { return err } - c.Request().Header.SetContentType(tr.Format.MimeType) + c.Response().Header.SetContentType(tr.Format.MimeType) c.Set("Cache-Control", cfg.RestreamCacheControl) if isDownload { @@ -99,23 +99,23 @@ func Load(r *fiber.App) { r.req.SetRequestURI(t.Artwork) err := sc.DoWithRetry(misc.ImageClient, r.req, r.resp) - if err != nil { - return err + if err == nil && r.resp.StatusCode() == 200 { + tag.AddAttachedPicture(id3v2.PictureFrame{MimeType: cfg.B2s(r.req.Header.ContentType()), Picture: r.req.Body(), PictureType: id3v2.PTFrontCover, Encoding: id3v2.EncodingUTF8}) } - - tag.AddAttachedPicture(id3v2.PictureFrame{MimeType: cfg.B2s(r.req.Header.ContentType()), Picture: r.req.Body(), PictureType: id3v2.PTFrontCover, Encoding: id3v2.EncodingUTF8}) } var col collector tag.WriteTo(&col) r.leftover = col.data - c.Response().Header.SetContentType("audio/mpeg") return c.SendStream(r) case cfg.AudioOpus: // might try to fuck around with metadata injection. Dynamically injecting metadata for opus wasn't really good idea as it breaks some things :P req := fasthttp.AcquireRequest() resp := fasthttp.AcquireResponse() + defer fasthttp.ReleaseRequest(req) + defer fasthttp.ReleaseResponse(resp) + req.SetRequestURI(u) req.Header.SetUserAgent(cfg.UserAgent) @@ -124,23 +124,24 @@ func Load(r *fiber.App) { return err } - data := resp.Body() - - res := make([]byte, 0, 1024*1024*1) - for _, s := range bytes.Split(data, []byte{'\n'}) { + parts := make([][]byte, 0, defaultPartsCapacity) + for _, s := range bytes.Split(resp.Body(), newline) { if len(s) == 0 || s[0] == '#' { continue } + parts = append(parts, clone(s)) + } + + res := make([]byte, 0, 1024*1024*1) + for _, s := range parts { req.SetRequestURIBytes(s) err := sc.DoWithRetry(misc.HlsClient, req, resp) if err != nil { return err } - data = resp.Body() - - res = append(res, data...) + res = append(res, resp.Body()...) } tag, err := oggmeta.ReadOGG(bytes.NewReader(res)) @@ -159,24 +160,18 @@ func Load(r *fiber.App) { req.SetRequestURI(t.Artwork) err := sc.DoWithRetry(misc.ImageClient, req, resp) - if err != nil { - return err + if err == nil && resp.StatusCode() == 200 { + parsed, _, err := image.Decode(resp.BodyStream()) + if err == nil { + tag.SetCoverArt(&parsed) + } } - - parsed, _, err := image.Decode(resp.BodyStream()) - resp.CloseBodyStream() - if err != nil { - return err - } - - tag.SetCoverArt(&parsed) } - c.Response().Header.SetContentType(`audio/ogg; codecs="opus"`) return tag.Save(c.Response().BodyWriter()) case cfg.AudioAAC: r := acquireReader() - err := r.Setup(u, true, &t.Duration) + err := r.Setup(u, true, nil) if err != nil { return err } @@ -204,17 +199,13 @@ func Load(r *fiber.App) { r.req.SetRequestURI(t.Artwork) err := sc.DoWithRetry(misc.ImageClient, r.req, r.resp) - if err != nil { - return err + if err == nil && r.resp.StatusCode() == 200 { + parsed, _, err := image.Decode(r.resp.BodyStream()) + r.resp.CloseBodyStream() + if err == nil { + tag.SetCoverArt(&parsed) + } } - - parsed, _, err := image.Decode(r.resp.BodyStream()) - r.resp.CloseBodyStream() - if err != nil { - return err - } - - tag.SetCoverArt(&parsed) } var col collector @@ -222,7 +213,6 @@ func Load(r *fiber.App) { fixDuration(col.data, &t.Duration) r.leftover = col.data - c.Response().Header.SetContentType("audio/mp4") return c.SendStream(r) } } diff --git a/lib/restream/reader.go b/lib/restream/reader.go index f3d8a93..782e82e 100644 --- a/lib/restream/reader.go +++ b/lib/restream/reader.go @@ -42,6 +42,7 @@ func clone(buf []byte) []byte { } var mvhd = []byte("mvhd") +var newline = []byte{'\n'} func fixDuration(data []byte, duration *uint32) { i := bytes.Index(data, mvhd) @@ -85,9 +86,9 @@ func (r *reader) Setup(url string, aac bool, duration *uint32) error { } else { misc.Log(cap(r.parts), len(r.parts)) } + // clone needed to mitigate memory skill issues smh if aac { - // clone needed to mitigate memory skill issues here - for _, s := range bytes.Split(r.resp.Body(), []byte{'\n'}) { + for _, s := range bytes.Split(r.resp.Body(), newline) { if len(s) == 0 { continue } @@ -102,12 +103,12 @@ func (r *reader) Setup(url string, aac bool, duration *uint32) error { r.parts = append(r.parts, clone(s)) } } else { - for _, s := range bytes.Split(r.resp.Body(), []byte{'\n'}) { + for _, s := range bytes.Split(r.resp.Body(), newline) { if len(s) == 0 || s[0] == '#' { continue } - r.parts = append(r.parts, s) + r.parts = append(r.parts, clone(s)) } } @@ -127,7 +128,7 @@ func (r *reader) Close() error { return nil } -// you could prob make this a bit faster by concurrency (make a bunch of workers => make them download the parts => temporarily add them to a map => fully assemble the result => make reader.Read() read out the result as the parts are coming in) but whatever, fine for now +// I have no idea what this truly even does anymore. Maybe a rewrite/refactor would be good? func (r *reader) Read(buf []byte) (n int, err error) { misc.Log("we read") if len(r.leftover) != 0 { diff --git a/lib/sc/track.go b/lib/sc/track.go index 771c772..4894b88 100644 --- a/lib/sc/track.go +++ b/lib/sc/track.go @@ -50,16 +50,20 @@ type Track struct { type TrackPolicy string const ( - PolicyBlock TrackPolicy = "BLOCK" // not available (in your country) - PolicySnip TrackPolicy = "SNIP" // 30-second snippet available - PolicyAllow TrackPolicy = "ALLOW" // all good + PolicyMonetize TrackPolicy = "MONETIZE" // seems like only certain countries get this policy? sometimes protected by widevine and fairplay + PolicyBlock TrackPolicy = "BLOCK" // not available (in your country) + PolicySnip TrackPolicy = "SNIP" // 30-second snippet available + PolicyAllow TrackPolicy = "ALLOW" // all good ) type Protocol string const ( - ProtocolHLS Protocol = "hls" - ProtocolProgressive Protocol = "progressive" + ProtocolHLS Protocol = "hls" + ProtocolProgressive Protocol = "progressive" + ProtocolEncryptedHLS Protocol = "encrypted-hls" // idk, haven't seen in the wild + ProtocolCTREncryptedHLS Protocol = "ctr-encrypted-hls" // google's widevine + ProtocolCBCEncryptedHLS Protocol = "cbc-encrypted-hls" // apple's fairplay ) type Format struct { diff --git a/templates/track.templ b/templates/track.templ index 44b464d..875cb9a 100644 --- a/templates/track.templ +++ b/templates/track.templ @@ -171,7 +171,7 @@ templ Track(prefs cfg.Preferences, t sc.Track, stream string, displayErr string, }

{ t.Title }

@TrackPlayer(prefs, t, stream, displayErr, autoplay, nextTrack, playlist, volume, mode, audio) - if cfg.Restream { + if displayErr == "" && cfg.Restream {
download
@@ -220,6 +220,7 @@ templ Track(prefs cfg.Preferences, t sc.Track, stream string, displayErr string, if t.License != "" {

License: { t.License }

} +

Policy: { t.Policy }

if t.TagList != "" {

Tags: { strings.Join(sc.TagListParser(t.TagList), ", ") }

}