mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Make fragments of ~6 seconds instead of a fragment per keyframe
This commit is contained in:
parent
0579afe02b
commit
f6dab80a98
@ -4,12 +4,16 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// In seconds, the spec recomands 6 but since we don't control keyframes we go over more often than not.
|
||||
const OptimalFragmentDuration = float64(5)
|
||||
|
||||
type Keyframe struct {
|
||||
Sha string
|
||||
Keyframes []float64
|
||||
@ -97,7 +101,7 @@ func GetKeyframes(sha string, path string) *Keyframe {
|
||||
}
|
||||
|
||||
func getKeyframes(path string, kf *Keyframe, sha string) error {
|
||||
defer printExecTime("ffprobe analysis for %s", path)()
|
||||
defer printExecTime("keyframe extraction for %s", path)()
|
||||
// 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 could ask it to return only i-frames (keyframes) with the -skip_frame nokey but using it is extremly slow
|
||||
@ -123,6 +127,7 @@ func getKeyframes(path string, kf *Keyframe, sha string) error {
|
||||
|
||||
ret := make([]float64, 0, 1000)
|
||||
max := 100
|
||||
last_frame := math.Inf(-1)
|
||||
done := 0
|
||||
// sometimes, videos can start at a timing greater than 0:00. We need to take that into account
|
||||
// and only list keyframes that come after the start of the video (without that, our segments count
|
||||
@ -154,12 +159,14 @@ func getKeyframes(path string, kf *Keyframe, sha string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Before, we wanted to only save keyframes with at least 3s betweens
|
||||
// to prevent segments of 0.2s but sometimes, the -f segment muxer discards
|
||||
// the segment time and decide to cut at a random keyframe. Having every keyframe
|
||||
// handled as a segment prevents that.
|
||||
// The -f hls encoder decides to not cut at every keyframes (even if we ask it to) when they are too close by.
|
||||
// Instead we can cut every X seconds at the next keyframe, we'll use that as a marker.
|
||||
if fpts < (last_frame+OptimalFragmentDuration) {
|
||||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, fpts)
|
||||
last_frame = fpts
|
||||
|
||||
if len(ret) == max {
|
||||
kf.add(ret)
|
||||
@ -190,7 +197,7 @@ func getKeyframes(path string, kf *Keyframe, sha string) error {
|
||||
}
|
||||
|
||||
func getDummyKeyframes(path string, sha string) ([]float64, error) {
|
||||
dummyKeyframeDuration := float64(2)
|
||||
dummyKeyframeDuration := OptimalFragmentDuration
|
||||
info, err := GetInfo(path, sha)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -267,8 +267,7 @@ func (ts *Stream) run(start int32) error {
|
||||
args = append(args, ts.handle.getTranscodeArgs(toSegmentStr(segments))...)
|
||||
args = append(args,
|
||||
"-f", "hls",
|
||||
// Cut at every keyframes.
|
||||
"-hls_time", "0",
|
||||
"-hls_time", fmt.Sprint(OptimalFragmentDuration),
|
||||
"-start_number", fmt.Sprint(start_segment),
|
||||
"-hls_segment_type", "fmp4",
|
||||
"-hls_fmp4_init_filename", fmt.Sprintf("%s/init.mp4", outpath),
|
||||
@ -302,7 +301,7 @@ func (ts *Stream) run(start int32) error {
|
||||
scanner := bufio.NewScanner(stdout)
|
||||
format := ts.handle.getSegmentName()
|
||||
should_stop := false
|
||||
is_init_ready:= false
|
||||
is_init_ready := false
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
@ -361,7 +360,7 @@ func (ts *Stream) run(start int32) error {
|
||||
|
||||
go func() {
|
||||
err := cmd.Wait()
|
||||
if exiterr, ok := err.(*exec.ExitError); ok && exiterr.ExitCode() == 255 {
|
||||
if exiterr, ok := err.(*exec.ExitError); ok && (exiterr.ExitCode() == 255 || exiterr.ExitCode() == -1) {
|
||||
log.Printf("ffmpeg %d was killed by us", encoder_id)
|
||||
} else if err != nil {
|
||||
log.Printf("ffmpeg %d occurred an error: %v: %s", encoder_id, err, stderr.String())
|
||||
@ -385,11 +384,11 @@ func (ts *Stream) GetIndex() (string, error) {
|
||||
#EXT-X-VERSION:7
|
||||
#EXT-X-PLAYLIST-TYPE:EVENT
|
||||
#EXT-X-START:TIME-OFFSET=0
|
||||
#EXT-X-TARGETDURATION:4
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXT-X-INDEPENDENT-SEGMENTS
|
||||
#EXT-X-MAP:URI="init.mp4"
|
||||
`
|
||||
index += fmt.Sprintf("#EXT-X-TARGETDURATION:%d\n", int(OptimalFragmentDuration))
|
||||
length, is_done := ts.file.Keyframes.Length()
|
||||
|
||||
for segment := int32(0); segment < length-1; segment++ {
|
||||
|
Loading…
x
Reference in New Issue
Block a user