PHP-FFMpeg: Как правильно объединить два видео?

СИТУАЦИЯ:

Мне нужно, чтобы объединить несколько видео в одно видео.
Я использую библиотеку PHP-FFMpeg.
Но мне не удается заставить его работать.

ВИДЕО:

Видео - это записи, сделанные с помощью MediaRecorder Web API.
Формат видео: video/webm;codecs=h264Аудиоформат opus,

recorder = new MediaRecorder(this.stream, {
  mimeType: 'video/webm;codecs=h264'
})

CONCAT, ИСПОЛЬЗУЯ PHP-FFMPEG (используя saveFromSameCodecs):

Вот как я пытаюсь объединить их, используя saveFromSameCodecs:
(Я проверил пути и они верны)

$video = $ffmpeg->open( $path1 );
$video
    ->concat([$path1, $path2])
    ->saveFromSameCodecs($path_output, TRUE);

Но это не удалось со следующим сообщением об ошибке:

ffmpeg не удалось выполнить команду '/usr/local/bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folder /dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX' '-c' 'copy' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4'

КОНКАТ ИСПОЛЬЗОВАТЬ FFMPEG COMMAND LINE:

По предложению @RolandStarke и @LordNeckbeard я попытался использовать командную строку ffmpeg, чтобы лучше понять, что происходит.

Если я использую следующую командную строку:

ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

Я получаю следующую ошибку, связанную с аудио кодеком opus.

Если я использую следующую командную строку, преобразование аудио, закодированного в acc:

ffmpeg -f concat -safe 0 -i mylist.txt -c:v copy -c:a aac output.mp4

Финальное видео правильно создано, как объединение других видео.

CONCAT, ИСПОЛЬЗУЯ PHP-FFMPEG: (используя saveFromDifferentCodecs)

Кажется, проблема связана ТОЛЬКО с кодеком. Итак, я попытался с помощью saveFromDifferentCodecs:

$format = new FFMpeg\Format\Video\X264('libfdk_aac', 'libx264');

$result = $video1
    ->concat([$path1, $path2])
    ->saveFromDifferentCodecs($format, $output_path);

Но я все еще получаю ошибку:

ffmpeg не удалось выполнить команду '/ usr / local / bin / ffmpeg' '-i' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/test1.mp4 '' -i '' /Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/test2.mp4 '' -filter_complex '' [0: v: 0] [ 0: a: 0] [1: v: 0] [1: a: 0] concat = n = 2: v = 1: a = 1 [v] [a] '' -map '' [v] '' -map '' [a] '' -b: a '' 128k '' /Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4 '

CONCAT ИСПОЛЬЗУЯ PHPFFMPEG (но с разными видео):

Если проблема связана только с кодеком, то используйте два разных видео с
видео кодек: h264 и аудио кодек aac,
это должно работать, но это не так:

ffmpeg failed to execute command '/usr/local/bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folders/dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concatoJGhLt' '-c' 'copy' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4'

Но с помощью командной строки все работает гладко: ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

CONCAT USING shell_exec:

Я попытался с помощью shell_exec, с первых двух видео (кодек opus):

echo shell_exec("/usr/local/bin/ffmpeg -f concat -safe 0 -i /Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/mylist.txt -c:v copy -c:a aac /Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/output.mp4 2>&1");

И это работает плавно. Окончательный вывод создается с помощью аудиокодека acc.

ИСПЫТАНИЕ БИБЛИОТЕКИ:

Чтобы увидеть, работает ли php-mpeg на самом деле, я протестировал его, выполнив базовое изменение размера видео, и оно заработало правильно.

ПРОДОЛЖИТЬ:

  • С помощью командной строки ffmpeg все работает отлично
  • С помощью shell_exec все отлично работает
  • Используя php-ffmpeg я всегда получаю ошибку ffmpeg failed to execute command

ВОПРОС:

Как я могу объединить видео, используя php-ffmpeg?

Проблема вызвана неправильной кодировкой?

Спасибо!

2 ответа

Решение

При возникновении проблем с php-ffmpeg лучше всего скопировать команду из сообщения об ошибке и вставить ее в терминал. Это даст вам лучшее сообщение об ошибке.

В вашем случае ошибка

ffmpeg не удалось выполнить команду '/ usr / local / bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folder /dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX' '-c' 'copy' '/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4

Отладить это немного сложнее, так как временный файл /private/var/[...]/ffmpeg-concath1kHiX удаляется при попытке выполнить команду ffmpeg в терминале. Чтобы проверить это, вы можете создать временный файл, например:

