Интеграция мультимедиа: обработка видеоконтента средствами PHP
Основные подходы к работе с видео в PHP
Наиболее эффективное решение: использование FFmpeg через обёртку PHP-FFmpeg
Данный подход позволяет выполнять практически все операции с видео: конвертацию, извлечение кадров, получение метаданных, наложение водяных знаков и многое другое. Библиотека PHP-FFmpeg (устанавливается через Composer) предоставляет объектно-ориентированный интерфейс к утилитам FFmpeg и FFprobe, что упрощает интеграцию и снижает количество ошибок.
Цель: автоматизировать обработку видео в проектах любой сложности – от создания превью до пакетной конвертации.
Как конвертировать видео из одного формата в другой с сохранением качества?
require 'vendor/autoload.php';
$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open('input.mp4');
$video->save(new FFMpeg\Format\Video\X264(), 'output.avi');
Video php content (работа с видео в php)
Типичные ошибки:
- Библиотека не находит FFmpeg – необходимо указать путь к бинарнику в конфигурации.
- Нехватка оперативной памяти при больших видео – увеличить лимит в php.ini (memory_limit).
- Ошибки формата – некоторые кодеки не поддерживаются стандартной сборкой FFmpeg.
Как загрузить видео на сервер и проверить его корректность?
Для простой загрузки достаточно стандартных средств PHP. Проверка MIME-типа и размера обязательна для безопасности.
if ($_FILES['video']['error'] === UPLOAD_ERR_OK) {
$allowed = ['video/mp4', 'video/webm', 'video/ogg'];
if (in_array($_FILES['video']['type'], $allowed)) {
move_uploaded_file($_FILES['video']['tmp_name'], 'uploads/' . $_FILES['video']['name']);
} else {
echo 'Недопустимый тип файла';
}
}
Возможные проблемы:
- Размер файла превышает лимиты PHP – настроить upload_max_filesize и post_max_size.
- Время выполнения скрипта истекает – увеличить max_execution_time или использовать чанки.
- MIME-тип легко подделывается – дополнительно проверять сигнатуру через finfo.
Как извлечь метаданные видео (длительность, кодек, разрешение) без использования внешних утилит?
Библиотека getID3 позволяет анализировать бинарную структуру файла. Подходит для случаев, когда FFmpeg недоступен.
require_once 'getid3/getid3.php';
$getID3 = new getID3;
$fileInfo = $getID3->analyze('video.mp4');
echo 'Длительность: ' . $fileInfo['playtime_string'];
echo 'Битрейт: ' . $fileInfo['bitrate'];
Ограничения и ошибки:
- getID3 не конвертирует видео – только анализ.
- Некоторые современные форматы могут не распознаваться.
- Большие файлы обрабатываются медленно.
Как организовать потоковое воспроизведение видео с защитой от прямого скачивания?
Скрипт-посредник (например, stream.php) считывает файл и передаёт его в буфер, проверяя права доступа. Дополнительно используется .htaccess для блокировки прямого доступа к папке с видео.
$file = 'protected/' . $_GET['file'];
if (!file_exists($file) || !check_access()) {
http_response_code(403);
exit;
}
header('Content-Type: video/mp4');
header('Content-Length: ' . filesize($file));
readfile($file);
Проблемы:
- Большие файлы могут вызвать переполнение памяти – использовать fread с chunks.
- Не поддерживается частичная загрузка (Range headers) – реализовать HTTP_RANGE для докачки.
- Скорость отдачи ниже, чем при прямой ссылке.
Как создать миниатюру (thumbnail) из видео используя только PHP?
С помощью FFmpeg через exec. В Windows убедиться, что FFmpeg добавлен в PATH.
$videoPath = 'video.mp4';
$thumbnailPath = 'thumb.jpg';
$timestamp = '00:00:05';
exec("ffmpeg -i $videoPath -ss $timestamp -vframes 1 $thumbnailPath 2>&1", $output, $return);
if ($return !== 0) {
echo 'Ошибка создания превью';
}
Типичные ошибки:
- Команда не выполняется из-за отключённых функций exec/shell_exec.
- FFmpeg не установлен или не в PATH.
- Права на запись в целевую папку отсутствуют.
Расширенные примеры работы с видео в PHP
Код возвращает длительность, битрейт, разрешение и список кодеков в формате JSON.
$videoFile = 'sample.mp4';
$json = shell_exec("ffprobe -v error -show_entries format=duration,bit_rate -show_entries stream=codec_type:stream=width,height,codec_name -of json $videoFile");
$data = json_decode($json, true);
echo 'Длительность: ' . $data['format']['duration'] . ' сек';
echo 'Размер: ' . $data['streams'][1]['width'] . 'x' . $data['streams'][1]['height'];
Длительность: 120.5 сек Размер: 1920x1080
Используем FFmpeg с параметрами. Результат – уменьшенная копия.
$input = 'big.mp4';
$output = 'small.mp4';
exec("ffmpeg -i $input -vf scale=640:480 -c:v libx264 -b:v 800k -c:a aac -b:a 128k $output 2>&1");
(вывод отсутствует при успешном выполнении; файл small.mp4 появляется в папке)
Создание 5 скриншотов через каждые 10 секунд.
$input = 'movie.mp4';
$outputPattern = 'capture_%02d.jpg';
exec("ffmpeg -i $input -vf \"fps=1/10\" -frames:v 5 $outputPattern 2>&1");
capture_01.jpg capture_02.jpg ...
Скрипт обрабатывает частичные запросы, позволяя перематывать видео.
$file = 'movies/secret.mp4';
$fp = @fopen($file, 'rb');
$size = filesize($file);
$length = $size;
$start = 0;
$end = $size - 1;
header('Accept-Ranges: bytes');
if (isset($_SERVER['HTTP_RANGE'])) {
preg_match('/bytes=(\d+)-(\d*)/', $_SERVER['HTTP_RANGE'], $matches);
$start = intval($matches[1]);
$end = ($matches[2] === '') ? $size - 1 : intval($matches[2]);
$length = $end - $start + 1;
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes $start-$end/$size");
}
header('Content-Length: ' . $length);
header('Content-Type: video/mp4');
fseek($fp, $start);
echo fread($fp, $length);
fclose($fp);
(вывод бинарных данных видео, клиент может перематывать)
Наложение PNG-изображения в правый нижний угол.
$input = 'video.mp4';
$logo = 'logo.png';
$output = 'watermarked_video.mp4';
exec("ffmpeg -i $input -i $logo -filter_complex \"overlay=W-w-10:H-h-10\" -codec:a copy $output 2>&1");
(файл watermarked_video.mp4 с логотипом)