From 413a48e8bb633d159452ad39fec01543662fae08 Mon Sep 17 00:00:00 2001 From: flashwave Date: Wed, 25 Jan 2023 22:27:40 +0000 Subject: [PATCH] Added thumbnailing for audio covers and external videos. --- .gitignore | 1 + lib/index | 2 +- src/Apis/v1_0.php | 42 +++++++++++++++++++++++++++++ src/FFMPEG.php | 17 ++++++++++++ src/Lookup/WebLookupMediaResult.php | 10 +++++-- uiharu.php | 5 +++- 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 16608fe..5a5d9ad 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /.debug /config.ini /public/robots.txt +/lib/index-dev diff --git a/lib/index b/lib/index index 99a4e0c..1a8344c 160000 --- a/lib/index +++ b/lib/index @@ -1 +1 @@ -Subproject commit 99a4e0c3027a7b29c58e0e0164cb831a03461527 +Subproject commit 1a8344c1c31cb62726305d079384045582315f64 diff --git a/src/Apis/v1_0.php b/src/Apis/v1_0.php index c2764cd..e95cbca 100644 --- a/src/Apis/v1_0.php +++ b/src/Apis/v1_0.php @@ -41,6 +41,48 @@ final class v1_0 implements \Uiharu\IApi { $router->post('/metadata', [$this, 'postMetadata']); $router->get('/metadata/batch', [$this, 'getMetadataBatch']); $router->post('/metadata/batch', [$this, 'postMetadataBatch']); + $router->get('/metadata/thumb/audio', [$this, 'getThumbAudio']); + $router->get('/metadata/thumb/video', [$this, 'getThumbVideo']); + } + + public function getThumbAudio($response, $request) { + $targetUrl = (string)$request->getParam('url'); + + if(empty($targetUrl)) + return 400; + + try { + $parsedUrl = Url::parse($targetUrl); + } catch(InvalidArgumentException $ex) { + return 404; + } + + if(!$parsedUrl->isWeb()) + return 400; + + $response->setContentType('image/png'); + $response->setCacheControl('public', 'max-age=31536000', 'immutable'); + $response->setContent(FFMPEG::grabFirstAudioCover($parsedUrl)); + } + + public function getThumbVideo($response, $request) { + $targetUrl = (string)$request->getParam('url'); + + if(empty($targetUrl)) + return 400; + + try { + $parsedUrl = Url::parse($targetUrl); + } catch(InvalidArgumentException $ex) { + return 404; + } + + if(!$parsedUrl->isWeb()) + return 400; + + $response->setContentType('image/png'); + $response->setCacheControl('public', 'max-age=31536000', 'immutable'); + $response->setContent(FFMPEG::grabFirstVideoFrame($parsedUrl)); } public function getMetadata($response, $request) { diff --git a/src/FFMPEG.php b/src/FFMPEG.php index 252f923..629edd4 100644 --- a/src/FFMPEG.php +++ b/src/FFMPEG.php @@ -2,8 +2,25 @@ namespace Uiharu; use stdClass; +use Imagick; +use Index\IO\Stream; +use Index\IO\ProcessStream; final class FFMPEG { + public static function grabFirstVideoFrame(string $url): Stream { + return new ProcessStream( + sprintf('ffmpeg -i %s -ss 00:00:00.000 -vframes 1 -c:v png -f image2pipe -', escapeshellarg($url)), + 'rb' + ); + } + + public static function grabFirstAudioCover(string $url): Stream { + return new ProcessStream( + sprintf('ffmpeg -i %s -an -c:v png -f image2pipe -', escapeshellarg($url)), + 'rb' + ); + } + public static function probe(string $url): ?object { return json_decode( shell_exec( diff --git a/src/Lookup/WebLookupMediaResult.php b/src/Lookup/WebLookupMediaResult.php index a4b18cf..9242388 100644 --- a/src/Lookup/WebLookupMediaResult.php +++ b/src/Lookup/WebLookupMediaResult.php @@ -68,10 +68,16 @@ class WebLookupMediaResult extends WebLookupResult implements \Uiharu\IHasMediaI } public function hasPreviewImage(): bool { - return $this->isImage(); + return $this->isImage() || $this->isVideo() || $this->isAudio(); } public function getPreviewImage(): string { - return (string)$this->url; + $url = (string)$this->url; + if($this->isVideo()) + return '//' . $_SERVER['HTTP_HOST'] . '/metadata/thumb/video?url=' . rawurlencode($url); + if($this->isAudio()) + return '//' . $_SERVER['HTTP_HOST'] . '/metadata/thumb/audio?url=' . rawurlencode($url); + + return $url; } public function getConfidence(): float { diff --git a/uiharu.php b/uiharu.php index e45ebcf..0ff1574 100644 --- a/uiharu.php +++ b/uiharu.php @@ -14,7 +14,10 @@ define('UIH_SOURCE', UIH_ROOT . '/src'); define('UIH_LIBRARY', UIH_ROOT . '/lib'); define('UIH_VERSION', '20230125'); -require_once UIH_LIBRARY . '/index/index.php'; +define('UIH_NDX_PATH', UIH_LIBRARY . '/index'); +define('UIH_NDX_PATH_DEV', UIH_LIBRARY . '/index-dev'); + +require_once (UIH_DEBUG && is_dir(UIH_NDX_PATH_DEV) ? UIH_NDX_PATH_DEV : UIH_NDX_PATH) . '/index.php'; Autoloader::addNamespace(__NAMESPACE__, UIH_SOURCE); Environment::setDebug(UIH_DEBUG);