39726-vm/process_conversion.php
2026-04-19 01:12:47 +00:00

125 lines
5.2 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/app.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: /');
exit;
}
try {
app_boot();
} catch (Throwable $e) {
notify_redirect('/', 'danger', 'The converter is not ready yet. Please try again in a moment.');
}
if (request_exceeds_upload_limit()) {
notify_redirect('/', 'warning', 'That upload is larger than the current ' . effective_upload_limit_mb() . ' MB limit. Please choose a smaller file.');
}
$toolKey = trim((string)($_POST['tool_key'] ?? 'webm_mp4'));
$catalog = tool_catalog();
if (!isset($catalog[$toolKey])) {
notify_redirect('/', 'warning', 'Please choose a supported conversion tool.');
}
$tool = $catalog[$toolKey];
if (!empty($tool['requires_ffmpeg']) && !ffmpeg_is_available()) {
notify_redirect('/', 'warning', 'FFmpeg is not available on the server yet, so this conversion tool is temporarily offline.');
}
$file = $_FILES['source_file'] ?? $_FILES['video_file'] ?? null;
if (!is_array($file)) {
notify_redirect('/', 'warning', 'Please choose a file to convert.');
}
$errorCode = (int) ($file['error'] ?? UPLOAD_ERR_NO_FILE);
if (in_array($errorCode, [UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE], true)) {
notify_redirect('/', 'warning', 'That upload is larger than the current ' . effective_upload_limit_mb() . ' MB limit. Please choose a smaller file.');
}
if ($errorCode !== UPLOAD_ERR_OK) {
notify_redirect('/', 'danger', 'Upload failed. Please try another file.');
}
$originalName = (string) ($file['name'] ?? 'upload.bin');
$safeOriginalName = preg_replace('/[^A-Za-z0-9._-]/', '-', $originalName) ?: 'upload.bin';
$extension = file_extension($safeOriginalName);
if (!in_array($extension, $tool['input_extensions'], true)) {
notify_redirect('/', 'warning', 'That file type is not supported for ' . $tool['label'] . '.');
}
$size = (int) ($file['size'] ?? 0);
if ($size < 1) {
notify_redirect('/', 'warning', 'The selected file looks empty. Please upload a valid file.');
}
if ($size > effective_upload_limit_bytes()) {
notify_redirect('/', 'warning', 'That upload is larger than the current ' . effective_upload_limit_mb() . ' MB limit. Please choose a smaller file.');
}
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = strtolower((string) $finfo->file((string) $file['tmp_name']));
$allowedMimes = match ($toolKey) {
'webm_mp4' => ['video/webm', 'application/octet-stream'],
'social_mp4' => ['video/webm', 'video/mp4', 'application/mp4', 'video/quicktime', 'application/octet-stream'],
'subtitle_convert' => ['text/plain', 'text/vtt', 'application/octet-stream', 'application/x-subrip'],
default => ['application/octet-stream'],
};
if (!in_array($mime, $allowedMimes, true)) {
notify_redirect('/', 'warning', 'The uploaded file does not match the expected file type for this converter.');
}
$targetFormat = 'mp4';
$presetKey = null;
$outputMime = $tool['output_mime'] !== '' ? $tool['output_mime'] : null;
if ($toolKey === 'social_mp4') {
$presetKey = trim((string)($_POST['preset_key'] ?? ''));
if ($presetKey === '' || preset_option($toolKey, $presetKey) === null) {
notify_redirect('/', 'warning', 'Please choose a social export preset.');
}
}
if ($toolKey === 'subtitle_convert') {
$requestedTarget = strtolower(trim((string)($_POST['subtitle_target'] ?? '')));
$allowedTargets = array_keys(subtitle_target_options());
if (!in_array($requestedTarget, $allowedTargets, true)) {
notify_redirect('/', 'warning', 'Please choose whether to export to SRT or VTT.');
}
if ($requestedTarget === $extension) {
notify_redirect('/', 'warning', 'Please choose the opposite subtitle format so the file is actually converted.');
}
$targetFormat = $requestedTarget;
$outputMime = $targetFormat === 'vtt' ? 'text/vtt' : 'application/x-subrip';
}
$publicId = bin2hex(random_bytes(16));
$inputPath = APP_UPLOAD_DIR . '/' . $publicId . '.' . $extension;
$outputPath = APP_OUTPUT_DIR . '/' . $publicId . '.' . $targetFormat;
if (!move_uploaded_file((string) $file['tmp_name'], $inputPath)) {
notify_redirect('/', 'danger', 'We could not save the uploaded file. Please try again.');
}
$downloadName = build_download_name($originalName, $toolKey, $targetFormat, $presetKey);
$jobId = create_job_record($publicId, $originalName, $inputPath, $size, $toolKey, $extension, $targetFormat, $presetKey, $outputMime, $downloadName);
$result = match ($toolKey) {
'webm_mp4' => convert_media_to_mp4($inputPath, $outputPath),
'social_mp4' => convert_media_to_mp4($inputPath, $outputPath, (string) preset_option($toolKey, $presetKey)['filter']),
'subtitle_convert' => convert_subtitle_file($inputPath, $outputPath, $extension, $targetFormat),
default => ['success' => false, 'message' => 'Unsupported conversion request.'],
};
if (!empty($result['success']) && is_file($outputPath)) {
mark_job_completed($jobId, $outputPath, (int) filesize($outputPath));
notify_redirect('/job.php?id=' . urlencode($publicId), 'success', $tool['label'] . ' completed. Your download is ready.');
}
mark_job_failed($jobId, (string) ($result['message'] ?? 'Conversion failed.'));
notify_redirect('/job.php?id=' . urlencode($publicId), 'danger', $tool['label'] . ' failed. Check the job details for more information.');