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

Filament Video Engine Laravel Package

martin6363/filament-video-engine

Filament Video Engine adds video handling to your Filament admin panels, letting you upload, preview, and manage video files directly from forms and tables. Integrate playback and media fields into your resources with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

This is the first tagged release (v1.0.0), so there is no migration path to worry about yet — you are adopting a package at its initial API surface. Treat the public API as unstable until a 1.x patch history exists.

Install and register

composer require martin6363/filament-video-engine
php artisan vendor:publish --tag="filament-video-engine-config"   # if offered
php artisan vendor:publish --tag="filament-video-engine-migrations" # if offered
php artisan migrate

Register the plugin on the panel you actually want it on, not globally:

use Martin6363\FilamentVideoEngine\FilamentVideoEnginePlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(FilamentVideoEnginePlugin::make());
}

Where to look first

  1. README.md — the only reliable description of the field/column API at this version. Read it end-to-end before writing code, since there is no prior art or Stack Overflow coverage.
  2. config/filament-video-engine.php (after publishing) — disk, path prefix, accepted MIME types, player options. This is where 80% of "why doesn't my video show up" issues are resolved.
  3. src/ — check whether the package ships a Fields/ or Components/ namespace; that tells you whether it is a form-field package or a full page/widget package.
  4. The GitHub commit history for v1.0.0 — the changelog link is empty of detail, so the commits are your only changelog.

First use case

Attach a video to an existing Eloquent model and expose it in a Filament resource form. Start with the simplest possible shape — a single video per record — and confirm upload → storage → playback works before adding multiple videos, transcoding, or thumbnails.

VideoField::make('video')
    ->disk('public')
    ->directory('videos');

Run php artisan storage:link before your first upload attempt.

Implementation Patterns

Model + cast alignment

Whatever column the field writes to, make sure the model treats it consistently. If the package stores a path string, a plain string column is fine. If it stores a JSON payload (path, mime, duration, thumbnail), cast it:

protected function casts(): array
{
    return ['video' => 'array'];
}

Verify which one it is by inspecting the generated migration or the field's saveUploadedFileUsing/dehydrateStateUsing logic — do not assume.

Separate disks for ingest and delivery

Use a private/temp disk for uploads and a public (or CDN-backed) disk for playback. Keep these distinct in config so you can move to S3 + CloudFront later without touching resource classes.

Table columns and infolists

Pair the form field with the package's column/entry counterpart so the resource list shows a thumbnail and the view page shows a player. If the package only ships a form field, render playback yourself with a Blade view or Filament\Infolists\Components\ViewEntry, pointing at the stored URL:

ViewEntry::make('video')->view('filament.infolists.video-player')

Wrap writes in a transaction with the parent record

Video uploads are slow; a failed save leaves an orphaned file on disk. Either write the file first and attach in a DB::transaction(), or add a scheduled model:prune for orphans. This matters more than usual because re-uploading a large file is expensive for the user.

Authorization

The field inherits the resource policy, but storage authorization is separate. If you use a private disk, playback needs a signed temporary URL — check whether the package exposes a ->temporaryUrl() / ->visibility('private') style toggle before you build your own route.

Multi-tenancy / panel scoping

If you use Filament tenancy, confirm the directory the package writes to is tenant-scoped. A global videos/ prefix means tenant A's files sit next to tenant B's; that is fine for paths but not for private-disk access. Pass tenant ID into the directory explicitly:

->directory(fn () => 'videos/' . filament()->getTenant()?->getKey())

Gotchas and Tips

v1.0.0 means zero backwards-compatibility guarantees. Pin the exact version ("martin6363/filament-video-engine": "1.0.0") in composer.json rather than a caret constraint. The empty changelog gives you no signal about how the maintainer intends to version; assume minor bumps may break.

Filament major version compatibility is unstated. Verify whether the plugin targets Filament v3 or v4 before installing — the plugin registration, field base classes, and asset registration differ. A mismatch usually surfaces as a Class not found or a blank field rather than a clear error. Check composer.json of the package for its filament/filament constraint.

Upload limits are the most likely first bug. Livewire's temporary upload limit, PHP's upload_max_filesize / post_max_size, and any web server body limit all apply before the package sees the file. A 200 MB video will silently fail at any of these layers. Set all three, and prefer chunked uploads if the package supports them.

Do not do video processing inline. If the package offers thumbnails or transcoding, ensure it dispatches a job. Synchronous FFmpeg calls inside a Livewire request will hit max_execution_time and take the panel down for that user. Queue it, and make the player degrade gracefully when the poster/thumbnail is not ready yet.

Publishing tags are guesses until confirmed. vendor:publish tags differ per package. Run php artisan vendor:publish with no arguments and read the list — it is faster than guessing tag names.

Debugging checklist, in order:

  1. Is the file on disk? storage/app/public/videos/...
  2. Is the symlink present? public/storage
  3. Does the config disk match the disk the file landed on?
  4. Is the URL being generated with the right APP_URL? A mismatch here produces a broken player with no error.
  5. Is the field actually dehydrated? ->dehydrated() / ->dehydrateStateUsing() overrides from another developer on the resource are a common cause of "upload works, nothing saves."

Extension points to probe early. Look for published Blade views and whether the field exposes ->view() / ->playerAttributes(). If neither exists, wrapping the field is unpleasant — a custom field that composes the package's field is the safer route than subclassing it, since subclass internals can change in 1.1.0 without notice.

Contribution risk. A single-tag package with a one-line changelog and no prior assessment history is a dependency you should be prepared to fork. Keep your integration thin — one custom field class or one Blade partial that calls into the package — so replacing it later is a localized change rather than a resource-wide rewrite.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin