diff --git a/ffmpeg/__init__.py b/ffmpeg/__init__.py index d4f48d8..7e913d3 100644 --- a/ffmpeg/__init__.py +++ b/ffmpeg/__init__.py @@ -1,9 +1,10 @@ from __future__ import unicode_literals -from . import _filters, _ffmpeg, _run +from . import _filters, _ffmpeg, _run, _probe from ._filters import * from ._ffmpeg import * from ._run import * from ._view import * +from ._probe import * -__all__ = _filters.__all__ + _ffmpeg.__all__ + _run.__all__ + _view.__all__ +__all__ = _filters.__all__ + _ffmpeg.__all__ + _run.__all__ + _view.__all__ + _probe.__all__ diff --git a/ffmpeg/_probe.py b/ffmpeg/_probe.py new file mode 100755 index 0000000..ea3a52c --- /dev/null +++ b/ffmpeg/_probe.py @@ -0,0 +1,29 @@ +import json +import subprocess + + +class ProbeException(Exception): + def __init__(self, stderr_output): + super(ProbeException, self).__init__('ffprobe error') + self.stderr_output = stderr_output + + +def probe(filename): + """Run ffprobe on the specified file and return a JSON representation of the output. + + Raises: + ProbeException: if ffprobe returns a non-zero exit code, a ``ProbeException`` is returned with a generic error + message. The stderr output can be retrieved by accessing the ``stderr_output`` property of the exception. + """ + args = ['ffprobe', '-show_format', '-show_streams', '-of', 'json', filename] + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + if p.returncode != 0: + raise ProbeException(err) + return json.loads(out.decode('utf-8')) + + +__all__ = [ + 'probe', + 'ProbeException', +] diff --git a/ffmpeg/tests/test_ffmpeg.py b/ffmpeg/tests/test_ffmpeg.py index b59fa88..1f43158 100644 --- a/ffmpeg/tests/test_ffmpeg.py +++ b/ffmpeg/tests/test_ffmpeg.py @@ -16,6 +16,7 @@ TEST_INPUT_FILE1 = os.path.join(SAMPLE_DATA_DIR, 'in1.mp4') TEST_OVERLAY_FILE = os.path.join(SAMPLE_DATA_DIR, 'overlay.png') TEST_OUTPUT_FILE1 = os.path.join(SAMPLE_DATA_DIR, 'out1.mp4') TEST_OUTPUT_FILE2 = os.path.join(SAMPLE_DATA_DIR, 'out2.mp4') +BOGUS_INPUT_FILE = os.path.join(SAMPLE_DATA_DIR, 'bogus') subprocess.check_call(['ffmpeg', '-version']) @@ -432,3 +433,16 @@ def test_pipe(): out_data = p.stdout.read() assert len(out_data) == frame_size * (frame_count - start_frame) assert out_data == in_data[start_frame*frame_size:] + + +def test_ffprobe(): + data = ffmpeg.probe(TEST_INPUT_FILE1) + assert set(data.keys()) == {'format', 'streams'} + assert data['format']['duration'] == '7.036000' + + +def test_ffprobe_exception(): + with pytest.raises(ffmpeg.ProbeException) as excinfo: + ffmpeg.probe(BOGUS_INPUT_FILE) + assert str(excinfo.value) == 'ffprobe error' + assert b'No such file or directory' in excinfo.value.stderr_output