From 0c6af5511225aabadf626b279200671aa3e1a4ca Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 8 Nov 2013 12:09:58 +0100 Subject: [PATCH 1/4] Added ffmpeg fallback when avconv is not available On some distros, avconv isn't available yet. This fix adds a fallback to ffmpeg. When none is found, no error message is displayed in the console any more. Fixes #5745 Also, this now uses exec() instead of shell_exec() to be able to get the return code. The binary path found with "which" is now used to prevent further FS binary lookup when running the commands. Moved the "-ss" parameter before "-i" for ffmpeg. --- lib/private/preview/movies.php | 56 +++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index 4d85e23c63..5c6a156d35 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -8,21 +8,37 @@ */ namespace OC\Preview; +function findBinaryPath($program) { + exec('which ' . escapeshellarg($program) . ' 2> /dev/null', $output, $returnCode); + if ($returnCode === 0 && count($output) > 0) { + return escapeshellcmd($output[0]); + } + return null; +} + // movie preview is currently not supported on Windows if (!\OC_Util::runningOnWindows()) { - $isShellExecEnabled = !in_array('shell_exec', explode(', ', ini_get('disable_functions'))); - $whichAVCONV = ($isShellExecEnabled ? shell_exec('which avconv') : ''); - $isAVCONVAvailable = !empty($whichAVCONV); + $isExecEnabled = !in_array('exec', explode(', ', ini_get('disable_functions'))); - if($isShellExecEnabled && $isAVCONVAvailable) { + if ($isExecEnabled) { + $avconvBinary = findBinaryPath('avconv'); + if (!$avconvBinary) { + $ffmpegBinary = findBinaryPath('ffmpeg'); + } + } + + if($isExecEnabled && ( $avconvBinary || $ffmpegBinary )) { class Movie extends Provider { + public static $avconvBinary; + public static $ffmpegBinary; public function getMimeType() { return '/video\/.*/'; } public function getThumbnail($path, $maxX, $maxY, $scalingup, $fileview) { + // TODO: use proc_open() and stream the source file ? $absPath = \OC_Helper::tmpFile(); $tmpPath = \OC_Helper::tmpFile(); @@ -31,20 +47,38 @@ if (!\OC_Util::runningOnWindows()) { $firstmb = stream_get_contents($handle, 1048576); //1024 * 1024 = 1048576 file_put_contents($absPath, $firstmb); - //$cmd = 'ffmpeg -y -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 -ss 1 -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . ' ' . $tmpPath; - $cmd = 'avconv -an -y -ss 1 -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 ' . escapeshellarg($tmpPath); + if (self::$avconvBinary) { + $cmd = self::$avconvBinary . ' -an -y -ss 1'. + ' -i ' . escapeshellarg($absPath) . + ' -f mjpeg -vframes 1 ' . escapeshellarg($tmpPath) . + ' > /dev/null 2>&1'; + } + else { + $cmd = self::$ffmpegBinary . ' -y -ss 1' . + ' -i ' . escapeshellarg($absPath) . + ' -f mjpeg -vframes 1' . + ' -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . + ' ' . $tmpPath . + ' > /dev/null 2>&1'; + } - shell_exec($cmd); - - $image = new \OC_Image($tmpPath); + exec($cmd, $output, $returnCode); unlink($absPath); - unlink($tmpPath); - return $image->valid() ? $image : false; + if ($returnCode === 0) { + $image = new \OC_Image($tmpPath); + unlink($tmpPath); + return $image->valid() ? $image : false; + } + return false; } } + // a bit hacky but didn't want to use subclasses + Movie::$avconvBinary = $avconvBinary; + Movie::$ffmpegBinary = $ffmpegBinary; + \OC\Preview::registerProvider('OC\Preview\Movie'); } } From 4b5083e3ca573bc4e57e253b7e4229d63cb4ccc9 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 8 Nov 2013 12:27:53 +0100 Subject: [PATCH 2/4] Fixed the rebellous space, replaced with a tab --- lib/private/preview/movies.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index 5c6a156d35..3ba3bdf120 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -49,7 +49,7 @@ if (!\OC_Util::runningOnWindows()) { if (self::$avconvBinary) { $cmd = self::$avconvBinary . ' -an -y -ss 1'. - ' -i ' . escapeshellarg($absPath) . + ' -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1 ' . escapeshellarg($tmpPath) . ' > /dev/null 2>&1'; } From df288605d4b9bf6996830df981a52b0058b95a24 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Sun, 10 Nov 2013 11:46:46 +0100 Subject: [PATCH 3/4] Fixed undefined variable error when using avconv --- lib/private/preview/movies.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index 3ba3bdf120..7c9f009a9c 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -19,6 +19,8 @@ function findBinaryPath($program) { // movie preview is currently not supported on Windows if (!\OC_Util::runningOnWindows()) { $isExecEnabled = !in_array('exec', explode(', ', ini_get('disable_functions'))); + $ffmpegBinary = null; + $avconvBinary = null; if ($isExecEnabled) { $avconvBinary = findBinaryPath('avconv'); From 99ee95d46c3e14cb902493df3201a2c1ad9d6dc5 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Mon, 11 Nov 2013 15:41:03 +0100 Subject: [PATCH 4/4] Added missing escaping --- lib/private/preview/movies.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/private/preview/movies.php b/lib/private/preview/movies.php index 7c9f009a9c..7e012ec44a 100644 --- a/lib/private/preview/movies.php +++ b/lib/private/preview/movies.php @@ -60,7 +60,7 @@ if (!\OC_Util::runningOnWindows()) { ' -i ' . escapeshellarg($absPath) . ' -f mjpeg -vframes 1' . ' -s ' . escapeshellarg($maxX) . 'x' . escapeshellarg($maxY) . - ' ' . $tmpPath . + ' ' . escapeshellarg($tmpPath) . ' > /dev/null 2>&1'; }