mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 15:30:34 -04:00
Rework keyframes creations to allow fs caching
This commit is contained in:
parent
4810d6cc5c
commit
6a1fff227e
@ -12,8 +12,7 @@ type FileStream struct {
|
|||||||
err error
|
err error
|
||||||
Path string
|
Path string
|
||||||
Out string
|
Out string
|
||||||
Keyframes []float64
|
Keyframes *Keyframe
|
||||||
CanTransmux bool
|
|
||||||
Info *MediaInfo
|
Info *MediaInfo
|
||||||
videos CMap[Quality, *VideoStream]
|
videos CMap[Quality, *VideoStream]
|
||||||
audios CMap[int32, *AudioStream]
|
audios CMap[int32, *AudioStream]
|
||||||
@ -40,12 +39,7 @@ func NewFileStream(path string, sha string, route string) *FileStream {
|
|||||||
ret.ready.Add(1)
|
ret.ready.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer ret.ready.Done()
|
defer ret.ready.Done()
|
||||||
keyframes, can_transmux, err := GetKeyframes(path)
|
ret.Keyframes = GetKeyframes(sha, path)
|
||||||
ret.Keyframes = keyframes
|
|
||||||
ret.CanTransmux = can_transmux
|
|
||||||
if err != nil {
|
|
||||||
ret.err = err
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
@ -210,7 +210,7 @@ func GetInfo(path string, sha string, route string) (*MediaInfo, error) {
|
|||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSavedInfo(save_path string, mi *MediaInfo) error {
|
func getSavedInfo[T any](save_path string, mi *T) error {
|
||||||
saved_file, err := os.Open(save_path)
|
saved_file, err := os.Open(save_path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -226,7 +226,7 @@ func getSavedInfo(save_path string, mi *MediaInfo) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveInfo(save_path string, mi *MediaInfo) error {
|
func saveInfo[T any](save_path string, mi *T) error {
|
||||||
content, err := json.Marshal(*mi)
|
content, err := json.Marshal(*mi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -2,13 +2,75 @@ package src
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"math"
|
"fmt"
|
||||||
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetKeyframes(path string) ([]float64, bool, error) {
|
type Keyframe struct {
|
||||||
|
Sha string
|
||||||
|
Keyframes []float64
|
||||||
|
CanTransmux bool
|
||||||
|
IsDone bool
|
||||||
|
mutex sync.RWMutex
|
||||||
|
ready sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kf *Keyframe) Get(idx int32) float64 {
|
||||||
|
kf.mutex.RLock()
|
||||||
|
defer kf.mutex.RUnlock()
|
||||||
|
return kf.Keyframes[idx]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kf *Keyframe) Slice(start int32, end int32) []float64 {
|
||||||
|
if end <= start {
|
||||||
|
return []float64{}
|
||||||
|
}
|
||||||
|
kf.mutex.RLock()
|
||||||
|
defer kf.mutex.RUnlock()
|
||||||
|
ref := kf.Keyframes[start:end]
|
||||||
|
ret := make([]float64, end-start)
|
||||||
|
copy(ret, ref)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kf *Keyframe) Length() (int32, bool) {
|
||||||
|
kf.mutex.RLock()
|
||||||
|
defer kf.mutex.RUnlock()
|
||||||
|
return int32(len(kf.Keyframes)), kf.IsDone
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyframes = NewCMap[string, *Keyframe]()
|
||||||
|
|
||||||
|
func GetKeyframes(sha string, path string) *Keyframe {
|
||||||
|
ret, _ := keyframes.GetOrCreate(sha, func() *Keyframe {
|
||||||
|
kf := &Keyframe{
|
||||||
|
Sha: sha,
|
||||||
|
IsDone: false,
|
||||||
|
}
|
||||||
|
kf.ready.Add(1)
|
||||||
|
go func() {
|
||||||
|
save_path := fmt.Sprintf("%s/%s/keyframes.json", Settings.Metadata, sha)
|
||||||
|
if err := getSavedInfo(save_path, kf); err == nil {
|
||||||
|
log.Printf("Using keyframes cache on filesystem for %s", path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := getKeyframes(path, kf)
|
||||||
|
if err == nil {
|
||||||
|
saveInfo(save_path, kf)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return kf
|
||||||
|
})
|
||||||
|
ret.ready.Wait()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func getKeyframes(path string, kf *Keyframe) error {
|
||||||
defer printExecTime("ffprobe analysis for %s", path)()
|
defer printExecTime("ffprobe analysis for %s", path)()
|
||||||
// run ffprobe to return all IFrames, IFrames are points where we can split the video in segments.
|
// run ffprobe to return all IFrames, IFrames are points where we can split the video in segments.
|
||||||
// We ask ffprobe to return the time of each frame and it's flags
|
// We ask ffprobe to return the time of each frame and it's flags
|
||||||
@ -24,11 +86,11 @@ func GetKeyframes(path string) ([]float64, bool, error) {
|
|||||||
)
|
)
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return err
|
||||||
}
|
}
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(stdout)
|
scanner := bufio.NewScanner(stdout)
|
||||||
@ -50,7 +112,7 @@ func GetKeyframes(path string) ([]float64, bool, error) {
|
|||||||
|
|
||||||
fpts, err := strconv.ParseFloat(pts, 64)
|
fpts, err := strconv.ParseFloat(pts, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Before, we wanted to only save keyframes with at least 3s betweens
|
// Before, we wanted to only save keyframes with at least 3s betweens
|
||||||
@ -70,5 +132,8 @@ func GetKeyframes(path string) ([]float64, bool, error) {
|
|||||||
}
|
}
|
||||||
ret = append(ret, fpts)
|
ret = append(ret, fpts)
|
||||||
}
|
}
|
||||||
return ret, can_transmux, nil
|
kf.Keyframes = ret
|
||||||
|
kf.IsDone = true
|
||||||
|
kf.ready.Done()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user