From 9b40baebf1c12c938f46824db9dae03089d6f687 Mon Sep 17 00:00:00 2001 From: Ruslan Valiyev Date: Sun, 11 Oct 2020 14:42:01 +0200 Subject: [PATCH] Allow specifying streams (e.g. IPTV) as input --- README.md | 8 ++++++-- ffprobe/ffprobe.py | 16 ++++++++++------ tests/ffprobe_test.py | 26 ++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 4519225..5578ba6 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,21 @@ ffprobe-python module ===================== -A wrapper around the ffprobe command to extract metadata from media files. +A wrapper around the ffprobe command to extract metadata from media files or streams. -Usage:: +Usage: ```python #!/usr/bin/env python from ffprobe import FFProbe +# Local file metadata=FFProbe('test-media-file.mov') +# Video stream +# metadata=FFProbe('http://some-streaming-url.com:8080/stream') + for stream in metadata.streams: if stream.is_video(): print('Stream contains {} frames.'.format(stream.frames())) diff --git a/ffprobe/ffprobe.py b/ffprobe/ffprobe.py index 61caaca..3668b23 100644 --- a/ffprobe/ffprobe.py +++ b/ffprobe/ffprobe.py @@ -27,7 +27,7 @@ def __init__(self, path_to_video): except FileNotFoundError: raise IOError('ffprobe not found.') - if os.path.isfile(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] else: @@ -105,7 +105,7 @@ def __init__(self, path_to_video): elif stream.is_attachment(): self.attachment.append(stream) else: - raise IOError('No such media file ' + self.path_to_video) + raise IOError('No such media file or stream is not responding: ' + self.path_to_video) def __repr__(self): return "".format(**vars(self)) @@ -204,10 +204,14 @@ def frames(self): Returns the length of a video stream in frames. Returns 0 if not a video stream. """ if self.is_video() or self.is_audio(): - try: - frame_count = int(self.__dict__.get('nb_frames', '')) - except ValueError: - raise FFProbeError('None integer frame count') + if self.__dict__.get('nb_frames', '') != 'N/A': + try: + frame_count = int(self.__dict__.get('nb_frames', '')) + except ValueError: + raise FFProbeError('None integer frame count') + else: + # When N/A is returned, set frame_count to 0 too + frame_count = 0 else: frame_count = 0 diff --git a/tests/ffprobe_test.py b/tests/ffprobe_test.py index 2d09444..9078f76 100644 --- a/tests/ffprobe_test.py +++ b/tests/ffprobe_test.py @@ -11,6 +11,12 @@ os.path.join(test_dir, './data/SampleVideo_1280x720_1mb.mp4'), ] +# Taken from https://bitmovin.com/mpeg-dash-hls-examples-sample-streams +test_streams = [ + 'https://bitdash-a.akamaihd.net/content/MI201109210084_1/m3u8s/f08e80da-bf1d-4e3d-8899-f0f6155f6efa.m3u8', + 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8' +] + def test_video (): for test_video in test_videos: media = FFProbe(test_video) @@ -30,3 +36,23 @@ def test_video (): print(e) except Exception as e: print(e) + +def test_stream (): + for test_stream in test_streams: + media = FFProbe(test_stream) + print('File:', test_stream) + print('\tStreams:', len(media.streams)) + for index, stream in enumerate(media.streams, 1): + print('\tStream: ', index) + 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\tDuration:', stream.duration_seconds()) + print('\t\tFrames:', stream.frames()) + print('\t\tIs video:', stream.is_video()) + except FFProbeError as e: + print(e) + except Exception as e: + print(e)