$vidoes = [__DIR__ . '/small.mp4', __DIR__ . '/small.mp4'];

file_put_contents('videolist.txt', implode("\n", array_map(function ($path) {
    return 'file ' . addslashes($path);
}, $vidoes)));

Теперь вы можете запустить команду ffmpeg в терминале

ffmpeg -f concat -safe 0 -i videolist.txt -c copy /Users/[...]/videos/output.mp4
#[...]
#File '/Users/[...]/videos/output.mp4' already exists. Overwrite ? [y/N] 
#Not overwriting - exiting

Так что в вашем случае ошибка в том, что выходной файл уже существовал. Решение состоит в том, чтобы использовать другой несуществующий выходной файл или удалить его перед объединением ваших видео.

Вот пример того, как объединить файлы (small.mp4 взят из http://techslides.com/sample-webm-ogg-and-mp4-video-files-for-html5)

<?php

require 'vendor/autoload.php';

$ffmpeg = FFMpeg\FFMpeg::create();
$video = $ffmpeg->open(__DIR__ . '/small.mp4'); 
$video
    ->concat([__DIR__ . '/small.mp4', __DIR__ . '/small.mp4'])
    ->saveFromSameCodecs(__DIR__ . '/out-'.  time() . '.mp4', true);

Правильный ответ от @RolandStarke.
Здесь я просто хочу собрать список предложений, которые могут быть полезны для устранения других подобных проблем при работе с ffmpeg:

  1. Сделайте переустановку ffmpeg. Это может быть отсутствующий параметр или отсутствующий кодек. Вот как установить (для Mac), включая все возможные варианты (сентябрь 2018). Это заняло у меня 30 минут, так что будьте терпеливы.

    brew install ffmpeg --with-chromaprint --with-fdk-aac --with-fontconfig --with-freetype --with-frei0r --with-game-music-emu --with-libass --with-libbluray --with-libbs2b --with-libcaca --with-libgsm --with-libmodplug --with-librsvg --with-libsoxr --with-libssh --with-libvidstab --with-libvorbis --with-libvpx --with-opencore-amr --with-openh264 --with-openjpeg --with-openssl --with-opus --with-rtmpdump --with-rubberband --with-sdl2 --with-snappy --with-speex --with-srt --with-tesseract --with-theora --with-tools --with-two-lame --with-wavpack --with-webp --with-x265 --with-xz --with-zeromqlibzeromq --with-zimg

    Чтобы получить обновленный список опций, вы можете запустить: brew options ffmpeg или просто погуглите это.

  2. Попробуйте сделать то же самое, что и вы, но используя только командную строку ffmpeg. Это позволит лучше понять и улучшить отчетность об ошибках. Например, для concat:

    ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

  3. Убедитесь, что PHP-FFMpeg работает правильно. Конкат это немного более сложная операция. Вы можете попробовать более простой и посмотреть, работает ли он и правильно ли установлена ​​библиотека. Например, вы можете попробовать простое преобразование:

    FFMpeg::fromDisk('local') ->open('public/videos/test.mp4') ->export() ->toDisk('local') ->inFormat(new FFMpeg\Format\Video\X264('libmp3lame', 'libx264')) ->save('public/videos/converted_test.mp4');

  4. Дважды проверьте каждый путь. А в случае concat убедитесь, что выходной файл еще не существует.

  5. Это может быть проблема кодирования. Попробуйте другие типы файлов с другими кодеками, чтобы увидеть, действительно ли это проблема. В случае, если вы можете конвертировать заранее в правильный кодек.

  6. Добавьте разрывы строк в исходном коде. В моем случае я получил общую ошибку: Unable to save concatenated video, Вот исходный код:

    try { $this->driver->command($commands); } catch (ExecutionFailureException $e) { $this->cleanupTemporaryFile($outputPathfile); $this->cleanupTemporaryFile($sourcesFile); throw new RuntimeException('Unable to save concatenated video', $e->getCode(), $e); }

    Но если я сброслю выполнение, а затем умру, прямо перед этим блоком:

    dd($this->driver->command($commands));

    Это давало мне более подробное сообщение об ошибке.

    Вы также можете вывести массив команд: dd($commands);

  7. Наконец, вот список похожих проблем с PHP-FFMpeg, которые вы можете проверить, чтобы узнать, было ли уже предоставлено решение: https://github.com/pascalbaljetmedia/laravel-ffmpeg/wiki/FFmpeg-failed-to-execute-command

Если у вас есть другие предложения, не стесняйтесь комментировать или редактировать ответ.

Другие вопросы по тегам