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:
Сделайте переустановку 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
или просто погуглите это.Попробуйте сделать то же самое, что и вы, но используя только командную строку ffmpeg. Это позволит лучше понять и улучшить отчетность об ошибках. Например, для concat:
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4
Убедитесь, что 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');
Дважды проверьте каждый путь. А в случае concat убедитесь, что выходной файл еще не существует.
Это может быть проблема кодирования. Попробуйте другие типы файлов с другими кодеками, чтобы увидеть, действительно ли это проблема. В случае, если вы можете конвертировать заранее в правильный кодек.
Добавьте разрывы строк в исходном коде. В моем случае я получил общую ошибку:
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);
Наконец, вот список похожих проблем с PHP-FFMpeg, которые вы можете проверить, чтобы узнать, было ли уже предоставлено решение: https://github.com/pascalbaljetmedia/laravel-ffmpeg/wiki/FFmpeg-failed-to-execute-command
Если у вас есть другие предложения, не стесняйтесь комментировать или редактировать ответ.