/**
* GNU social - a federating social network
*
- * Plugin to make thumbnails of video files with ffmpeg
+ * Plugin to make thumbnails of video files with ffmpeg/avconv
*
* PHP version 5
*
/*
* Dependencies:
- * php5-ffmpeg
+ * ffmpeg/avconv (external program call)
* php5-gd
*
- * Video support will depend on your ffmpeg.
+ * Todo:
+ * Make sure we support ffmpeg too, so we're not super Debian oriented.
+ *
+ * Video support will depend on your ffmpeg/avconv.
*/
class VideoThumbnailsPlugin extends Plugin
{
+ const PLUGIN_VERSION = '2.0.0';
+
/*
* This function should only extract an image from the video stream
* and disregard any cropping or scaling in the resulting file, as
* that will be handled in the core thumbnail algorithm.
*/
- public function onCreateFileImageThumbnailSource(MediaFile $file, &$imgPath, $media=null)
+ public function onCreateFileImageThumbnailSource(File $file, &$imgPath, $media=null)
{
// The calling function might accidentally pass application/ogg videos.
// If that's a problem, let's fix it in the calling function.
- if ($media !== 'video') {
+ if ($media !== 'video' || empty($file->filename)) {
return true;
}
- $movie = new ffmpeg_movie($file->getPath(), false);
-
- $frames = $movie->getFrameCount();
- if ($frames > 0) {
- $frame = $movie->getFrame(floor($frames/2));
- } else {
- $frame = $movie->getNextKeyFrame();
+ try {
+ // Exception thrown if no thumbnail found
+ $thumb = File_thumbnail::byFile($file, false);
+ $imgPath = $thumb->getPath();
+ // If getPath didn't throw an exception, we have a working locally stored thumbnail
+ return false;
+ } catch (NoResultException $e) {
+ // Alright, no thumbnail found, so let's create one.
+ } catch (InvalidFilenameException $e) {
+ // I guess this means $thumb->filename is null? Shouldn't happen because $file->filename is not null, so delete it
+ $thumb->delete();
+ } catch (FileNotFoundException $e) {
+ // Thumb file was not found, let's delete it.
+ $thumb->delete();
}
- // We failed to get a frame.
- if ($frame === null) {
+ // Let's save our frame to a temporary file. If we fail, remove it.
+ $tmp_imgPath = tempnam(sys_get_temp_dir(), 'socialthumb-');
+
+ $cmd = null;
+ if (shell_exec('which ffmpeg')) {
+ $cmd = 'ffmpeg';
+ } elseif (shell_exec('which avconv')) {
+ $cmd = 'avconv';
+ } else {
+ common_log(LOG_ERR, 'Neither ffmpeg nor avconv was found in your PATH. Cannot create video thumbnail.');
return true;
}
+ $fullcmd = $cmd.' -y -i '.escapeshellarg($file->getPath()).' -vcodec mjpeg -vframes 1 -f image2 -an '.escapeshellarg($tmp_imgPath);
+ common_debug(__METHOD__ . ' executing: '._ve($fullcmd));
+ $result = exec($fullcmd);
- // Let's save our frame to a temporary file. If we fail, remove it.
- $imgPath = tempnam(sys_get_temp_dir(), 'socialthumb');
- if (!imagejpeg($frame->toGDImage(), $imgPath)) {
- @unlink($imgPath);
+ if (!getimagesize($tmp_imgPath)) {
+ common_debug('exec of "avconv" produced a bad/nonexisting image it seems');
+ @unlink($tmp_imgPath);
return true;
}
+ $imgPath = $tmp_imgPath;
return false;
}
- public function onPluginVersion(&$versions)
+ public function onPluginVersion(array &$versions)
{
$versions[] = array('name' => 'Video Thumbnails',
- 'version' => GNUSOCIAL_VERSION,
+ 'version' => self::PLUGIN_VERSION,
'author' => 'Mikael Nordfeldth',
'homepage' => 'https://www.gnu.org/software/social/',
'rawdescription' =>