Added thumbnail support for videos and embedded covers in audio.

This commit is contained in:
flash 2020-05-30 23:49:59 +00:00
parent 5ab496b833
commit a6ef98210c
2 changed files with 79 additions and 39 deletions

View file

@ -132,6 +132,7 @@ if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})(\.t)?/?$#', $reqPath, $matches)) {
$uploadInfo->bumpExpiry();
}
$fileName = $uploadInfo->getName();
$contentType = $uploadInfo->getType();
if($contentType === 'application/octet-stream' || substr($contentType, 0, 5) === 'text/')
@ -139,49 +140,16 @@ if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})(\.t)?/?$#', $reqPath, $matches)) {
$sourceDir = basename($getThumbnail ? PRM_THUMBS : PRM_UPLOADS);
if($getThumbnail) {
if(substr($contentType, 0, 6) !== 'image/') {
http_response_code(404);
echo 'Thumbnails are not supported for this filetype.';
return;
}
try {
$imagick = new \Imagick($uploadInfo->getPath());
$imagick->setImageFormat('jpg');
$imagick->setImageCompressionQuality(40);
$thumbRes = 100;
$width = $imagick->getImageWidth();
$height = $imagick->getImageHeight();
if ($width > $height) {
$resizeWidth = $width * $thumbRes / $height;
$resizeHeight = $thumbRes;
} else {
$resizeWidth = $thumbRes;
$resizeHeight = $height * $thumbRes / $width;
}
$imagick->resizeImage(
$resizeWidth, $resizeHeight,
\Imagick::FILTER_GAUSSIAN, 0.7
);
$imagick->cropImage(
$thumbRes,
$thumbRes,
($resizeWidth - $thumbRes) / 2,
($resizeHeight - $thumbRes) / 2
);
$imagick->writeImage($uploadInfo->getThumbPath());
} catch(\Exception $ex) {}
if($getThumbnail && $uploadInfo->supportsThumbnail()) {
if(!is_file($uploadInfo->getThumbPath()))
$uploadInfo->createThumbnail();
$contentType = 'image/jpeg';
$fileName = pathinfo($fileName, PATHINFO_FILENAME) . '-thumb.jpg';
}
header(sprintf('X-Accel-Redirect: /%s/%s', $sourceDir, $uploadInfo->getId()));
header(sprintf('Content-Type: %s', $contentType));
header(sprintf('Content-Disposition: inline; filename="%s"', addslashes($uploadInfo->getName())));
header(sprintf('Content-Disposition: inline; filename="%s"', addslashes($fileName)));
return;
}

View file

@ -2,6 +2,7 @@
namespace EEPROM;
use Exception;
use Imagick;
use JsonSerializable;
class UploadNotFoundException extends Exception {};
@ -70,6 +71,15 @@ final class Upload implements JsonSerializable {
public function getType(): string {
return $this->upload_type ?? 'text/plain';
}
public function isImage(): bool {
return substr($this->getType(), 0, 6) === 'image/';
}
public function isVideo(): bool {
return substr($this->getType(), 0, 6) === 'video/';
}
public function isAudio(): bool {
return substr($this->getType(), 0, 6) === 'audio/';
}
public function getName(): string {
return $this->upload_name ?? '';
@ -387,4 +397,66 @@ final class Upload implements JsonSerializable {
return $out;
}
public function supportsThumbnail(): bool {
return $this->isImage() || $this->isAudio() || $this->isVideo();
}
public function createThumbnail(): void {
$tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'eeprom' . bin2hex(random_bytes(10)) . '.jpg';
try {
if($this->isImage())
$imagick = new Imagick($this->getPath());
elseif($this->isAudio())
$imagick = $this->getCoverFromAudio($tmpFile);
elseif($this->isVideo())
$imagick = $this->getFrameFromVideo($tmpFile);
if(!isset($imagick))
return;
$imagick->setImageFormat('jpg');
$imagick->setImageCompressionQuality(40);
$thumbRes = 100;
$width = $imagick->getImageWidth();
$height = $imagick->getImageHeight();
if ($width > $height) {
$resizeWidth = $width * $thumbRes / $height;
$resizeHeight = $thumbRes;
} else {
$resizeWidth = $thumbRes;
$resizeHeight = $height * $thumbRes / $width;
}
$imagick->resizeImage(
$resizeWidth, $resizeHeight,
Imagick::FILTER_GAUSSIAN, 0.7
);
$imagick->cropImage(
$thumbRes,
$thumbRes,
($resizeWidth - $thumbRes) / 2,
($resizeHeight - $thumbRes) / 2
);
$imagick->writeImage($this->getThumbPath());
} catch(Exception $ex) {}
if(is_file($tmpFile))
unlink($tmpFile);
}
private function getFrameFromVideo(string $path): Imagick {
shell_exec(sprintf('ffmpeg -i %s -ss 00:00:01.000 -vframes 1 %s', $this->getPath(), $path));
return new Imagick($path);
}
private function getCoverFromAudio(string $path): Imagick {
shell_exec(sprintf('ffmpeg -i %s -an -vcodec copy %s', $this->getPath(), $path));
return new Imagick($path);
}
}