Laravel-medialibrary: Call to undefined method FFMpeg\FFMpeg::getDuration()

Created on 29 Jan 2019  路  6Comments  路  Source: spatie/laravel-medialibrary

After setting up medialibrary for video thumbnailing I kept on getting the following exception in my conversion job.

Symfony\Component\Debug\Exception\FatalThrowableError: Call to undefined method FFMpeg\FFMpeg::getDuration() in /var/www/kiosk_manager/vendor/spatie/laravel-medialibrary/src/ImageGenerators/FileTypes/Video.php:23
Stack trace:
#0 /var/www/kiosk_manager/vendor/spatie/laravel-medialibrary/src/FileManipulator.php(94): Spatie\MediaLibrary\ImageGenerators\FileTypes\Video->convert('/var/www/kiosk_...', Object(Spatie\MediaLibrary\Conversion\Conversion))
#1 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Support/Collection.php(418): Spatie\MediaLibrary\FileManipulator->Spatie\MediaLibrary\{closure}(Object(Spatie\MediaLibrary\Conversion\Conversion), 0)
#2 /var/www/kiosk_manager/vendor/spatie/laravel-medialibrary/src/FileManipulator.php(117): Illuminate\Support\Collection->each(Object(Closure))
#3 /var/www/kiosk_manager/vendor/spatie/laravel-medialibrary/src/Jobs/PerformConversions.php(32): Spatie\MediaLibrary\FileManipulator->performConversions(Object(Spatie\MediaLibrary\Conversion\ConversionCollection), Object(Spatie\MediaLibrary\Models\Media))
#4 [internal function]: Spatie\MediaLibrary\Jobs\PerformConversions->handle()
#5 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(29): call_user_func_array(Array, Array)
#6 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#7 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#8 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/Container.php(572): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#9 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(94): Illuminate\Container\Container->call(Array)
#10 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(116): Illuminate\Bus\Dispatcher->Illuminate\Bus\{closure}(Object(Spatie\MediaLibrary\Jobs\PerformConversions))
#11 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Spatie\MediaLibrary\Jobs\PerformConversions))
#12 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Bus/Dispatcher.php(98): Illuminate\Pipeline\Pipeline->then(Object(Closure))
#13 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(49): Illuminate\Bus\Dispatcher->dispatchNow(Object(Spatie\MediaLibrary\Jobs\PerformConversions), false)
#14 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(83): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\RedisJob), Array)
#15 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(327): Illuminate\Queue\Jobs\Job->fire()
#16 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(277): Illuminate\Queue\Worker->process('redis', Object(Illuminate\Queue\Jobs\RedisJob), Object(Illuminate\Queue\WorkerOptions))
#17 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(118): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\RedisJob), 'redis', Object(Illuminate\Queue\WorkerOptions))
#18 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(102): Illuminate\Queue\Worker->daemon('redis', 'default', Object(Illuminate\Queue\WorkerOptions))
#19 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(86): Illuminate\Queue\Console\WorkCommand->runWorker('redis', 'default')
#20 /var/www/kiosk_manager/vendor/laravel/horizon/src/Console/WorkCommand.php(46): Illuminate\Queue\Console\WorkCommand->handle()
#21 [internal function]: Laravel\Horizon\Console\WorkCommand->handle()
#22 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(29): call_user_func_array(Array, Array)
#23 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}()
#24 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure))
#25 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Container/Container.php(572): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL)
#26 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Console/Command.php(183): Illuminate\Container\Container->call(Array)
#27 /var/www/kiosk_manager/vendor/symfony/console/Command/Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#28 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Console/Command.php(170): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle))
#29 /var/www/kiosk_manager/vendor/symfony/console/Application.php(893): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#30 /var/www/kiosk_manager/vendor/symfony/console/Application.php(262): Symfony\Component\Console\Application->doRunCommand(Object(Laravel\Horizon\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#31 /var/www/kiosk_manager/vendor/symfony/console/Application.php(145): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#32 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Console/Application.php(89): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#33 /var/www/kiosk_manager/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(122): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#34 /var/www/kiosk_manager/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#35 {main}

Digging a little deeper I found that the way to get the duration of a video clip in the php ffmpeg library has changed and there are two tests around this method ImageGenerators/FileTypes/Video.php:23 that currently are failing.

1) Spatie\MediaLibrary\Tests\Feature\Conversion\ConversionFileExtensionTest::it_always_defaults_to_jpg_when_the_original_file_is_not_an_image
Error: Call to undefined method FFMpeg\FFMpeg::getDuration()

/vagrant/src/ImageGenerators/FileTypes/Video.php:23
/vagrant/src/FileManipulator.php:94
/vagrant/vendor/laravel/framework/src/Illuminate/Support/Collection.php:418
/vagrant/src/FileManipulator.php:117
/vagrant/src/FileManipulator.php:43
/vagrant/src/Filesystem/Filesystem.php:32
/vagrant/src/FileAdder/FileAdder.php:307
/vagrant/src/FileAdder/FileAdder.php:298
/vagrant/src/FileAdder/FileAdder.php:248
/vagrant/tests/Feature/Conversion/ConversionFileExtensionTest.php:28

