Поворот видео в PHP по EXIF-данным
23 декабря 2013 FFMPEG 9793 просмотра
Видео, записанные с поворотом устройства часто так и отображаются при загрузке на сайт. Некоторые программы (или операционные системы) поворачивают их при проигрывании. Делают они это исходя из метаданных файла (например, в iPhone). Но в Windows видео будет проигрываться так, как оно записано. Поэтому при загрузке видео на ваш сайт нужно видео вручную перевернуть, чтобы гарантировать нужное положение на всех устройствах.

EXIF
Метаданные существуют в нескольких форматах. Самый распространенный - EXIF. Что хранится в этих метаданных? Информация о времени, геолокация, о камере и т.д. Мы не будет сейчас рассматривать всё это, нас интересует информация о ориентации.

Как получить эту информацию из скрипта? Я предлагаю инструмент Exiftool. Его необходимо установить на сервер, в документации можно посмотреть инструкции. Далее нам нужно вызвать эту программу из скрипта.
// Сохраняем EXIF как php массив в файл
$cmd = 'exiftool -php video.mp4 > exif.php';
exec($cmd);

$content  = file_get_contents('exif.php');
if ($content) {
    eval('$exif = ' . $content);
    if (isset($exif[0]['Rotation'])) {
       rotate('video.mp4', $exif[0]['Rotation']);
    }
}
Для работы с видео на сервер необходимо установить ffmpeg. Это очень мощный инструмент, умеющий многое, в том числе и повороты видео. Функция rotate будет поворачивать видео на угол из EXIF-данных. Важный момент: чтобы некоторые устройства повторно не учитывали Rotation, нам нужно сбросить этот параметр в метаданных. Начнем.
/**
 * @param string $file
 * @param int $deg
 */
function rotate($file, $deg)
{
    // Это список возможных углов и связанных с ними значений для параметра transpose
    $rotateDegrees = array(
        -90  => array(2),
        90   => array(1),
        180  => array(1, 1),
        -180 => array(2, 2)
    );

    if (array_key_exists($deg, $rotateDegrees)) {
        $values  = $rotateDegrees[$deg];
        $filters = array();
        foreach ($values as $val) {
            $filters[] = 'transpose=' . $val;
        }

        $cmd = 'ffmpeg -y -i ' . escapeshellarg($file) . ' -vf "' . implode(',', $filters) . '" -metadata:s:v:0 rotate=0 ' . escapeshellarg($file) . ' ';
        exec($cmdLine);
    }
}
Параметр transpose поворачивает видео, для 180 градусов нужно указать 2 таких параметра по 90 градусов. Мы используем значения 1 и 2, хотя в transpose можно передать еще 2 типа:

0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip

А метаданные сбрасываются атрибутом metadata. Теперь видео ваших пользователей будет всем хорошо видно.