From 975e3d9ae1d2220d820da727a3ce5d3b92976c04 Mon Sep 17 00:00:00 2001 From: Mike Lang Date: Sun, 26 May 2024 11:37:25 +1000 Subject: [PATCH] Move ffmpeg_cut_segment to new ffmpeg_cut_many() system --- common/common/segments.py | 55 ++++++++++++--------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/common/common/segments.py b/common/common/segments.py index 94f86ec..a3be982 100644 --- a/common/common/segments.py +++ b/common/common/segments.py @@ -11,7 +11,7 @@ import logging import os import shutil from collections import namedtuple -from contextlib import closing, contextmanager +from contextlib import contextmanager from tempfile import TemporaryFile from uuid import uuid4 @@ -358,14 +358,12 @@ def streams_info(segment): def ffmpeg_cut_segment(segment, cut_start=None, cut_end=None): - """Return a Popen object which is ffmpeg cutting the given single segment. - This is used when doing a fast cut. """ - args = [ - 'ffmpeg', - '-hide_banner', '-loglevel', 'error', # suppress noisy output - '-i', segment.path, - ] + Wrapper for ffmpeg_cut_many() which cuts a single segment file to stdout, + taking care to preserve stream order and other metadata. + Used when doing a fast cut. + """ + args = [] # output from ffprobe is generally already sorted but let's be paranoid, # because the order of map args matters. for stream in sorted(streams_info(segment), key=lambda stream: stream['index']): @@ -384,11 +382,10 @@ def ffmpeg_cut_segment(segment, cut_start=None, cut_end=None): # as it changes the order that frames go in the file, which messes with our "concatenate the # packets" method of concatenating the video. args += ['-bf', '0'] - # output to stdout as MPEG-TS - args += ['-f', 'mpegts', '-'] - # run it - logging.info("Running segment cut with args: {}".format(" ".join(args))) - return subprocess.Popen(args, stdout=subprocess.PIPE) + # output as MPEG-TS + args += ['-f', 'mpegts'] + + return ffmpeg_cut_one([segment], args) def ffmpeg_cut_one(segments, encode_args, output_file=subprocess.PIPE, input_args=[]): @@ -620,31 +617,13 @@ def fast_cut_range(segments, start, end, fixts=None): if segment in (first, last): if fixts: fixts.next() - proc = None - try: - proc = ffmpeg_cut_segment( - segment, - cut_start if segment == first else None, - cut_end if segment == last else None, - ) - with closing(proc.stdout): - for chunk in read_chunks(proc.stdout): - yield fixts.feed(chunk) if fixts else chunk - proc.wait() - except Exception as ex: - # try to clean up proc, ignoring errors - if proc is not None: - try: - proc.kill() - except OSError: - pass - raise ex - else: - # check if ffmpeg had errors - if proc.returncode != 0: - raise Exception( - "Error while streaming cut: ffmpeg exited {}".format(proc.returncode) - ) + with ffmpeg_cut_segment( + segment, + cut_start if segment == first else None, + cut_end if segment == last else None, + ) as ffmpeg: + for chunk in read_chunks(ffmpeg.stdout): + yield fixts.feed(chunk) if fixts else chunk if fixts: fixts.next() else: