Transcoder: Use mediainfo to get duration for dummy keyframes + handle case when audio file has poster

This commit is contained in:
Arthur Jamet 2024-06-17 08:37:18 +02:00 committed by Zoe Roux
parent 1c010c92db
commit 9dcbcce137

View File

@ -2,7 +2,6 @@ package src
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"log" "log"
"os/exec" "os/exec"
@ -27,9 +26,6 @@ type KeyframeInfo struct {
func (kf *Keyframe) Get(idx int32) float64 { func (kf *Keyframe) Get(idx int32) float64 {
kf.info.mutex.RLock() kf.info.mutex.RLock()
defer kf.info.mutex.RUnlock() defer kf.info.mutex.RUnlock()
if len(kf.Keyframes) == 0 {
return float64(idx * 2)
}
return kf.Keyframes[idx] return kf.Keyframes[idx]
} }
@ -84,7 +80,7 @@ func GetKeyframes(sha string, path string) *Keyframe {
return return
} }
err := getKeyframes(path, kf) err := getKeyframes(path, kf, sha)
if err == nil { if err == nil {
saveInfo(save_path, kf) saveInfo(save_path, kf)
} }
@ -95,7 +91,7 @@ func GetKeyframes(sha string, path string) *Keyframe {
return ret return ret
} }
func getKeyframes(path string, kf *Keyframe) error { func getKeyframes(path string, kf *Keyframe, sha string) 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
@ -172,15 +168,13 @@ func getKeyframes(path string, kf *Keyframe) error {
ret = ret[:0] ret = ret[:0]
} }
} }
if len(ret) == 0 { // If there is less than 2 (i.e. equals 0 or 1 (it happens for audio files with poster))
duration, err := getFileDuration(path) if len(ret) < 2 {
dummy, err := getDummyKeyframes(path, sha)
if err != nil { if err != nil {
return err return err
} }
ret = make([]float64, 0, int((duration/2)+1)) ret = dummy
for segmentTime := float64(0); segmentTime < duration; segmentTime += 2 {
ret = append(ret, segmentTime)
}
} }
kf.add(ret) kf.add(ret)
if done == 0 { if done == 0 {
@ -190,28 +184,16 @@ func getKeyframes(path string, kf *Keyframe) error {
return nil return nil
} }
func getFileDuration(path string) (float64, error) { func getDummyKeyframes(path string, sha string) ([]float64, error) {
cmd := exec.Command( dummyKeyframeDuration := float64(2)
"ffprobe", info, err := GetInfo(path, sha)
"-loglevel", "error",
"-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1",
path,
)
stdout, err := cmd.StdoutPipe()
if err != nil { if err != nil {
return -1, err return nil, err
} }
err = cmd.Start() segmentCount := int((float64(info.Duration) / dummyKeyframeDuration) + 1)
if err != nil { ret := make([]float64, segmentCount)
return -1, err for segmentIndex := 0; segmentIndex < segmentCount; segmentIndex += 1 {
ret[segmentIndex] = float64(segmentIndex) * dummyKeyframeDuration
} }
return ret, nil
scanner := bufio.NewScanner(stdout)
if !scanner.Scan() {
return -1, errors.New("Could not get file duration from ffprobe.")
}
frame := scanner.Text()
return strconv.ParseFloat(frame, 64)
} }