From 74c6da332fe6294181da960e59b9fad370466c7a Mon Sep 17 00:00:00 2001 From: jeanmichel_nwsb Date: Thu, 26 Jun 2025 11:07:49 +0200 Subject: [PATCH 1/3] add alternate duration --- .gitignore | 2 ++ ffprobe/ffprobe.py | 41 +++++++++++++++++++++++++++++------------ tests/ffprobe_test.py | 2 ++ 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index b1efb15..8ef98ae 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,5 @@ pip-selfcheck.json # Other MANIFEST +*.env +.vscode/* \ No newline at end of file diff --git a/ffprobe/ffprobe.py b/ffprobe/ffprobe.py index 1b00c26..d3403d7 100644 --- a/ffprobe/ffprobe.py +++ b/ffprobe/ffprobe.py @@ -30,14 +30,13 @@ def __init__(self, path_to_video): if os.path.isfile(self.path_to_video) or self.path_to_video.startswith('http'): if platform.system() == 'Windows': - cmd = ["ffprobe", "-show_streams", self.path_to_video] + cmd = ["ffprobe", "-show_streams", "-show_format", self.path_to_video] else: cmd = ["ffprobe -show_streams " + pipes.quote(self.path_to_video)] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - stream = False - ignoreLine = False + aggregate_lines = False self.streams = [] self.video = [] self.audio = [] @@ -49,16 +48,20 @@ def __init__(self, path_to_video): line = line.decode('UTF-8', 'ignore') if '[STREAM]' in line: - stream = True - ignoreLine = False + aggregate_lines = True data_lines = [] - elif '[/STREAM]' in line and stream: + elif '[/STREAM]' in line and aggregate_lines: stream = False - ignoreLine = False # noinspection PyUnboundLocalVariable self.streams.append(FFStream(data_lines)) - elif stream: - if '=' in line and ignoreLine == False: + elif '[FORMAT]' in line: + aggregate_lines = True + data_lines = [] + elif '[/FORMAT]' in line and aggregate_lines: + aggregate_lines = False + self.format = FFFormat(data_lines) + elif aggregate_lines: + if '=' in line: data_lines.append(line) self.metadata = {} @@ -82,12 +85,18 @@ def __init__(self, path_to_video): self.metadata[m.groups()[0]] = m.groups()[1].strip() if '[STREAM]' in line: - stream = True + aggregate_lines = True data_lines = [] elif '[/STREAM]' in line and stream: - stream = False + aggregate_lines = False self.streams.append(FFStream(data_lines)) - elif stream: + elif '[FORMAT]' in line: + aggregate_lines = True + data_lines = [] + elif '[/FORMAT]' in line and aggregate_lines: + aggregate_lines = False + self.format = FFFormat(data_lines) + elif aggregate_lines: data_lines.append(line) if 'timecode' in line: @@ -114,6 +123,14 @@ def __repr__(self): return "".format(**vars(self)) +class FFFormat: + """ + An object representation of the overall container format of a multimedia file. + """ + def __init__(self, data_lines): + for line in data_lines: + self.__dict__.update({key: value for key, value, *_ in [line.strip().split('=')]}) + class FFStream: """ An object representation of an individual stream in a multimedia file. diff --git a/tests/ffprobe_test.py b/tests/ffprobe_test.py index 2959376..ecf5414 100644 --- a/tests/ffprobe_test.py +++ b/tests/ffprobe_test.py @@ -38,6 +38,8 @@ def test_video (): print(e) except Exception as e: print(e) + print(f"\tFormat:\n\t\tDuration: {media.format.duration}") + def test_stream (): for test_stream in test_streams: From 2f3c9a9c13c8cfcbe99e82140b52230d0b066051 Mon Sep 17 00:00:00 2001 From: jeanmichel_nwsb Date: Thu, 26 Jun 2025 11:11:49 +0200 Subject: [PATCH 2/3] little rewrite --- ffprobe/ffprobe.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ffprobe/ffprobe.py b/ffprobe/ffprobe.py index d3403d7..453a488 100644 --- a/ffprobe/ffprobe.py +++ b/ffprobe/ffprobe.py @@ -60,8 +60,7 @@ def __init__(self, path_to_video): elif '[/FORMAT]' in line and aggregate_lines: aggregate_lines = False self.format = FFFormat(data_lines) - elif aggregate_lines: - if '=' in line: + elif aggregate_lines and '=' in line: data_lines.append(line) self.metadata = {} @@ -96,7 +95,7 @@ def __init__(self, path_to_video): elif '[/FORMAT]' in line and aggregate_lines: aggregate_lines = False self.format = FFFormat(data_lines) - elif aggregate_lines: + elif aggregate_lines and '=' in line: data_lines.append(line) if 'timecode' in line: From f290cba4ab0948e14a5c900c96675324e23872b2 Mon Sep 17 00:00:00 2001 From: jeanmichel_nwsb Date: Wed, 17 Sep 2025 19:32:07 +0200 Subject: [PATCH 3/3] add function to test interlaved-progressive --- ffprobe/ffprobe.py | 10 ++++++++++ tests/ffprobe_test.py | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ffprobe/ffprobe.py b/ffprobe/ffprobe.py index 453a488..bd86de2 100644 --- a/ffprobe/ffprobe.py +++ b/ffprobe/ffprobe.py @@ -294,3 +294,13 @@ def bit_rate(self): return int(self.__dict__.get('bit_rate', '')) except ValueError: raise FFProbeError('None integer bit_rate') + + def is_progressive(self): + if self.is_video() and self.__dict__.get('field_order', "") == "progressive": + return True + return False + + def is_interlaced(self): + if self.is_video() and self.__dict__.get('field_order', "") in ["tt", "bb", "tb", "bt"]: + return True + return False diff --git a/tests/ffprobe_test.py b/tests/ffprobe_test.py index ecf5414..78d0e8d 100644 --- a/tests/ffprobe_test.py +++ b/tests/ffprobe_test.py @@ -27,8 +27,11 @@ def test_video (): try: if stream.is_video(): frame_rate = stream.frames() / stream.duration_seconds() - print('\t\tFrame Rate:', frame_rate) - print('\t\tFrame Size:', stream.frame_size()) + print('\t\tFrame Rate :', frame_rate) + print('\t\tFrame Size :', stream.frame_size()) + print('\t\tField order:', stream.field_order) + print('\t\tProgressive:', stream.is_progressive()) + print('\t\tInterlaced :', stream.is_interlaced()) print('\t\tDuration:', stream.duration_seconds()) print('\t\tFrames:', stream.frames()) print('\t\tIs video:', stream.is_video()) @@ -53,6 +56,9 @@ def test_stream (): frame_rate = stream.frames() / stream.duration_seconds() print('\t\tFrame Rate:', frame_rate) print('\t\tFrame Size:', stream.frame_size()) + print('\t\tField order:', stream.field_order) + print('\t\tProgressive:', stream.is_progressive()) + print('\t\tInterlaced :', stream.is_interlaced()) print('\t\tDuration:', stream.duration_seconds()) print('\t\tFrames:', stream.frames()) print('\t\tIs video:', stream.is_video())