diff --git a/.gitignore b/.gitignore
index 0971f29..f474a5d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
 /vendor/
 /docs/build
 composer.phar
+phpunit.xml
 
diff --git a/README.md b/README.md
index 4aaee43..0c68d66 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,21 @@ $ffmpeg->open('Video.mpeg')
     ->close();
 ```
 
+##Getting progress information
+
+
+```php
+$progressHelper = new FFMpeg\Helper\AudioProgressHelper(function($percent, $remaining, $rate) {
+	echo "Current progress: " . $percent "%\n";
+	echo "Remaining time: " . $remaining " seconds\n";
+});
+
+$ffmpeg->open('Audio.wav')
+	->attachHelper($progressHelper)
+    ->encode(new Mp3(), 'file.mp3')
+    ->close();
+```
+
 ##Using with Silex Microframework
 
 ```php
diff --git a/composer.json b/composer.json
index 825ebad..c40110e 100644
--- a/composer.json
+++ b/composer.json
@@ -28,8 +28,9 @@
     "minimum-stability": "dev",
     "require-dev": {
         "fabpot/php-cs-fixer": "master",
-	    "sami/sami": "dev-master",
-	    "silex/silex": "dev-master"
+        "sami/sami": "dev-master",
+        "silex/silex": "dev-master",
+        "phpunit/phpunit": "3.7.*"
     },
     "autoload": {
         "psr-0": {
diff --git a/src/FFMpeg/FFMpeg.php b/src/FFMpeg/FFMpeg.php
index 167b05f..200dbbc 100644
--- a/src/FFMpeg/FFMpeg.php
+++ b/src/FFMpeg/FFMpeg.php
@@ -16,6 +16,7 @@ use FFMpeg\Exception\LogicException;
 use FFMpeg\Exception\RuntimeException;
 use FFMpeg\Format\Audio;
 use FFMpeg\Format\Video;
+use FFMpeg\Helper\HelperInterface;
 use Symfony\Component\Process\Process;
 use Symfony\Component\Process\ProcessBuilder;
 
@@ -35,6 +36,11 @@ class FFMpeg extends Binary
     protected $prober;
     protected $threads = 1;
 
+    /**
+     * @var HelperInterface[]
+     */
+    protected $helpers = array();
+
     /**
      * Destructor
      */
@@ -44,6 +50,24 @@ class FFMpeg extends Binary
         parent::__destruct();
     }
 
+    /**
+     * @param HelperInterface $helper
+     * @return \FFMpeg\FFMpeg
+     */
+    public function attachHelper(HelperInterface $helper)
+    {
+        $this->helpers[] = $helper;
+        $helper->setProber($this->prober);
+
+        // ensure the helpers have the path to the file in case
+        // they need to probe for format information
+        if ($this->pathfile !== null) {
+            $helper->open($this->pathfile);
+        }
+
+        return $this;
+    }
+
     public function setThreads($threads)
     {
         if ($threads > 64 || $threads < 1) {
@@ -76,9 +100,12 @@ class FFMpeg extends Binary
         }
 
         $this->logger->addInfo(sprintf('FFmpeg opens %s', $pathfile));
-
         $this->pathfile = $pathfile;
 
+        foreach ($this->helpers as $helper) {
+            $helper->open($pathfile);
+        }
+
         return $this;
     }
 
@@ -135,7 +162,7 @@ class FFMpeg extends Binary
         $this->logger->addInfo(sprintf('FFmpeg executes command %s', $process->getCommandline()));
 
         try {
-            $process->run();
+            $process->run(array($this, 'transcodeCallback'));
         } catch (\RuntimeException $e) {
 
         }
@@ -218,7 +245,7 @@ class FFMpeg extends Binary
         $this->logger->addInfo(sprintf('FFmpeg executes command %s', $process->getCommandLine()));
 
         try {
-            $process->run();
+            $process->run(array($this, 'transcodeCallback'));
         } catch (\RuntimeException $e) {
 
         }
@@ -344,7 +371,7 @@ class FFMpeg extends Binary
             $this->logger->addInfo(sprintf('FFmpeg executes command %s', $process->getCommandline()));
 
             try {
-                $process->run();
+                $process->run(array($this, 'transcodeCallback'));
             } catch (\RuntimeException $e) {
                 break;
             }
@@ -365,6 +392,19 @@ class FFMpeg extends Binary
         return $this;
     }
 
