diff --git a/ffmpeg/__init__.py b/ffmpeg/__init__.py
index d4f48d803f84746b153e2f8eb5f1402c428e1796..7e913d37ae3fb81d01a5f65e23ef4d7f75d91f3f 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 0000000000000000000000000000000000000000..ea3a52c987da528900579de573876bc9ceac0c5e
--- /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 1380fdbd756ff02661383080a4eedf9ef9bd079e..b874a86b14f9f7581c265657fb7e5e88703562bd 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'])
@@ -353,3 +354,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