mirror of
https://git.maid.zone/stuff/soundcloak.git
synced 2025-12-10 05:39:38 +05:00
patch duration in m4a for restream/downloads
This commit is contained in:
@@ -2,6 +2,7 @@ package restream
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"image"
|
"image"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -27,6 +28,7 @@ type reader struct {
|
|||||||
parts [][]byte
|
parts [][]byte
|
||||||
leftover []byte
|
leftover []byte
|
||||||
index int
|
index int
|
||||||
|
duration *uint32
|
||||||
|
|
||||||
req *fasthttp.Request
|
req *fasthttp.Request
|
||||||
resp *fasthttp.Response
|
resp *fasthttp.Response
|
||||||
@@ -49,7 +51,21 @@ func clone(buf []byte) []byte {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *reader) Setup(url string, aac bool) error {
|
var mvhd = []byte("mvhd")
|
||||||
|
|
||||||
|
func fixDuration(data []byte, duration *uint32) {
|
||||||
|
i := bytes.Index(data, mvhd)
|
||||||
|
if i != -1 {
|
||||||
|
i += 20
|
||||||
|
|
||||||
|
bt := make([]byte, 4)
|
||||||
|
binary.BigEndian.PutUint32(bt, *duration)
|
||||||
|
copy(data[i:], bt)
|
||||||
|
// timescale is already 1000 in the files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *reader) Setup(url string, aac bool, duration *uint32) error {
|
||||||
if r.req == nil {
|
if r.req == nil {
|
||||||
r.req = fasthttp.AcquireRequest()
|
r.req = fasthttp.AcquireRequest()
|
||||||
}
|
}
|
||||||
@@ -64,6 +80,7 @@ func (r *reader) Setup(url string, aac bool) error {
|
|||||||
|
|
||||||
if aac {
|
if aac {
|
||||||
r.client = misc.HlsAacClient
|
r.client = misc.HlsAacClient
|
||||||
|
r.duration = duration
|
||||||
} else {
|
} else {
|
||||||
r.client = misc.HlsClient
|
r.client = misc.HlsClient
|
||||||
}
|
}
|
||||||
@@ -118,7 +135,6 @@ func (r *reader) Close() error {
|
|||||||
r.req.Reset()
|
r.req.Reset()
|
||||||
r.resp.Reset()
|
r.resp.Reset()
|
||||||
|
|
||||||
r.client = nil
|
|
||||||
r.leftover = nil
|
r.leftover = nil
|
||||||
r.index = 0
|
r.index = 0
|
||||||
r.parts = r.parts[:0]
|
r.parts = r.parts[:0]
|
||||||
@@ -168,6 +184,10 @@ func (r *reader) Read(buf []byte) (n int, err error) {
|
|||||||
data = r.resp.Body()
|
data = r.resp.Body()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if r.index == 0 && r.duration != nil {
|
||||||
|
fixDuration(data, r.duration) // I'm guessing that mvhd will always be in first part
|
||||||
|
}
|
||||||
|
|
||||||
if len(data) > len(buf) {
|
if len(data) > len(buf) {
|
||||||
n = copy(buf, data[:len(buf)])
|
n = copy(buf, data[:len(buf)])
|
||||||
} else {
|
} else {
|
||||||
@@ -241,7 +261,7 @@ func Load(r *fiber.App) {
|
|||||||
switch audio {
|
switch audio {
|
||||||
case cfg.AudioMP3:
|
case cfg.AudioMP3:
|
||||||
r := acquireReader()
|
r := acquireReader()
|
||||||
if err := r.Setup(u, false); err != nil {
|
if err := r.Setup(u, false, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,6 +424,8 @@ func Load(r *fiber.App) {
|
|||||||
result = append(result, data...)
|
result = append(result, data...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixDuration(result, &t.Duration)
|
||||||
|
|
||||||
tag, err := mp4meta.ReadMP4(bytes.NewReader(result))
|
tag, err := mp4meta.ReadMP4(bytes.NewReader(result))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -439,7 +461,13 @@ func Load(r *fiber.App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r := acquireReader()
|
r := acquireReader()
|
||||||
if err := r.Setup(u, audio == cfg.AudioAAC); err != nil {
|
if audio == cfg.AudioAAC {
|
||||||
|
err = r.Setup(u, true, &t.Duration)
|
||||||
|
} else {
|
||||||
|
err = r.Setup(u, false, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ var TracksCache = map[string]cached[Track]{}
|
|||||||
var tracksCacheLock = &sync.RWMutex{}
|
var tracksCacheLock = &sync.RWMutex{}
|
||||||
|
|
||||||
type Track struct {
|
type Track struct {
|
||||||
Artwork string `json:"artwork_url"`
|
Artwork string `json:"artwork_url"`
|
||||||
Comments int `json:"comment_count"`
|
Comments int `json:"comment_count"`
|
||||||
CreatedAt string `json:"created_at"`
|
CreatedAt string `json:"created_at"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
//Duration int `json:"duration"` // there are duration and full_duration fields wtf does that mean
|
Duration uint32 `json:"full_duration"`
|
||||||
Genre string `json:"genre"`
|
Genre string `json:"genre"`
|
||||||
Kind string `json:"kind"` // should always be "track"!
|
Kind string `json:"kind"` // should always be "track"!
|
||||||
LastModified string `json:"last_modified"`
|
LastModified string `json:"last_modified"`
|
||||||
|
|||||||
Reference in New Issue
Block a user