+    /**
+     * The main transcoding callback, delegates the content to the helpers.
+     *
+     * @param string $channel (stdio|stderr)
+     * @param string $content the current line of the ffmpeg output
+     */
+    public function transcodeCallback($channel, $content)
+    {
+        foreach ($this->helpers as $helper) {
+            $helper->transcodeCallback($channel, $content);
+        }
+    }
+
     /**
      * Removes unnecessary file
      *
diff --git a/src/FFMpeg/FFProbe.php b/src/FFMpeg/FFProbe.php
index 65ddabd..0303f55 100644
--- a/src/FFMpeg/FFProbe.php
+++ b/src/FFMpeg/FFProbe.php
@@ -24,6 +24,8 @@ use Symfony\Component\Process\ProcessBuilder;
 class FFProbe extends Binary
 {
 
+    protected $cachedFormats = array();
+
     /**
      * Probe the format of a given file
      *
@@ -39,6 +41,10 @@ class FFProbe extends Binary
             throw new InvalidArgumentException($pathfile);
         }
 
+        if (isset($this->cachedFormats[$pathfile])) {
+            return $this->cachedFormats[$pathfile];
+        }
+
         $builder = ProcessBuilder::create(array(
             $this->binary, $pathfile, '-show_format'
         ));
@@ -69,7 +75,7 @@ class FFProbe extends Binary
             $ret[$key] = $value;
         }
 
-        return json_encode($ret);
+        return $this->cachedFormats[$pathfile] = json_encode($ret);
     }
 
     /**
diff --git a/src/FFMpeg/Helper/AudioProgressHelper.php b/src/FFMpeg/Helper/AudioProgressHelper.php
new file mode 100644
index 0000000..5044469
--- /dev/null
+++ b/src/FFMpeg/Helper/AudioProgressHelper.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace FFMpeg\Helper;
+
+/**
+ * Parses ffmpeg stderr progress information. An example:
+ *
+ * 
+ *       size=    3552kB time=00:03:47.29 bitrate= 128.0kbits/s
+ * 
+ *
+ * @author Robert Gruendler 
+ */
+class AudioProgressHelper extends ProgressHelper
+{
+    public function getPattern()
+    {
+        return '/size=(.*?) time=(.*?) /';
+    }
+}
diff --git a/src/FFMpeg/Helper/HelperInterface.php b/src/FFMpeg/Helper/HelperInterface.php
new file mode 100644
index 0000000..e7778c0
--- /dev/null
+++ b/src/FFMpeg/Helper/HelperInterface.php
@@ -0,0 +1,42 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace FFMpeg\Helper;
+
+use FFMpeg\FFProbe;
+
+/**
+ * @author Robert Gruendler 
+ */
+interface HelperInterface
+{
+    /**
+     * The callback from the ffmpeg process.
+     *
+     * @param string $channel (stdio|stderr)
+     * @param string $content the current line of the ffmpeg output
+     */
+    function transcodeCallback($channel, $content);
+
+    /**
+     * The helper has access to a prober instance if available.
+     *
+     * @param FFProbe $prober
+     */
+    function setProber(FFProbe $prober);
+
+    /**
+     * Called when the input file is opened.
+     *
+     * @param string $pathfile
+     */
+    function open($pathfile);
+}
diff --git a/src/FFMpeg/Helper/ProgressHelper.php b/src/FFMpeg/Helper/ProgressHelper.php
new file mode 100644
index 0000000..a44a068
--- /dev/null
+++ b/src/FFMpeg/Helper/ProgressHelper.php
@@ -0,0 +1,223 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace FFMpeg\Helper;
+
+use FFMpeg\FFProbe;
+
+/**
+ * @author Robert Gruendler 
+ */
+abstract class ProgressHelper implements HelperInterface
+{
+    /**
+     * @var number
+     */
+    protected $duration = null;
+
+    /**
+     * transcoding rate in kb/s
+     *
+     * @var number
+     */
+    protected $rate;
+
+    /**
+     * @var array
+     */
+    protected $format;
+
+    /**
+     * @var number
+     */
+    protected $totalSize;
+
+    /**
+     * @var number
+     */
+    protected $currentSize;
+
+    /**
+     * @var number
+     */
+    protected $currentTime;
+
+    /**
+     * @var double
+     */
+    protected $lastOutput = null;
+
+    /**
+     * Percentage of transcoding progress (0 - 100)
+     *
+     * @var number
+     */
+    protected $percent = 0;
+
+    /**
+     * Time remaining (seconds)
+     *
+     * @var number
+     */
+    protected $remaining = null;
+
+    /**
+     * @var FFProbe
+     */
+    protected $prober;
+
+    /**
+     * @var Closure|string|array
+     */
+    protected $callback;
+
+    /**
+     * @param mixed $callback
+     */
+    public function __construct($callback)
+    {
+        $this->callback = $callback;
+    }
+
+    /**
+     * Used to ease testing.
+     *
+     * @param number $duration
+     */
+    public function setDuration($duration)
+    {
+        $this->duration = $duration;
+    }
+
+    /*
+     *  {@inheritdoc}
+     */
+    public function transcodeCallback($channel, $content)
+    {
+        $progress = $this->parseProgress($content);
+
+        if (is_array($progress)) {
+            call_user_func_array($this->callback, $progress);
+        }
+    }
+
+    /*
+     *  {@inheritdoc}
+     */
+    public function setProber(FFProbe $prober)
+    {
+        $this->prober = $prober;
+    }
+
+    /*
+     *  {@inheritdoc}
+     */
+    public function open($pathfile)
+    {
+        if ($this->prober === null) {
+            throw new \RuntimeException('Unable to report audio progress without a prober');
+        }
+
+        $format = json_decode($this->prober->probeFormat($pathfile), true);
+
+        if ($format === null || count($format) === 0 || isset($format['size']) === false) {
+            throw new \RuntimeException('Unable to probe format for ' . $pathfile);
+        }
+
+        $this->format = $format;
+        $this->totalSize = $format['size'] / 1024;
+        $this->duration = $format['duration'];
+    }
+
+    /**
+     * @param string $progress A ffmpeg stderr progress output
+     * @return array the progressinfo array or null if there's no progress available yet.
+     */
+    public function parseProgress($progress)
+    {
+        $matches = array();
+
+        if (preg_match($this->getPattern(), $progress, $matches) !== 1) {
+            return null;
+        }
+
+        $currentDuration = $this->convertDuration($matches[2]);
+        $currentTime = $this->microtimeFloat();
+        $currentSize = trim(str_replace('kb', '', strtolower(($matches[1]))));
+        $percent = $currentDuration/ $this->duration;
+
+        if ($this->lastOutput !== null) {
+            $delta = $currentTime - $this->lastOutput;
+            $deltaSize = $currentSize - $this->currentSize;
+            $rate = $deltaSize * $delta;
+            $totalDuration = $this->totalSize / $rate;
+            $this->remaining = floor($totalDuration - ($totalDuration * $percent));
+            $this->rate = floor($rate);
+        }
+
+        $this->percent = floor($percent * 100);
+        $this->lastOutput = $currentTime;
+        $this->currentSize = (int) $currentSize;
+        $this->currentTime = $currentDuration;
+
+        return $this->getProgressInfo();
+    }
+
+    /**
+     *
+     * @param string $rawDuration in the format 00:00:00.00
+     * @return number
+     */
+    protected function convertDuration($rawDuration)
+    {
+        $ar = array_reverse(explode(":", $rawDuration));
+        $duration = floatval($ar[0]);
+        if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
+        if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;
+
+        return $duration;
+    }
+
+    /**
+     * @return array
+     */
+    public function getProgressInfo()
+    {
+        if ($this->remaining === null) {
+            return null;
+        }
+
+        return array(
+            /*
+            'currentSize' => $this->currentSize,
+            'currentTime' => $this->currentTime,
+            */
+            'percent' => $this->percent,
+            'remaining' => $this->remaining,
+            'rate' => $this->rate
+        );
+    }
+
+    /**
+     * @return number
+     */
+    protected function microtimeFloat()
+    {
+        list($usec, $sec) = explode(" ", microtime());
+        return ((float)$usec + (float)$sec);
+    }
+
+    /**
+     * Get the regex pattern to match a ffmpeg stderr status line
+     */
+    abstract function getPattern();
+
+}
diff --git a/src/FFMpeg/Helper/VideoProgressHelper.php b/src/FFMpeg/Helper/VideoProgressHelper.php
new file mode 100644
index 0000000..7322abf
--- /dev/null
+++ b/src/FFMpeg/Helper/VideoProgressHelper.php
@@ -0,0 +1,29 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace FFMpeg\Helper;
+
+/**
+ * Parses ffmpeg stderr progress information for video files. An example:
+ *
+ * 
+ *       frame=  171 fps=0.0 q=10.0 size=      18kB time=00:00:05.72 bitrate=  26.4kbits/s dup=8 drop=0
+ * 
+ *
+ * @author Robert Gruendler 
+ */
+class VideoProgressHelper extends ProgressHelper
+{
+    public function getPattern()
+    {
+        return '/size=(.*?) time=(.*?) /';
+    }
+}
diff --git a/tests/src/FFMpeg/Progress/ProgressTest.php b/tests/src/FFMpeg/Progress/ProgressTest.php
new file mode 100644
index 0000000..bd20f2f
--- /dev/null
+++ b/tests/src/FFMpeg/Progress/ProgressTest.php
@@ -0,0 +1,70 @@
+object->open(__DIR__ . '/../../../files/Audio.mp3');
+        $this->object->attachHelper($audioProgress);
+        $this->object->encode(new Mp3(), $dest);
+
+        $this->assertGreaterThanOrEqual(3, $progressInfo);
+    }
+
+    /**
+     * @covers FFMpeg\Helper\AudioProgressHelper::getPattern
+     */
+    public function testAudioProgressHelper()
+    {
+        $audioProgress = new AudioProgressHelper(function($percent, $remaining, $rate) { });
+        $audioProgress->setDuration(500);
+
+        $line = "size=     712kB time=00:00:45.50 bitrate= 128.1kbits/s";
+        $audioProgress->parseProgress($line);
+
+        sleep(1);
+
+        $line = "size=     4712kB time=00:01:45.50 bitrate= 128.1kbits/s";
+        $progress = $audioProgress->parseProgress($line);
+
+        $this->assertEquals('21.0', $progress['percent']);
+    }
+
+    /**
+     * @covers FFMpeg\Helper\VideoProgressHelper::getPattern
+     */
+    public function testVideoProgress()
+    {
+        $videoProgress = new VideoProgressHelper(function($percent, $remaining, $rate) {});
+        $videoProgress->setDuration(500);
+
+        $line = "frame=  206 fps=202 q=10.0 size=     571kB time=00:00:07.12 bitrate= 656.8kbits/s dup=9 drop=0";
+        $videoProgress->parseProgress($line);
+
+        sleep(1);
+
+        $line = "frame=  854 fps=113 q=20.0 size=    4430kB time=00:00:33.04 bitrate=1098.5kbits/s dup=36 drop=0";
+        $progress = $videoProgress->parseProgress($line);
+
+        $this->assertEquals('6.0', $progress['percent']);
+    }
+}