diff --git a/README.md b/README.md
index b54efcc..3c99199 100644
--- a/README.md
+++ b/README.md
@@ -79,9 +79,12 @@ support in mind.
- Moderate posts by visiting the management panel.
- To allow video uploads:
- Ensure your web host is running Linux.
- - Install [mediainfo](https://mediaarea.net/en/MediaInfo) and [ffmpegthumbnailer](https://code.google.com/p/ffmpegthumbnailer/). On Ubuntu, run ``sudo apt-get install mediainfo ffmpegthumbnailer``.
+ - Install [ffmpeg](https://ffmpeg.org). On Ubuntu, run ``sudo apt-get install ffmpeg``.
- Add desired video file types to ``$tinyib_uploads``.
- To remove the play icon from .SWF and .WebM thumbnails, delete or rename **video_overlay.png**
+ - To use FFMPEG to create thumbnails:
+ - Install FFMPEG and ensure the ``ffmpeg`` and ``ffprobe`` commands are available.
+ - Set ``TINYIB_THUMBNAIL`` to ``ffmpeg``.
- To use ImageMagick instead of GD when creating thumbnails:
- Install ImageMagick and ensure that the ``convert`` command is available.
- Set ``TINYIB_THUMBNAIL`` to ``imagemagick``.
diff --git a/imgboard.php b/imgboard.php
index 263af55..2541646 100644
--- a/imgboard.php
+++ b/imgboard.php
@@ -38,8 +38,7 @@ while (ob_get_level() > 0) {
ob_end_flush();
}
-function fancyDie($message)
-{
+function fancyDie($message) {
$back = 'Click here to go back';
if (function_exists('__')) {
$back = __('Click here to go back');
@@ -55,8 +54,7 @@ require 'inc/defines.php';
global $tinyib_capcodes, $tinyib_embeds, $tinyib_hidefields, $tinyib_hidefieldsop;
if (!defined('TINYIB_LOCALE') || TINYIB_LOCALE == '') {
- function __($string)
- {
+ function __($string) {
return $string;
}
} else {
diff --git a/inc/functions.php b/inc/functions.php
index 787e196..4e958f5 100644
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -469,6 +469,67 @@ function thumbnailDimensions($post) {
return ($post['image_width'] > $max_width || $post['image_height'] > $max_height) ? array($max_width, $max_height) : array($post['image_width'], $post['image_height']);
}
+function videoDimensions($file_location) {
+ $discard = '';
+ $exit_status = 1;
+ exec("ffprobe -version", $discard, $exit_status);
+ if ($exit_status != 0) {
+ fancyDie('FFMPEG is not installed, or the commands ffmpeg and ffprobe are not in the server\'s $PATH.
Install FFMPEG, or set TINYIB_THUMBNAIL to \'gd\' or \'imagemagick\'.');
+ }
+
+ $dimensions = '';
+ $exit_status = 1;
+ exec("ffprobe -hide_banner -loglevel error -of csv=p=0 -show_entries stream=width,height $file_location", $dimensions, $exit_status);
+ if ($exit_status != 0) {
+ return array(0, 0);
+ }
+ if (is_array($dimensions)) {
+ $dimensions = $dimensions[0];
+ }
+ $split = explode(',', $dimensions);
+ if (count($split) != 2) {
+ return array(0, 0);
+ }
+ return array(intval($split[0]), intval($split[1]));
+}
+
+function videoDuration($file_location) {
+ $discard = '';
+ $exit_status = 1;
+ exec("ffprobe -version", $discard, $exit_status);
+ if ($exit_status != 0) {
+ fancyDie('FFMPEG is not installed, or the commands ffmpeg and ffprobe are not in the server\'s $PATH.
Install FFMPEG, or set TINYIB_THUMBNAIL to \'gd\' or \'imagemagick\'.');
+ }
+
+ $duration = '';
+ $exit_status = 1;
+ exec("ffprobe -hide_banner -loglevel error -of csv=p=0 -show_entries format=duration $file_location", $duration, $exit_status);
+ if ($exit_status != 0) {
+ return 0;
+ }
+ if (is_array($duration)) {
+ $duration = $duration[0];
+ }
+ return floatval($duration);
+}
+
+function ffmpegThumbnail($file_location, $thumb_location, $new_w, $new_h) {
+ $discard = '';
+ $exit_status = 1;
+ exec("ffmpeg -version", $discard, $exit_status);
+ if ($exit_status != 0) {
+ fancyDie('FFMPEG is not installed, or the commands ffmpeg and ffprobe are not in the server\'s $PATH.
Install FFMPEG, or set TINYIB_THUMBNAIL to \'gd\' or \'imagemagick\'.');
+ }
+
+ $quarter = videoDuration($file_location) / 4;
+
+ $exit_status = 1;
+ exec("ffmpeg -hide_banner -loglevel error -ss $quarter -i $file_location -frames:v 1 -vf \"thumbnail,scale='if(gt(iw,ih),$new_w,trunc(oh*a/2)*2)':'if(gt(iw,ih),trunc(ow/a/2)*2,$new_h)'\" $thumb_location", $discard, $exit_status);
+ if ($exit_status != 0) {
+ return false;
+ }
+}
+
function createThumbnail($file_location, $thumb_location, $new_w, $new_h) {
if (TINYIB_THUMBNAIL == 'gd') {
$system = explode(".", $thumb_location);
@@ -523,13 +584,15 @@ function createThumbnail($file_location, $thumb_location, $new_w, $new_h) {
imagedestroy($dst_img);
imagedestroy($src_img);
+ } else if (TINYIB_THUMBNAIL == 'ffmpeg') {
+ ffmpegThumbnail($file_location, $thumb_location, $new_w, $new_h);
} else { // ImageMagick
$discard = '';
$exit_status = 1;
exec("convert -version", $discard, $exit_status);
if ($exit_status != 0) {
- fancyDie('ImageMagick is not installed, or the convert command is not in the server\'s $PATH.
Install ImageMagick, or set TINYIB_THUMBNAIL to \'gd\'.');
+ fancyDie('ImageMagick is not installed, or the convert command is not in the server\'s $PATH.
Install ImageMagick, or set TINYIB_THUMBNAIL to \'gd\' or \'ffmpeg\'.');
}
$exit_status = 1;
@@ -575,7 +638,7 @@ function addVideoOverlay($thumb_location) {
return;
}
- if (TINYIB_THUMBNAIL == 'gd') {
+ if (TINYIB_THUMBNAIL == 'gd' || TINYIB_THUMBNAIL == 'ffmpeg') {
if (substr($thumb_location, -4) == ".jpg") {
$thumbnail = imagecreatefromjpeg($thumb_location);
} else {
@@ -721,13 +784,12 @@ function attachFile($post, $filepath, $filename, $uploaded) {
}
if ($file_mime == 'audio/webm' || $file_mime == 'video/webm' || $file_mime == 'audio/mp4' || $file_mime == 'video/mp4') {
- $post['image_width'] = max(0, intval(shell_exec('mediainfo --Inform="Video;%Width%" ' . $file_location)));
- $post['image_height'] = max(0, intval(shell_exec('mediainfo --Inform="Video;%Height%" ' . $file_location)));
+ list($post['image_width'], $post['image_height']) = videoDimensions($file_location);
if ($post['image_width'] > 0 && $post['image_height'] > 0) {
list($thumb_maxwidth, $thumb_maxheight) = thumbnailDimensions($post);
$post['thumb'] = $file_name . 's.jpg';
- shell_exec("ffmpegthumbnailer -s " . max($thumb_maxwidth, $thumb_maxheight) . " -i $file_location -o thumb/{$post['thumb']}");
+ ffmpegThumbnail($file_location, 'thumb/' . $post['thumb'], $thumb_maxwidth, $thumb_maxheight);
$thumb_info = getimagesize('thumb/' . $post['thumb']);
$post['thumb_width'] = $thumb_info[0];
@@ -742,7 +804,7 @@ function attachFile($post, $filepath, $filename, $uploaded) {
addVideoOverlay('thumb/' . $post['thumb']);
}
- $duration = intval(shell_exec('mediainfo --Inform="General;%Duration%" ' . $file_location));
+ $duration = videoDuration($file_location);
if ($duration > 0) {
$mins = floor(round($duration / 1000) / 60);
$secs = str_pad(floor(round($duration / 1000) % 60), 2, '0', STR_PAD_LEFT);
diff --git a/settings.default.php b/settings.default.php
index 4098ade..3a4ede1 100644
--- a/settings.default.php
+++ b/settings.default.php
@@ -76,7 +76,7 @@ $tinyib_uploads = array('image/jpeg' => array('jpg'),
// 'audio/mp4' => array('mp4');
// 'audio/wav' => array('wav');
// 'audio/webm' => array('webm');
-// 'video/mp4' => array('mp4'); // Video uploads require mediainfo and ffmpegthumbnailer (see README for instructions)
+// 'video/mp4' => array('mp4'); // Video uploads require ffmpeg (see README for instructions)
// 'video/webm' => array('webm');
// oEmbed APIs
@@ -88,7 +88,7 @@ $tinyib_embeds = array('SoundCloud' => 'https://soundcloud.com/oembed?format=jso
// File control
define('TINYIB_MAXKB', 2048); // Maximum file size in kilobytes [0 to disable]
define('TINYIB_MAXKBDESC', '2 MB'); // Human-readable representation of the maximum file size
-define('TINYIB_THUMBNAIL', 'gd'); // Thumbnail method to use: gd / imagemagick (see README for instructions)
+define('TINYIB_THUMBNAIL', 'gd'); // Thumbnail method to use: gd / ffmpeg / imagemagick (see README for instructions)
define('TINYIB_UPLOADVIAURL', false); // Allow files to be uploaded via URL
define('TINYIB_NOFILEOK', false); // Allow the creation of new threads without uploading a file