diff options
| author | Jonas Kohl | 2024-10-10 17:33:13 +0200 | 
|---|---|---|
| committer | Jonas Kohl | 2024-10-10 17:33:13 +0200 | 
| commit | 64b1ec0fabbf7328a79a20ff58502ebfa80fad8b (patch) | |
| tree | 88f2281295b347bdd3beee5bc45f68314f2051dc /src/application/actions/thumb | |
| parent | 4ffc399a847ce4f328d4f14adebb48d06ad033f9 (diff) | |
Break up actions into individual files
Diffstat (limited to 'src/application/actions/thumb')
| -rw-r--r-- | src/application/actions/thumb/get.php | 101 | 
1 files changed, 101 insertions, 0 deletions
| diff --git a/src/application/actions/thumb/get.php b/src/application/actions/thumb/get.php new file mode 100644 index 0000000..c34bf92 --- /dev/null +++ b/src/application/actions/thumb/get.php @@ -0,0 +1,101 @@ +<?php + +use FFMpeg\Coordinate\TimeCode; +use FFMpeg\FFMpeg; +use FFMpeg\FFProbe; +use mystic\forum\orm\Attachment; + +$attId = $_GET["attachment"] ?? throw new Exception("Missing attachment id"); +$attachment = new Attachment(); +$attachment->id = $attId; +if (!$db->fetch($attachment)) { +    http_response_code(404); +    msg_error(__("No attachment exists with this id")); +    exit; +} + +$isImage = str_starts_with($attachment->mimeType, "image/"); +$isVideo = str_starts_with($attachment->mimeType, "video/"); + +if (!$isImage && !$isVideo) { +    http_response_code(400); +    msg_error(__("Attachment is neither an image nor a video")); +    exit; +} + +$contentHash = hash("sha256", $attachment->contents); + +$cacheId = bin2hex($attachment->id); +$cacheDir = sys_get_temp_dir() . "/mystic/forum/0/cache/thumbs/" . substr($cacheId, 0, 2) . "/" . substr($cacheId, 0, 8) . "/"; +if (!is_dir($cacheDir)) +    mkdir($cacheDir, recursive: true); + +$cacheFileData = $cacheDir . $cacheId . ".data"; +$cacheFileInfo = $cacheDir . $cacheId . ".info"; + +if (is_file($cacheFileData) && is_file($cacheFileInfo)) { +    $info = json_decode(file_get_contents($cacheFileInfo)); +    if ($info->contentHash === $contentHash) { +        header("Content-Type: image/jpeg"); +        header("Cache-Control: max-age=86400"); +        //header("X-Debug-Content: $cacheFileData"); +        readfile($cacheFileData); +        exit; +    } +} + +if ($isVideo) { +    $suffix = (microtime(true) * 1000) . "-" . random_int(0, 99999); +    $tempVid = sys_get_temp_dir() . "/video_" . $suffix; +    file_put_contents($tempVid, $attachment->contents); +    $tempImg = sys_get_temp_dir() . "/image_" . $suffix . ".jpg"; + +    try { +        $ffprobe = FFProbe::create(); +        /** @var string $duration */ +        $duration = $ffprobe +            ->format($tempVid) +            ->get("duration", "0"); + +        $screenshotFramePoint = TimeCode::fromSeconds(floatval($duration) / 2.0); +         +        $ffmpeg = FFMpeg::create(); +        $video = $ffmpeg->open($tempVid); +        $screenshot = $video +            ->frame($screenshotFramePoint) +            ->save($tempImg); +        $im = imagecreatefromjpeg($tempImg); +    } finally { +        if (is_file($tempVid)) unlink($tempVid); +        if (is_file($tempImg)) unlink($tempImg); +    } +} elseif ($isImage) { +    $im = imagecreatefromstring($attachment->contents); +} + +$w = imagesx($im); +$h = imagesy($im); +$r = $w / floatval($h); + +if ($w > $h) { +    $nw = THUMB_MAX_DIM; +    $nh = floor($nw / $r); +} else { +    $nh = THUMB_MAX_DIM; +    $nw = floor($r * $nh); +} + +$thumb = imagecreatetruecolor($nw, $nh); +imagecopyresampled($thumb, $im, 0, 0, 0, 0, $nw, $nh, $w, $h); +imagedestroy($im); + +header("Content-Type: image/jpeg"); +header("Cache-Control: max-age=86400"); +imagejpeg($thumb, $cacheFileData, 40); +imagedestroy($thumb); +file_put_contents($cacheFileInfo, json_encode([ +    "format" => 1, +    "contentHash" => $contentHash, +    "created" => time(), +], JSON_UNESCAPED_SLASHES)); +readfile($cacheFileData); |