2) Spatie\MediaLibrary\Tests\Unit\ImageGenerators\VideoTest::it_can_convert_a_video
Error: Call to undefined method FFMpeg\FFMpeg::getDuration()

/vagrant/src/ImageGenerators/FileTypes/Video.php:23
/vagrant/tests/Unit/ImageGenerators/VideoTest.php:26

I'll submit a pr to fix this. No tests are needed as failing tests already exist for this method.

Most helpful comment

Thanks @acodeninja it's a nice solution, I will share mine as well:

  1. Create a new class extending the original one and apply the changes that @acodeninja already propose on his PR
<?php

namespace App\Media;

use FFMpeg\Coordinate\TimeCode;
use FFMpeg\FFMpeg;
use Spatie\MediaLibrary\Conversion\Conversion;
use Spatie\MediaLibrary\ImageGenerators\FileTypes\Video;

class CustomVideoGenerator extends Video
{
    public function convert(string $file, Conversion $conversion = null): string
    {
        $imageFile = pathinfo($file, PATHINFO_DIRNAME).'/'.pathinfo($file, PATHINFO_FILENAME).'.jpg';

        $ffmpeg = FFMpeg::create([
            'ffmpeg.binaries' => config('medialibrary.ffmpeg_path'),
            'ffprobe.binaries' => config('medialibrary.ffprobe_path'),
        ]);

        $video = $ffmpeg->open($file);
        $duration = $ffmpeg->getFFProbe()->format($file)->get('duration');

        $seconds = $conversion ? $conversion->getExtractVideoFrameAtSecond() : 0;
        $seconds = $duration < $seconds ? 0 : $seconds;

        $frame = $video->frame(TimeCode::fromSeconds($seconds));
        $frame->save($imageFile);

        return $imageFile;
    }
}
  1. Then you can update the configuration file of the medialibrary and set your new generator
...
/*
     * These generators will be used to create an image of media files.
     */
    'image_generators' => [
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Image::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Webp::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Pdf::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Svg::class,
        App\Media\CustomVideoGenerator::class
    ],
...

Enjoy! :+1:

All 6 comments

Please merge this PR ASAP!! The changes introduced in _7.5.5_ are breaking the conversions for videos. Kindly ask the collaborators to take action ASAP. I already checked the changes from the proposed PR and they fix the problems. Thanks @acodeninja

In our environment I've added the following step to our deployment script while I've been waiting for this to be merged:

sed -i -e "s/\$duration = \$ffmpeg->getDuration();/\$duration = \$ffmpeg->getFFProbe()->format(\$file)->get('duration');/" vendor/spatie/laravel-medialibrary/src/ImageGenerators/FileTypes/Video.php

Might help you and yours with your deployments in the meantime 馃憤

Thanks @acodeninja it's a nice solution, I will share mine as well:

  1. Create a new class extending the original one and apply the changes that @acodeninja already propose on his PR
<?php

namespace App\Media;

use FFMpeg\Coordinate\TimeCode;
use FFMpeg\FFMpeg;
use Spatie\MediaLibrary\Conversion\Conversion;
use Spatie\MediaLibrary\ImageGenerators\FileTypes\Video;

class CustomVideoGenerator extends Video
{
    public function convert(string $file, Conversion $conversion = null): string
    {
        $imageFile = pathinfo($file, PATHINFO_DIRNAME).'/'.pathinfo($file, PATHINFO_FILENAME).'.jpg';

        $ffmpeg = FFMpeg::create([
            'ffmpeg.binaries' => config('medialibrary.ffmpeg_path'),
            'ffprobe.binaries' => config('medialibrary.ffprobe_path'),
        ]);

        $video = $ffmpeg->open($file);
        $duration = $ffmpeg->getFFProbe()->format($file)->get('duration');

        $seconds = $conversion ? $conversion->getExtractVideoFrameAtSecond() : 0;
        $seconds = $duration < $seconds ? 0 : $seconds;

        $frame = $video->frame(TimeCode::fromSeconds($seconds));
        $frame->save($imageFile);

        return $imageFile;
    }
}
  1. Then you can update the configuration file of the medialibrary and set your new generator
...
/*
     * These generators will be used to create an image of media files.
     */
    'image_generators' => [
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Image::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Webp::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Pdf::class,
        Spatie\MediaLibrary\ImageGenerators\FileTypes\Svg::class,
        App\Media\CustomVideoGenerator::class
    ],
...

Enjoy! :+1:

this needs to get fixed... its already 3 month

The temp solution above worked for me... but yeah can we get the PR related to this issue merged? :O

Fixed in #1372 will release later today

Was this page helpful?
0 / 5 - 0 ratings

Related issues

intrepidws picture intrepidws  路  3Comments

amrnn90 picture amrnn90  路  3Comments

ideadx picture ideadx  路  4Comments

Krato picture Krato  路  4Comments

Nks picture Nks  路  3Comments