Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Ffmpeg Tools Laravel Package

projektgopher/laravel-ffmpeg-tools

View on GitHub
Deep Wiki
Context7

Getting Started

projektgopher/laravel-ffmpeg-tools is a thin, opinionated wrapper around the FFmpeg binary: you describe the operation (thumbnail, transcode, HLS, probe) and it builds/executes the command for you, without hand-assembling flag strings.

  1. Install the package:

    composer require projektgopher/laravel-ffmpeg-tools
    
  2. Make sure a real ffmpeg (and ffprobe) binary is available on the machine that runs your queue workers, not just your laptop. Verify with ffmpeg -version. If you deploy in containers, install it in the image and pin the version.

  3. Publish the config (if the package ships one) and check the binary path / timeout settings:

    php artisan vendor:publish --tag=ffmpeg-tools-config
    
  4. Start with the smallest possible use case — generate a poster frame for an uploaded video — then graduate to transcoding. Read the README's examples first, then src/ for the fluent builder and any DTOs, since those define the actual method surface. Don't trust blog posts; the API here is young and has moved between 0.x releases.

  5. Confirm the Laravel 12 constraint in composer.json. v0.8.1 adds Laravel 12 support, so on a fresh Laravel 12 app this should be the minimum version you require (^0.8.1).

Implementation Patterns

Always run outside the request cycle. FFmpeg is slow and CPU-bound. Put every invocation behind a queued job:

final class GenerateThumbnail implements ShouldQueue
{
    use Queueable;

    public function __construct(public Video $video) {}

    public function handle(): void
    {
        $path = FFmpegTools::input(Storage::disk('local')->path($this->video->source_path))
            ->thumbnailAt('00:00:03')
            ->to(Storage::disk('local')->path("thumbs/{$this->video->id}.jpg"))
            ->run();
    }
}

Local disk in, cloud disk out. FFmpeg needs real filesystem paths and random access. Download from S3 to a tmp directory, operate, then Storage::disk('s3')->put(...), and clean up in a finally block. Don't hand FFmpeg an S3 URL and expect streaming to work reliably.

Chain the fluent builder and log the resolved command. Build the operation, dump ->command() (or the string equivalent) into your logs, then ->run(). When something fails, that line is what you paste into a shell to reproduce outside Laravel.

Model integration. Use an observer or a booted() hook to dispatch the job when a media record is created, and store status on the model (pending / processing / failed / ready) so your UI can poll. Avoid doing conversion work inside the observer itself.

Concurrency control. Add WithoutOverlapping to transcoding jobs and consider a dedicated queue (->onQueue('media')) so a 10-minute encode doesn't starve your mail queue. A small RateLimited middleware keyed by user ID prevents a bulk upload from saturating the box.

Testing. In feature tests, either bind a fake implementation of the underlying executor in the container, or point the config at a stub binary. Assert on the command that would have been built rather than on real output; then keep one or two slow integration tests with a tiny fixture (a 1-second clip committed to tests/fixtures) that actually exercise the binary in CI.

Progress reporting. If you need a percentage, tail FFmpeg's stderr in the command's callback and write to cache; broadcasting per-percent from a queue worker gets noisy fast.

Gotchas and Tips

  • Version drift. FFmpeg flags are not stable across versions. Pin the binary version in your Docker image and in CI; a build that works locally on FFmpeg 7.x can fail in production on 4.x. Assert ffmpeg -version in a health check.
  • Worker timeouts. queue.worker --timeout and retry_after must both exceed your worst-case encode. If retry_after < runtime you'll get duplicate jobs running concurrently on the same file — a classic source of corrupted output.
  • Path escaping. Filenames with spaces, quotes, or unicode are the number one cause of "it worked in staging" bugs. Normalize uploads to a sanitized slug/hash before handing them to FFmpeg.
  • Temp file leaks. Failed encodes leave partial files behind. Wrap in try/finally and unlink() the input and output on failure; monitor disk usage on your workers.
  • OOM kills. FFmpeg dies silently (exit 137) under a container memory limit. Cap threads (-threads) and consider lowering resolution in a first pass for large inputs.
  • Zero-byte success. A successful exit code doesn't guarantee a valid file. Probe the output duration/size before marking a record ready.
  • Upgrading from 0.8.0. v0.8.1 is an additive compatibility release — the only change is Laravel 12 support. Bump the constraint, run your test suite, and you're done. There are no deprecations or breaking changes here.
  • Pre-1.0 API churn. The package is still 0.x, so treat the fluent method names as unstable across minor versions. Pin with ^0.8.1 (not *) and read the changelog on every bump; the API surface can change without a major version signal.
  • Debugging checklist. 1) Does the command work when pasted into a shell as the same OS user? 2) Is the path absolute? 3) Is the binary on the PATH of the worker process (php-fpm/supervisor often has a different PATH than your shell)? 4) Is it a permission problem on the output directory?
  • Extension point. If you need something the builder doesn't expose, most wrappers of this shape let you append raw arguments or swap the executor in the container. Bind a custom implementation in a service provider rather than forking the package.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect