summaryrefslogtreecommitdiff
path: root/inc/lib
diff options
context:
space:
mode:
authorMichael Walker <mike@barrucadu.co.uk>2015-09-12 21:03:54 +0100
committerMichael Walker <mike@barrucadu.co.uk>2015-09-12 21:03:54 +0100
commit166ba2a0a205c88bdb8fcc6fc538a0bdc01b60d9 (patch)
tree5a7293c0d78804f72e253e385d015162e029777b /inc/lib
parent05c569e656070f086de49d24749d4b18916975da (diff)
parent844b26216614d953ee8521838f1030ad59d735ec (diff)
Merge remote-tracking branch 'vichan/master'
Diffstat (limited to 'inc/lib')
-rw-r--r--inc/lib/webm/README.md7
-rw-r--r--inc/lib/webm/ffmpeg.php55
-rw-r--r--inc/lib/webm/posthandler.php19
3 files changed, 38 insertions, 43 deletions
diff --git a/inc/lib/webm/README.md b/inc/lib/webm/README.md
index dc3394c9..d1c2a52a 100644
--- a/inc/lib/webm/README.md
+++ b/inc/lib/webm/README.md
@@ -30,6 +30,13 @@ If you have an [FFmpeg](https://www.ffmpeg.org/) binary on your server and you w
$config['webm']['ffmpeg_path'] = '/path/to/ffmeg';
$config['webm']['ffprobe_path'] = '/path/to/ffprobe';
+MP4 support
+-----------
+
+MP4 support is available only if you use FFmpeg thumbnailing (see above).
+
+ $config['allowed_ext_files'][] = 'mp4';
+
License
-------
diff --git a/inc/lib/webm/ffmpeg.php b/inc/lib/webm/ffmpeg.php
index edd2c73a..0747b420 100644
--- a/inc/lib/webm/ffmpeg.php
+++ b/inc/lib/webm/ffmpeg.php
@@ -3,60 +3,63 @@
* ffmpeg.php
* A barebones ffmpeg based webm implementation for vichan.
*/
-
function get_webm_info($filename) {
global $board, $config;
-
$filename = escapeshellarg($filename);
$ffprobe = $config['webm']['ffprobe_path'];
$ffprobe_out = array();
$webminfo = array();
-
exec("$ffprobe -v quiet -print_format json -show_format -show_streams $filename", $ffprobe_out);
$ffprobe_out = json_decode(implode("\n", $ffprobe_out), 1);
$webminfo['error'] = is_valid_webm($ffprobe_out);
-
if(empty($webminfo['error'])) {
$webminfo['width'] = $ffprobe_out['streams'][0]['width'];
$webminfo['height'] = $ffprobe_out['streams'][0]['height'];
+ $webminfo['duration'] = $ffprobe_out['format']['duration'];
}
-
return $webminfo;
}
-
function is_valid_webm($ffprobe_out) {
global $board, $config;
-
if (empty($ffprobe_out))
return array('code' => 1, 'msg' => $config['error']['genwebmerror']);
-
- if ($ffprobe_out['format']['format_name'] != 'matroska,webm')
- return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
-
+ $extension = pathinfo($ffprobe_out['format']['filename'], PATHINFO_EXTENSION);
+ if ($extension === 'webm') {
+ if ($ffprobe_out['format']['format_name'] != 'matroska,webm')
+ return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
+ } elseif ($extension === 'mp4') {
+ if ($ffprobe_out['streams'][0]['codec_name'] != 'h264' && $ffprobe_out['streams'][1]['codec_name'] != 'aac')
+ return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
+ } else {
+ return array('code' => 1, 'msg' => $config['error']['genwebmerror']);
+ }
if ((count($ffprobe_out['streams']) > 1) && (!$config['webm']['allow_audio']))
return array('code' => 3, 'msg' => $config['error']['webmhasaudio']);
-
- if ($ffprobe_out['streams'][0]['codec_name'] != 'vp8')
- return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
-
if (empty($ffprobe_out['streams'][0]['width']) || (empty($ffprobe_out['streams'][0]['height'])))
return array('code' => 2, 'msg' => $config['error']['invalidwebm']);
-
if ($ffprobe_out['format']['duration'] > $config['webm']['max_length'])
- return array('code' => 4, 'msg' => $config['error']['webmtoolong']);
+ return array('code' => 4, 'msg' => sprintf($config['error']['webmtoolong'], $config['webm']['max_length']));
}
-
-function make_webm_thumbnail($filename, $thumbnail, $width, $height) {
+function make_webm_thumbnail($filename, $thumbnail, $width, $height, $duration) {
global $board, $config;
-
$filename = escapeshellarg($filename);
- $thumbnail = escapeshellarg($thumbnail); // Should be safe by default but you
+ $thumbnailfc = escapeshellarg($thumbnail); // Should be safe by default but you
// can never be too safe.
-
+ $width = escapeshellarg($width);
+ $height = escapeshellarg($height); // Same as above.
$ffmpeg = $config['webm']['ffmpeg_path'];
+ $ret = 0;
$ffmpeg_out = array();
-
- exec("$ffmpeg -i $filename -v quiet -ss 00:00:00 -an -vframes 1 -f mjpeg -vf scale=$width:$height $thumbnail 2>&1");
-
- return count($ffmpeg_out);
+ exec("$ffmpeg -strict -2 -ss " . floor($duration / 2) . " -i $filename -v quiet -an -vframes 1 -f mjpeg -vf scale=$width:$height $thumbnailfc 2>&1", $ffmpeg_out, $ret);
+ // Work around for https://trac.ffmpeg.org/ticket/4362
+ if (filesize($thumbnail) === 0) {
+ // try again with first frame
+ exec("$ffmpeg -y -strict -2 -ss 0 -i $filename -v quiet -an -vframes 1 -f mjpeg -vf scale=$width:$height $thumbnailfc 2>&1", $ffmpeg_out, $ret);
+ clearstatcache();
+ // failed if no thumbnail size even if ret code 0, ffmpeg is buggy
+ if (filesize($thumbnail) === 0) {
+ $ret = 1;
+ }
+ }
+ return $ret;
}
diff --git a/inc/lib/webm/posthandler.php b/inc/lib/webm/posthandler.php
index a5b7429b..15c6600d 100644
--- a/inc/lib/webm/posthandler.php
+++ b/inc/lib/webm/posthandler.php
@@ -1,27 +1,22 @@
<?php
// Glue code for handling a Tinyboard post.
// Portions of this file are derived from Tinyboard code.
-
function postHandler($post) {
global $board, $config;
-
- if ($post->has_file) foreach ($post->files as &$file) if ($file->extension == 'webm') {
+ if ($post->has_file) foreach ($post->files as &$file) if ($file->extension == 'webm' || $file->extension == 'mp4') {
if ($config['webm']['use_ffmpeg']) {
require_once dirname(__FILE__) . '/ffmpeg.php';
$webminfo = get_webm_info($file->file_path);
-
if (empty($webminfo['error'])) {
$file->width = $webminfo['width'];
$file->height = $webminfo['height'];
-
if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
$file = webm_set_spoiler($file);
}
else {
$file = set_thumbnail_dimensions($post, $file);
$tn_path = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.jpg';
-
- if(false == make_webm_thumbnail($file->file_path, $tn_path, $file->thumbwidth, $file->thumbheight)) {
+ if(0 == make_webm_thumbnail($file->file_path, $tn_path, $file->thumbwidth, $file->thumbheight, $webminfo['duration'])) {
$file->thumb = $file->file_id . '.jpg';
}
else {
@@ -37,7 +32,6 @@ function postHandler($post) {
require_once dirname(__FILE__) . '/videodata.php';
$videoDetails = videoData($file->file_path);
if (!isset($videoDetails['container']) || $videoDetails['container'] != 'webm') return "not a WebM file";
-
// Set thumbnail
$thumbName = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.webm';
if ($config['spoiler_images'] && isset($_POST['spoiler'])) {
@@ -53,12 +47,10 @@ function postHandler($post) {
$file->thumb = 'file';
}
unset($videoDetails['frame']);
-
// Set width and height
if (isset($videoDetails['width']) && isset($videoDetails['height'])) {
$file->width = $videoDetails['width'];
$file->height = $videoDetails['height'];
-
if ($file->thumb != 'file' && $file->thumb != 'spoiler') {
$file = set_thumbnail_dimensions($post, $file);
}
@@ -66,14 +58,11 @@ function postHandler($post) {
}
}
}
-
function set_thumbnail_dimensions($post,$file) {
global $board, $config;
-
$tn_dimensions = array();
$tn_maxw = $post->op ? $config['thumb_op_width'] : $config['thumb_width'];
$tn_maxh = $post->op ? $config['thumb_op_height'] : $config['thumb_height'];
-
if ($file->width > $tn_maxw || $file->height > $tn_maxh) {
$file->thumbwidth = min($tn_maxw, intval(round($file->width * $tn_maxh / $file->height)));
$file->thumbheight = min($tn_maxh, intval(round($file->height * $tn_maxw / $file->width)));
@@ -81,17 +70,13 @@ function set_thumbnail_dimensions($post,$file) {
$file->thumbwidth = $file->width;
$file->thumbheight = $file->height;
}
-
return $file;
}
-
function webm_set_spoiler($file) {
global $board, $config;
-
$file->thumb = 'spoiler';
$size = @getimagesize($config['spoiler_image']);
$file->thumbwidth = $size[0];
$file->thumbheight = $size[1];
-
return $file;
}