首页 > 解决方案 > 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/folders/dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX ''-c''复制''/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4'

使用 FFMPEG 命令行连接:

根据@RolandStarke 和@LordNeckbeard 的建议,我尝试使用ffmpeg 命令行来更好地了解正在发生的事情。

如果我使用以下命令行:

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

我收到以下错误,与音频作品编解码器有关。

在此处输入图像描述

如果我使用以下命令行,将音频编码转换为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(但使用不同的视频):

如果问题仅与编解码器有关,那么将两个不同的视频与
video codec:h264和 audio codec一起使用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

使用 shell_exec 连接:

我曾尝试使用 shell_exec,前两个视频(作品编解码器):

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 是否实际工作,我通过对视频进行基本调整大小来测试它,它工作正常。

恢复:

问题:

如何使用 php-ffmpeg 连接视频?

问题是由错误的编码引起的吗?

谢谢!

标签: phplaravellaravel-5ffmpegffmpeg-php

解决方案


当遇到 php-ffmpeg 的问题时,最好的方法是从错误消息中复制命令并将其粘贴到终端中。这将为您提供更好的错误消息。

在你的情况下,错误是

ffmpeg 无法执行命令 '/usr/local/bin/ffmpeg' '-f' 'concat' '-safe' '0' '-i' '/private/var/folders/dw/919v2nds7s78pz_qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX ''-c''复制''/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera-laravel/storage/app/public/videos/output.mp4

当您尝试在终端中执行 ffmpeg 命令时,临时文件/private/var/[...]/ffmpeg-concath1kHiX会被删除,因此调试起来有点困难。要对其进行测试,您可以自己创建临时文件,例如:

$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);

推荐阅读