代码之家  ›  专栏  ›  技术社区  ›  FrancescoMussi

PHP-FFMpeg:如何正确连接两个视频?

  •  1
  • FrancescoMussi  · 技术社区  · 6 年前

    情况:

    我需要它连接成一个单一的视频多个视频。
    我在用图书馆 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\u qhp7z9rcm0000gn/T/ffmpeg-concath1kHiX'-c''copy'/Users/francescomussi/Desktop/Apps/cameraProject/back-end/camera laravel/storage/app/public/videos/output.mp4'

    CONCAT使用FFMPEG命令行:

    关于@RolandStarke和@LordNeckbeard的建议,我尝试使用 ffmpeg command line

    如果使用以下命令行:

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

    我得到以下错误,与 音频opus编解码器 .

    enter image description here

    如果我使用以下命令行,将音频编码转换为 acc

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

    最终的视频是正确创建的,作为其他视频的串联。

    CONCAT使用PHP-FFMPEG:(使用savefromtocodecs)

    似乎问题只与编解码器有关。 所以我试着用 saveFromDifferentCodecs

    $format = new FFMpeg\Format\Video\X264('libfdk_aac', 'libx264');
    
    $result = $video1
        ->concat([$path1, $path2])
        ->saveFromDifferentCodecs($format, $output_path);
    

    但我还是犯了个错误:

    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

    我尝试过在前两个视频(opus编解码器)中使用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");
    

    而且工作很顺利。

    测试库:

    为了看看php-mpeg是否真的可以工作,我通过对视频进行基本的调整大小来测试它,它工作正常。

    简历:

    • 使用ffmpeg命令行一切正常
    • 使用php-ffmpeg我总是得到错误 ffmpeg failed to execute command

    问题:

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

    谢谢!

    2 回复  |  直到 6 年前
        1
  •  2
  •   Roland Starke    6 年前

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

    在你的情况下,错误是

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

    调试这个有点困难,因为temp文件 /专用/var/[…]/ffmpeg-concath1kHiX 尝试在终端中执行ffmpeg命令时删除。要测试它,您可以自己创建temp文件,如下所示:

    $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);
    
        2
  •  1
  •   FrancescoMussi    6 年前

    正确答案来自@RolandStarke。
    在这里,我只想列出一些建议,这些建议可能对调试处理ffmpeg时的其他类似问题有用:

    1. 重新安装ffmpeg。可能是缺少选项或缺少编解码器。以下是如何安装(mac),包括所有可能的选项(2018年9月)。我花了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 -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. 在源代码中添加换行符。在我的例子中,我得到了一般性错误: 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);

    6. https://github.com/pascalbaljetmedia/laravel-ffmpeg/wiki/FFmpeg-failed-to-execute-command

    如果您有其他建议,请随时评论或编辑答案。