mirror of
https://github.com/Studio-42/elFinder
synced 2026-06-08 12:37:09 +00:00
[ui:cwd] fix #1433 create a thumbnail of the video file with ffmpeg
Added volume root options
```php
// Video to Image converters ['TYPE or MIME' => ['func' => function($file){ /* Converts $file to Image */ return true; }, 'maxlen' => (int)TransferLength]]
'imgConverter' => array(),
// Max length of transfer to image converter
'tmbVideoConvLen' => 10000000,
// Captre point seccond
'tmbVideoConvSec' => 6,
// Resource path of fallback icon images defailt: php/resouces
'resourcePath' => '',
```
It can specify a specific number of seconds part in the file name.
e.g.
xxx^[sec].[extention] -> video^3.mp4
This commit is contained in:
@@ -108,6 +108,13 @@ abstract class elFinderVolumeDriver {
|
||||
**/
|
||||
protected $imgLib = 'auto';
|
||||
|
||||
/**
|
||||
* Video to Image converter
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $imgConverter = array();
|
||||
|
||||
/**
|
||||
* Library to crypt files name
|
||||
*
|
||||
@@ -236,6 +243,14 @@ abstract class elFinderVolumeDriver {
|
||||
'imgLib' => 'auto',
|
||||
// Fallback self image to thumbnail (nothing imgLib)
|
||||
'tmbFbSelf' => true,
|
||||
// Video to Image converters ['TYPE or MIME' => ['func' => function($file){ /* Converts $file to Image */ return true; }, 'maxlen' => (int)TransferLength]]
|
||||
'imgConverter' => array(),
|
||||
// Max length of transfer to image converter
|
||||
'tmbVideoConvLen' => 10000000,
|
||||
// Captre point seccond
|
||||
'tmbVideoConvSec' => 6,
|
||||
// Resource path of fallback icon images defailt: php/resouces
|
||||
'resourcePath' => '',
|
||||
// Jpeg image saveing quality
|
||||
'jpgQuality' => 100,
|
||||
// on paste file - if true - old file will be replaced with new one, if false new file get name - original_name-number.ext
|
||||
@@ -656,6 +671,10 @@ abstract class elFinderVolumeDriver {
|
||||
$this->tmbPathWritable = is_writable($path);
|
||||
}
|
||||
}
|
||||
// set resouce path
|
||||
if (! is_dir($this->options['resourcePath'])) {
|
||||
$this->options['resourcePath'] = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'resources';
|
||||
}
|
||||
|
||||
// set image manipulation library
|
||||
$type = preg_match('/^(imagick|gd|convert|auto)$/i', $this->options['imgLib'])
|
||||
@@ -681,6 +700,28 @@ abstract class elFinderVolumeDriver {
|
||||
$this->imgLib = extension_loaded('imagick')? 'imagick' : (function_exists('gd_info')? 'gd' : '');
|
||||
}
|
||||
|
||||
// check video to img converter
|
||||
if (! empty($this->options['imgConverter']) && is_array($this->options['imgConverter'])) {
|
||||
foreach($this->options['imgConverter'] as $_type => $_converter) {
|
||||
if (isset($_converter['func'])) {
|
||||
$this->imgConverter[strtolower($_type)] = $_converter;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! isset($this->imgConverter['video'])) {
|
||||
$videoLibCache = 'videoLib';
|
||||
if (($videoLibCmd = $this->session->get($videoLibCache, false)) === false) {
|
||||
$videoLibCmd = ($this->procExec('ffmpeg -version') === 0)? 'ffmpeg' : '';
|
||||
$this->session->set($videoLibCache, $videoLibCmd);
|
||||
}
|
||||
if ($videoLibCmd) {
|
||||
$this->imgConverter['video'] = array(
|
||||
'func' => array($this, $videoLibCmd . 'ToImg'),
|
||||
'maxlen' => $this->options['tmbVideoConvLen']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// check archivers
|
||||
if (empty($this->archivers['create'])) {
|
||||
$this->disabled[] ='archive';
|
||||
@@ -1604,7 +1645,18 @@ abstract class elFinderVolumeDriver {
|
||||
$stat = $this->stat($path);
|
||||
|
||||
if (isset($stat['tmb'])) {
|
||||
return $stat['tmb'] == "1" ? $this->createTmb($path, $stat) : $stat['tmb'];
|
||||
$res = $stat['tmb'] == "1" ? $this->createTmb($path, $stat) : $stat['tmb'];
|
||||
if (! $res) {
|
||||
list($type) = explode('/', $stat['mime']);
|
||||
$fallback = $this->options['resourcePath'] . DIRECTORY_SEPARATOR . strtolower($type) . '.png';
|
||||
if (is_file($fallback)) {
|
||||
$res = $this->tmbname($stat);
|
||||
if (! copy($fallback, $this->tmbPath . DIRECTORY_SEPARATOR . $res)) {
|
||||
$res = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2625,6 +2677,34 @@ abstract class elFinderVolumeDriver {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Video To Image by ffmpeg
|
||||
*
|
||||
* @param $file video source file path
|
||||
* @param $stat file stat array
|
||||
* @return bool
|
||||
* @author Naoki Sawada
|
||||
*/
|
||||
public function ffmpegToImg($file, $stat) {
|
||||
$name = basename($file);
|
||||
$path = dirname($file);
|
||||
$tmp = $path . DIRECTORY_SEPARATOR . md5($name);
|
||||
$GLOBALS['elFinderTempFiles'][] = $tmp; // regist to remove at the end
|
||||
if (rename($file, $tmp)) {
|
||||
// specific start time by file name (xxx^[sec].[extention] - video^3.mp4)
|
||||
if (preg_match('/\^(\d+(?:\.\d+)?)\.[^.]+$/', $stat['name'], $_m)) {
|
||||
$ss = $_m[1];
|
||||
} else {
|
||||
$ss = $this->options['tmbVideoConvSec'];
|
||||
}
|
||||
$cmd = sprintf('ffmpeg -ss 00:00:%.3f -vframes 1 -i %s -f image2 %s', $ss, escapeshellarg($tmp), escapeshellarg($file));
|
||||
$r = $this->procExec($cmd);
|
||||
unlink($tmp);
|
||||
return ($r === 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save error message
|
||||
*
|
||||
@@ -4126,11 +4206,24 @@ abstract class elFinderVolumeDriver {
|
||||
* @author Dmitry (dio) Levashov
|
||||
**/
|
||||
protected function canCreateTmb($path, $stat, $checkTmbPath = true) {
|
||||
return (!$checkTmbPath || $this->tmbPathWritable)
|
||||
&& (!$this->tmbPath || strpos($path, $this->tmbPath) === false) // do not create thumnbnail for thumnbnail
|
||||
&& $this->imgLib
|
||||
&& strpos($stat['mime'], 'image') === 0
|
||||
&& ($this->imgLib == 'gd' ? in_array($stat['mime'], array('image/jpeg', 'image/png', 'image/gif', 'image/x-ms-bmp')) : true);
|
||||
if ((! $checkTmbPath || $this->tmbPathWritable)
|
||||
&& (! $this->tmbPath || strpos($path, $this->tmbPath) === false) // do not create thumnbnail for thumnbnail
|
||||
) {
|
||||
$mime = strtolower($stat['mime']);
|
||||
list($type) = explode('/', $mime);
|
||||
if (! empty($this->imgConverter)) {
|
||||
if (isset($this->imgConverter[$mime])) {
|
||||
return true;
|
||||
}
|
||||
if (isset($this->imgConverter[$type])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return $this->imgLib
|
||||
&& ($type === 'image')
|
||||
&& ($this->imgLib == 'gd' ? in_array($stat['mime'], array('image/jpeg', 'image/png', 'image/gif', 'image/x-ms-bmp')) : true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4163,6 +4256,27 @@ abstract class elFinderVolumeDriver {
|
||||
$name = $this->tmbname($stat);
|
||||
$tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
|
||||
|
||||
$maxlength = -1;
|
||||
$imgConverter = null;
|
||||
|
||||
// check imgConverter
|
||||
$mime = strtolower($stat['mime']);
|
||||
list($type) = explode('/', $mime);
|
||||
if (isset($this->imgConverter[$mime])) {
|
||||
$imgConverter = $this->imgConverter[$mime]['func'];
|
||||
if (! empty($this->imgConverter[$mime]['maxlen'])) {
|
||||
$maxlength = intval($this->imgConverter[$mime]['maxlen']);
|
||||
}
|
||||
} else if (isset($this->imgConverter[$type])) {
|
||||
$imgConverter = $this->imgConverter[$type]['func'];
|
||||
if (! empty($this->imgConverter[$type]['maxlen'])) {
|
||||
$maxlength = intval($this->imgConverter[$type]['maxlen']);
|
||||
}
|
||||
}
|
||||
if ($imgConverter && ! is_callable($imgConverter)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy image into tmbPath so some drivers does not store files on local fs
|
||||
if (($src = $this->fopenCE($path, 'rb')) == false) {
|
||||
return false;
|
||||
@@ -4173,13 +4287,19 @@ abstract class elFinderVolumeDriver {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!feof($src)) {
|
||||
fwrite($trg, fread($src, 8192));
|
||||
}
|
||||
stream_copy_to_stream($src, $trg, $maxlength);
|
||||
|
||||
$this->fcloseCE($src, $path);
|
||||
fclose($trg);
|
||||
|
||||
// call imgConverter
|
||||
if ($imgConverter) {
|
||||
if (! call_user_func_array($imgConverter, array($tmb, $stat, $this))) {
|
||||
file_exists($tmb) && unlink($tmb);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$result = false;
|
||||
|
||||
$tmbSize = $this->tmbSize;
|
||||
@@ -4213,7 +4333,7 @@ abstract class elFinderVolumeDriver {
|
||||
} catch (Exception $e) {}
|
||||
}
|
||||
if (! $result) {
|
||||
unlink($tmb);
|
||||
file_exists($tmb) && unlink($tmb);
|
||||
return false;
|
||||
}
|
||||
$result = false;
|
||||
|
||||
Reference in New Issue
Block a user