Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,5 @@ pip-selfcheck.json

# Other
MANIFEST
*.env
.vscode/*
50 changes: 38 additions & 12 deletions ffprobe/ffprobe.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand All @@ -49,16 +48,19 @@ 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 and '=' in line:
data_lines.append(line)

self.metadata = {}
Expand All @@ -82,12 +84,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 and '=' in line:
data_lines.append(line)

if 'timecode' in line:
Expand All @@ -114,6 +122,14 @@ def __repr__(self):
return "<FFprobe: {metadata}, {video}, {audio}, {subtitle}, {attachment}, {timecode}>".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.
Expand Down Expand Up @@ -278,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
12 changes: 10 additions & 2 deletions tests/ffprobe_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -38,6 +41,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:
Expand All @@ -51,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())
Expand Down