Implement video auto resizing and reencoding

This commit is contained in:
Kijin Sung 2023-05-24 13:16:11 +09:00
parent 4fc308afad
commit a14cf85763
3 changed files with 111 additions and 6 deletions

View file

@ -838,7 +838,7 @@ class FileController extends File
}
// video
if(in_array($file_info['extension'], ['mp4', 'webm', 'ogv']))
if(in_array($file_info['extension'], ['mp4', 'webm', 'ogv', 'avi', 'mkv', 'mov', 'mpg', 'mpe', 'mpeg', 'wmv', 'm4v', 'flv']))
{
$file_info = $this->adjustUploadedVideo($file_info, $config);
}
@ -1221,16 +1221,115 @@ class FileController extends File
return $file_info;
}
// Set video size
// Get video size and duration
$file_info['width'] = (int)$stream_info['video']['width'];
$file_info['height'] = (int)$stream_info['video']['height'];
$file_info['duration'] = (int)$stream_info['video']['duration'];
$adjusted = [
'width' => $file_info['width'],
'height' => $file_info['height'],
'type' => $file_info['extension'],
'force' => false,
];
// MP4
if ($file_info['extension'] === 'mp4')
// Check video size
if (!empty($config->max_video_size_action) && ($config->max_video_width || $config->max_video_height) && (!$this->user->isAdmin() || $config->max_video_size_admin === 'Y'))
{
// Treat as GIF
if ($config->video_mp4_gif_time && $file_info['duration'] <= $config->video_mp4_gif_time && empty($stream_info['audio']))
$exceeded = 0;
$resize_width = $adjusted['width'];
$resize_height = $adjusted['height'];
if ($config->max_video_width > 0 && $adjusted['width'] > $config->max_video_width)
{
$resize_width = $config->max_video_width;
$resize_height = $adjusted['height'] * ($config->max_video_width / $adjusted['width']);
$exceeded++;
}
if ($config->max_video_height > 0 && $resize_height > $config->max_video_height)
{
$resize_width = $resize_width * ($config->max_video_height / $resize_height);
$resize_height = $config->max_video_height;
$exceeded++;
}
if ($exceeded)
{
// Block upload
if ($config->max_video_size_action === 'block')
{
if ($config->max_video_width && $config->max_video_height)
{
$message = sprintf(lang('msg_exceeds_max_video_size'), $config->max_video_width, $config->max_video_height);
}
elseif ($config->max_video_width)
{
$message = sprintf(lang('msg_exceeds_max_video_width'), $config->max_video_width);
}
else
{
$message = sprintf(lang('msg_exceeds_max_video_height'), $config->max_video_height);
}
throw new Rhymix\Framework\Exception($message);
}
$adjusted['width'] = (int)$resize_width;
$adjusted['height'] = (int)$resize_height;
$adjusted['type'] = 'mp4';
}
}
// Check if this video should be force-converted to MP4
if (isset($config->video_autoconv['any2mp4']) && $config->video_autoconv['any2mp4'] && $file_info['extension'] !== 'mp4')
{
$adjusted['type'] = 'mp4';
}
// Check if this video should be reencoded anyway
if (isset($config->video_always_reencode) && $config->video_always_reencode)
{
$adjusted['force'] = true;
$adjusted['type'] = 'mp4';
}
// Convert
if ($adjusted['width'] !== $file_info['width'] ||
$adjusted['height'] !== $file_info['height'] ||
$adjusted['type'] !== $file_info['extension'] ||
$adjusted['force']
)
{
$output_name = $file_info['tmp_name'] . '.converted.mp4';
// Width and height of video must be even
$adjusted['width'] -= $adjusted['width'] % 2;
$adjusted['height'] -= $adjusted['height'] % 2;
// Convert using ffmpeg
$command = \RX_WINDOWS ? escapeshellarg($config->ffmpeg_command) : $config->ffmpeg_command;
$command .= ' -nostdin -i ' . escapeshellarg($file_info['tmp_name']);
$command .= ' -movflags +faststart -pix_fmt yuv420p -c:v libx264 -crf 23';
$command .= empty($stream_info['audio']) ? ' -an' : ' -acodec aac';
$command .= sprintf(' -vf "scale=%d:%d"', $adjusted['width'], $adjusted['height']);
$command .= ' ' . escapeshellarg($output_name);
@exec($command, $output, $return_var);
$result = $return_var === 0 ? true : false;
// Update file info
if ($result)
{
$file_info['tmp_name'] = $output_name;
$file_info['size'] = filesize($output_name);
$file_info['type'] = Rhymix\Framework\MIME::getContentType($output_name);
$file_info['extension'] = $adjusted['type'];
$file_info['width'] = $adjusted['width'];
$file_info['height'] = $adjusted['height'];
$file_info['converted'] = true;
}
}
// Set original type to GIF if this video is short and has no audio stream.
if (isset($config->video_mp4_gif_time) && $config->video_mp4_gif_time)
{
if ($file_info['extension'] === 'mp4' && $file_info['duration'] <= $config->video_mp4_gif_time && empty($stream_info['audio']))
{
$file_info['original_type'] = 'image/gif';
}

View file

@ -54,6 +54,9 @@ $lang->msg_exceeds_limit_size = 'This file exceeds the attachment limit.';
$lang->msg_exceeds_max_image_size = 'This image is too large. Images must be no larger than %dx%dpx.';
$lang->msg_exceeds_max_image_width = 'This image is too large. The maximum permitted width is %dpx.';
$lang->msg_exceeds_max_image_height = 'This image is too large. The maximum permitted height is %dpx.';
$lang->msg_exceeds_max_video_size = 'This video is too large. Videos must be no larger than %dx%dpx.';
$lang->msg_exceeds_max_video_width = 'This video is too large. The maximum permitted width is %dpx.';
$lang->msg_exceeds_max_video_height = 'This video is too large. The maximum permitted height is %dpx.';
$lang->msg_file_not_found = 'Could not find requested file.';
$lang->msg_file_key_expired = 'This download link is expired. Please initiate the download again.';
$lang->file_search_target_list['filename'] = 'File Name';

View file

@ -55,6 +55,9 @@ $lang->msg_not_allowed_filetype = '업로드할 수 없는 파일 형식입니
$lang->msg_exceeds_max_image_size = '이미지가 너무 큽니다. %dx%dpx 이하의 이미지만 허용됩니다.';
$lang->msg_exceeds_max_image_width = '이미지가 너무 큽니다. 폭 %dpx 이하의 이미지만 허용됩니다.';
$lang->msg_exceeds_max_image_height = '이미지가 너무 큽니다. 높이 %dpx 이하의 이미지만 허용됩니다.';
$lang->msg_exceeds_max_video_size = '동영상이 너무 큽니다. %dx%dpx 이하의 동영상만 허용됩니다.';
$lang->msg_exceeds_max_video_width = '동영상이 너무 큽니다. 폭 %dpx 이하의 동영상만 허용됩니다.';
$lang->msg_exceeds_max_video_height = '동영상이 너무 큽니다. 높이 %dpx 이하의 동영상만 허용됩니다.';
$lang->msg_file_not_found = '요청한 파일을 찾을 수 없습니다.';
$lang->msg_file_key_expired = '다운로드 링크의 유효기간이 지났습니다. 다시 다운로드하여 주시기 바랍니다.';
$lang->file_search_target_list['filename'] = '파일 이름';