add JPG preview generation for pages and update routing logic

This commit is contained in:
2026-05-17 21:04:49 +02:00
parent f8c10c9d53
commit ed7eeda24c
4 changed files with 179 additions and 21 deletions

View File

@@ -4,6 +4,100 @@ declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
/**
* Render a JPG preview for a generated page using a local headless browser.
*/
function renderPagePreview(string $seed, string $htmlFilePath): void
{
$previewDir = __DIR__ . '/previews';
if (! is_dir($previewDir)) {
mkdir($previewDir, 0775, true);
}
$realHtmlPath = realpath($htmlFilePath);
if ($realHtmlPath === false) {
return;
}
$pageUrl = 'file://' . $realHtmlPath;
$previewPngPath = $previewDir . '/' . $seed . '.png';
$previewJpgPath = $previewDir . '/' . $seed . '.jpg';
$browserCandidates = [
'/usr/bin/google-chrome',
'/usr/bin/google-chrome-stable',
'/usr/bin/chromium',
'/usr/bin/chromium-browser',
'google-chrome',
'google-chrome-stable',
'chromium',
'chromium-browser',
];
$browserBinary = null;
foreach ($browserCandidates as $candidate) {
$candidatePath = null;
if (str_starts_with($candidate, '/')) {
if (! is_executable($candidate)) {
continue;
}
$candidatePath = $candidate;
} else {
$pathOut = [];
$pathExitCode = 1;
exec('command -v ' . escapeshellarg($candidate) . ' 2>/dev/null', $pathOut, $pathExitCode);
if ($pathExitCode !== 0 || ! isset($pathOut[0]) || $pathOut[0] === '') {
continue;
}
$candidatePath = $pathOut[0];
}
$versionOut = [];
$versionExitCode = 1;
exec(escapeshellarg($candidatePath) . ' --version 2>/dev/null', $versionOut, $versionExitCode);
if ($versionExitCode === 0) {
$browserBinary = $candidatePath;
break;
}
}
if ($browserBinary === null) {
return;
}
$command = sprintf(
'%s --headless --disable-gpu --no-sandbox --disable-dev-shm-usage --hide-scrollbars --window-size=1440,900 --screenshot=%s --virtual-time-budget=8000 --run-all-compositor-stages-before-draw %s 2>/dev/null',
escapeshellarg($browserBinary),
escapeshellarg($previewPngPath),
escapeshellarg($pageUrl)
);
$output = [];
$exitCode = 1;
exec($command, $output, $exitCode);
if ($exitCode !== 0 || ! file_exists($previewPngPath)) {
@unlink($previewPngPath);
return;
}
if (function_exists('imagecreatefrompng') && function_exists('imagejpeg')) {
$image = @imagecreatefrompng($previewPngPath);
if ($image !== false) {
imagejpeg($image, $previewJpgPath, 85);
imagedestroy($image);
}
}
if (file_exists($previewJpgPath)) {
@unlink($previewPngPath);
} else {
// Keep PNG as fallback if JPG conversion is unavailable.
@rename($previewPngPath, $previewJpgPath);
}
}
header('Content-Type: text/html; charset=UTF-8');
$startedAt = microtime(true);
@@ -138,7 +232,9 @@ try {
//echo $html;
file_put_contents(__DIR__ . '/../pages/' . $seed . '.html', $html);
$htmlPath = __DIR__ . '/../pages/' . $seed . '.html';
file_put_contents($htmlPath, $html);
renderPagePreview($seed, $htmlPath);
} catch (Throwable $e) {
http_response_code(500);