diff --git a/transcoder/src/filestream.go b/transcoder/src/filestream.go index a9d244d3..93f7be47 100644 --- a/transcoder/src/filestream.go +++ b/transcoder/src/filestream.go @@ -55,7 +55,35 @@ func NewFileStream(path string, sha string, route string) *FileStream { return ret } +// 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 +// mismatch and we can have the same segment twice on the stream). +func GetStartTime(path string) (float64, error) { + // we can't run this ffprobe in the same call as below because stream entries + // are always after packet entries and we want to start processing packets as + // soon as possible (but we need start_time for that) + cmd := exec.Command( + "ffprobe", + "-loglevel", "quiet", + "-select_streams", "v:0", + "-show_entries", "stream=start_time", + "-of", "csv=p=0", + path, + ) + out, err := cmd.Output() + if err != nil { + return 0, err + } + ret := strings.TrimSpace(string(out)) + return strconv.ParseFloat(ret, 64) +} + func GetKeyframes(path string) ([]float64, bool, error) { + start_time, err := GetStartTime(path) + if err != nil { + return nil, false, err + } + defer printExecTime("ffprobe analysis 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 @@ -107,9 +135,10 @@ func GetKeyframes(path string) ([]float64, bool, error) { // 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. - // if fpts-last < 3 { - if fpts == 0 { - // we still ignore a keyframe in 0 because we hard code it above + + if fpts <= start_time { + // look GetStartTime comment for explanations + // tldr: start time can be greater than 0, ignore keyframes before start_time continue } diff --git a/transcoder/src/stream.go b/transcoder/src/stream.go index e492a3c4..df516574 100644 --- a/transcoder/src/stream.go +++ b/transcoder/src/stream.go @@ -166,14 +166,16 @@ func (ts *Stream) run(start int32) error { "-nostats", "-hide_banner", "-loglevel", "warning", } - if ts.handle.getFlags()&VideoF != 0 { - // This is the default behavior in transmux mode and needed to force pre/post segment to work - // This must be disabled when processing only audio because it creates gaps in audio - args = append(args, "-noaccurate_seek") + if start_ref != 0 { + if ts.handle.getFlags()&VideoF != 0 { + // This is the default behavior in transmux mode and needed to force pre/post segment to work + // This must be disabled when processing only audio because it creates gaps in audio + args = append(args, "-noaccurate_seek") + } + args = append(args, + "-ss", fmt.Sprintf("%.6f", start_ref), + ) } - args = append(args, - "-ss", fmt.Sprintf("%.6f", start_ref), - ) // do not include -to if we want the file to go to the end if end+1 < int32(len(ts.file.Keyframes)) { // sometimes, the duration is shorter than expected (only during transcode it seems)