PHPackages                             zupolgec/laravel-ffmpeg-api - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. zupolgec/laravel-ffmpeg-api

ActiveLibrary[Image &amp; Media](/categories/media)

zupolgec/laravel-ffmpeg-api
===========================

Run pbmedia/laravel-ffmpeg jobs on a remote ffmpeg-api endpoint (verygoodffmpeg.com or a self-hosted instance) instead of the local ffmpeg binary, with automatic local fallback.

v0.2.0(1mo ago)085MITPHPPHP ^8.2CI passing

Since Jul 11Pushed 1mo agoCompare

[ Source](https://github.com/zupolgec/laravel-ffmpeg-api)[ Packagist](https://packagist.org/packages/zupolgec/laravel-ffmpeg-api)[ Docs](https://github.com/zupolgec/laravel-ffmpeg-api)[ RSS](/packages/zupolgec-laravel-ffmpeg-api/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (12)Versions (5)Used By (0)

laravel-ffmpeg-api
==================

[](#laravel-ffmpeg-api)

[![tests](https://github.com/zupolgec/laravel-ffmpeg-api/actions/workflows/tests.yml/badge.svg)](https://github.com/zupolgec/laravel-ffmpeg-api/actions/workflows/tests.yml)[![Packagist](https://camo.githubusercontent.com/51bb4bee8ef1ab74a9e884153146be54edde9899fcc7b32d356adb9f8dd6bc5c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a75706f6c6765632f6c61726176656c2d66666d7065672d6170692e737667)](https://packagist.org/packages/zupolgec/laravel-ffmpeg-api)[![License](https://camo.githubusercontent.com/f14891ad585233001e2a80af27881c12d1aed3e7c77ece7df01d4c7b42a43ed7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7a75706f6c6765632f6c61726176656c2d66666d7065672d6170692e737667)](LICENSE)

Run [`pbmedia/laravel-ffmpeg`](https://github.com/protonemedia/laravel-ffmpeg)jobs on a remote **ffmpeg-api** endpoint instead of the local `ffmpeg` binary — with automatic fallback to local. Your application code doesn't change: you keep using the `FFMpeg` facade.

Works with any [ffmpeg-api](https://verygoodffmpeg.com) compatible endpoint (the hosted `verygoodffmpeg.com` or your own self-hosted instance) — the endpoint URL is the only thing that changes.

- **Transparent** — subclasses php-ffmpeg's driver; no changes to your exports.
- **Broad coverage** — single &amp; multiple outputs, HLS (incl. AES-encrypted), and 2-pass, all handled automatically.
- **GPU-aware** — commands using NVIDIA encoders/filters route to a GPU worker.
- **Live progress** — `->onProgress()` keeps working over the remote job.
- **Safe** — anything it can't model exactly runs on the local binary instead.

How it works
------------

[](#how-it-works)

`laravel-ffmpeg` builds ffmpeg commands and runs them through php-ffmpeg's `FFMpegDriver`. This package subclasses that driver and overrides the single `command()` choke point:

- **remotable** commands become an ffmpeg-api job — local inputs are uploaded (`POST /api/tmp-file`), http(s) inputs are passed straight through, the job is submitted and polled, and outputs are downloaded back to the exact temp paths `laravel-ffmpeg` expects, so the rest of your pipeline is untouched;
- **everything else** runs on the **local binary** via `parent::command()`.

Install
-------

[](#install)

```
composer require zupolgec/laravel-ffmpeg-api
php artisan vendor:publish --tag=ffmpeg-api-config
```

```
FFMPEG_API_ENDPOINT=https://verygoodffmpeg.com   # or your own https://ffmpeg.example.com
FFMPEG_API_KEY=sk_xxx
FFMPEG_API_DRIVER=auto                            # local | remote | auto
```

Leave `FFMPEG_API_ENDPOINT` unset and the package is inert — every command runs locally, exactly like plain `laravel-ffmpeg`.

Usage
-----

[](#usage)

Nothing changes. Use the facade as you always do:

```
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;

FFMpeg::openUrl('https://cdn.example.com/master.mp4')
    ->export()
    ->onProgress(fn ($percentage) => logger("transcoding: {$percentage}%"))
    ->inFormat(new \FFMpeg\Format\Video\X264)
    ->save('lowres.mp4');
```

### Per-call overrides

[](#per-call-overrides)

The config is the default, not a straitjacket: any setting can be overridden for the scope of a closure. Handy when only one recipe in your pipeline is worth offloading (a re-encode) while the rest is stream-copy that would only pay the upload twice.

```
use Zupolgec\FFMpegApi\FFMpegApi;

// This one recipe goes to the GPU pool, no matter the configured driver mode.
FFMpegApi::remote(fn () => FFMpeg::openUrl($master)
    ->export()
    ->inFormat($nvencFormat)
    ->save($lowres), machine: 'nvidia');

FFMpegApi::local(fn () => /* stream-copy, keep it on this machine */);
FFMpegApi::on('cpu', fn () => /* pin the pool, keep the driver mode */);
FFMpegApi::using(['wait_timeout' => 7200], fn () => /* a long one */);
```

`remote()` defaults to **no local fallback**: a remote-only recipe (an NVENC command on a machine with no NVIDIA GPU) should fail loudly rather than be replayed on a binary that cannot run it. Pass `fallbackToLocal: true` to opt in.

What runs remotely
------------------

[](#what-runs-remotely)

The translator classifies ffmpeg args by option arity, so it handles a broad set of commands and sends them to the API:

- **single-output** transcodes / muxes — remux, downscale, poster frames, audio;
- **multiple outputs** in one invocation (e.g. split streams);
- **HLS** (playlist + segment glob), including **AES-encrypted** HLS: the key is uploaded and the `-hls_key_info_file` keyinfo is rewritten to a workdir-relative key (the playlist `URI` line is kept verbatim);
- **multipass** (`-pass` / `-passlogfile`): php-ffmpeg emits each pass as a separate `command()` call, so the driver **buffers the analysis pass(es) and chains them with the final pass into one job** — they run sequentially in the same worker, sharing the pass log.

It **falls back to the local binary** for what it can't model exactly: probes (`-version`), commands with no capturable output, tokens containing both quote characters, or any leftover unmodeled local path. Fallback is always safe — it never ships a job it isn't sure about.

### GPU routing

[](#gpu-routing)

A command that uses NVIDIA encoders or filters (`h264_nvenc`, `scale_cuda`, …) is automatically submitted to the endpoint's `nvidia` worker pool; everything else runs on `cpu`. Force a pool with `FFMPEG_API_MACHINE=nvidia|cpu`.

### Progress

[](#progress)

`->onProgress()` works over the remote job. The driver submits non-blocking and polls `GET /api/jobs/{id}`, forwarding the endpoint's `progress` (0–100), `eta_seconds`, and `speed` into php-ffmpeg's progress listeners — so your `->onProgress($percentage, $remaining, $rate)` callback fires as usual, with a single 0→100 sweep across chained commands (2-pass, HLS).

Progress needs a discoverable duration: file inputs and any command with `-t`/`-to` report a live percentage; a pure generated source with no duration reports `null` until it finishes (then 100).

Config
------

[](#config)

keyenvdefaultmeaning`endpoint``FFMPEG_API_ENDPOINT`–base URL, no path (client appends `/api`)`key``FFMPEG_API_KEY`–bearer API key`driver``FFMPEG_API_DRIVER``auto``local` | `remote` | `auto``fallback_to_local``FFMPEG_API_FALLBACK_LOCAL``true`on remote failure, retry locally instead of throwing`machine``FFMPEG_API_MACHINE`–force `cpu`/`nvidia`; empty = auto-detect from the command`wait_timeout``FFMPEG_API_WAIT_TIMEOUT``1800`seconds for a job / upload / download`connect_timeout``FFMPEG_API_CONNECT_TIMEOUT``10`seconds`poll_interval_ms``FFMPEG_API_POLL_INTERVAL_MS``1000`job poll cadenceTesting
-------

[](#testing)

```
composer install
vendor/bin/pest --testsuite=Unit                 # pure, no endpoint needed
FFMPEG_API_ENDPOINT=… FFMPEG_API_KEY=… vendor/bin/pest --group=live
```

License
-------

[](#license)

MIT — see [LICENSE](LICENSE).

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance90

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity39

Early-stage or recently created project

 Bus Factor1

Top contributor holds 54.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

4

Last Release

45d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c4d043f6d69ebdba89936fb938bd273b7cbca8911f1952eb0cb5dd17d9ba8d0d?d=identicon)[zupolgec](/maintainers/zupolgec)

---

Top Contributors

[![16bit-dev](https://avatars.githubusercontent.com/u/47613210?v=4)](https://github.com/16bit-dev "16bit-dev (6 commits)")[![zupolgec](https://avatars.githubusercontent.com/u/161318?v=4)](https://github.com/zupolgec "zupolgec (5 commits)")

---

Tags

laravelvideoffmpeglaravel-ffmpegtranscodingffmpeg-apiverygoodffmpeg

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/zupolgec-laravel-ffmpeg-api/health.svg)

```
[![Health](https://phpackages.com/badges/zupolgec-laravel-ffmpeg-api/health.svg)](https://phpackages.com/packages/zupolgec-laravel-ffmpeg-api)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.4M354](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

80427.1M249](/packages/laravel-mcp)[intervention/image-laravel

Laravel Integration of Intervention Image

1599.8M228](/packages/intervention-image-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

818355.4k3](/packages/defstudio-telegraph)[api-platform/laravel

API Platform support for Laravel

58190.1k21](/packages/api-platform-laravel)[forjedio/inertia-table

Backend-driven dynamic tables for Laravel + Inertia.js

272.0k](/packages/forjedio-inertia-table)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
