foxws / laravel-av1
A Laravel package for ab-av1 video encoding with AV1
Fund package maintenance!
foxws
Installs: 325
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/foxws/laravel-av1
Requires
- php: ^8.2
- illuminate/contracts: ^11.0 || ^12.0
- illuminate/filesystem: ^11.0 || ^12.0
- illuminate/process: ^11.0 || ^12.0
- illuminate/support: ^11.0 || ^12.0
- psr/log: ^3.0
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.14
- nunomaduro/collision: ^8.8
- orchestra/testbench: ^9.0.0 || ^10.0.0
- pestphp/pest: ^4.0
- pestphp/pest-plugin-arch: ^4.0
- pestphp/pest-plugin-laravel: ^4.0
- phpstan/extension-installer: ^1.4
- phpstan/phpstan-deprecation-rules: ^2.0
- phpstan/phpstan-phpunit: ^2.0
- spatie/laravel-ray: ^1.35
README
A Laravel package for ab-av1, enabling you to encode videos to AV1 format with VMAF-targeted quality optimization.
use Foxws\AV1\Facades\AV1; // VMAF-targeted encoding $result = AV1::open('videos/input.mp4') ->abav1() // Use ab-av1 encoder ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->toDisk('s3') ->save('output.mp4');
Features
- ๐ฌ Fluent API - Laravel-style chainable methods
- ๐ Multiple Disks - Works with local, S3, and custom filesystems
- ๐ฏ VMAF-Targeted Encoding - Automatically finds optimal CRF for target quality
- ๐ Quality Metrics - Built-in VMAF & XPSNR scoring
- ๐ Multiple Encoders - Designed to support ab-av1, av1an, svt-av1, and more
- ๐งช Testable - Clean architecture with mockable components
- ๐ Type-Safe - Full PHP 8.4+ type declarations
Requirements
- PHP 8.3 or higher
- Laravel 11.x or higher
- ab-av1 binary installed on your system
Installation
Install the package via composer:
composer require foxws/laravel-av1
Publish the config file:
php artisan vendor:publish --tag="av1-config"
Installing ab-av1
Install ab-av1 using cargo:
cargo install ab-av1
Or download a prebuilt binary from the releases page.
Verify Installation
After installation, verify that ab-av1 is properly configured:
php artisan av1:verify
This will check:
- Binary exists and is executable
- Can retrieve version information
- Configuration is properly set up
- Temporary directory is accessible
Package Information
View package and binary information:
php artisan av1:info
Quick Start
Using ab-av1 Encoder
This package uses ab-av1 as its primary encoder. Select the encoder explicitly:
use Foxws\AV1\Facades\AV1; $result = AV1::open('input.mp4') ->abav1() // Use ab-av1 encoder ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->save('output.mp4');
Note: The package is designed to support multiple encoders (av1an, svt-av1, etc.) in future versions using the same fluent API pattern.
VMAF Encode
Automatically find the optimal CRF value to achieve a target VMAF quality score and encode the full video:
use Foxws\AV1\Facades\AV1; $result = AV1::open('input.mp4') ->abav1() // Use ab-av1 encoder ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->save('output.mp4');
CRF Search
Search for the optimal CRF value without encoding the full video:
$result = AV1::open('input.mp4') ->abav1() ->crfSearch() ->preset('6') ->minVmaf(95) ->export() ->save(); // The output will contain the recommended CRF value echo $result->getOutput();
Sample Encode
Encode a sample of the video to test settings:
$result = AV1::open('input.mp4') ->abav1() ->sampleEncode() ->crf(30) ->preset('6') ->sample(60) // Sample duration in seconds ->export() ->save('sample.mp4');
Full Encode
Encode the entire video with a specific CRF:
$result = AV1::open('input.mp4') ->abav1() ->encode() ->crf(30) ->preset('6') ->export() ->save('output.mp4');
VMAF Score
Calculate VMAF score between two videos:
$result = AV1::vmaf() ->abav1() ->reference('original.mp4') ->distorted('encoded.mp4') ->export() ->save(); echo $result->getOutput(); // VMAF score
XPSNR Score
Calculate XPSNR score between two videos:
$result = AV1::xpsnr() ->abav1() ->reference('original.mp4') ->distorted('encoded.mp4') ->export() ->save(); echo $result->getOutput(); // XPSNR score
Working with Different Disks
From S3
$result = AV1::fromDisk('s3') ->open('videos/input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->toDisk('s3') ->save('videos/output.mp4');
From Local to S3
$result = AV1::open('local/input.mp4') ->abav1() ->encode() ->crf(30) ->preset('6') ->export() ->toDisk('s3') ->toPath('videos/encoded') ->save('output.mp4');
Advanced Options
CRF Range
$result = AV1::open('input.mp4') ->abav1() ->crfSearch() ->minCrf(20) ->maxCrf(40) ->preset('6') ->minVmaf(95) ->export() ->save();
Max Encoded Size
$result = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->maxEncodedPercent(95) // Max 95% of original size ->export() ->save('output.mp4');
Pixel Format
$result = AV1::open('input.mp4') ->abav1() ->encode() ->crf(30) ->preset('6') ->pixFmt('yuv420p10le') ->export() ->save('output.mp4');
Full VMAF
$result = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->fullVmaf() // Calculate VMAF for entire video ->export() ->save('output.mp4');
VMAF Model
$result = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->vmafModel('/path/to/vmaf_model.json') ->export() ->save('output.mp4');
Verbose Output
$result = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->verbose() ->export() ->save('output.mp4'); echo $result->getOutput();
Batch Processing
Process multiple files:
$files = ['video1.mp4', 'video2.mp4', 'video3.mp4']; AV1::fromDisk('s3') ->each($files, function ($av1, $file) { $av1->open($file) ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->toDisk('s3') ->toPath('encoded') ->save(); });
Callbacks
Add callbacks after encoding:
$result = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->afterSaving(function ($result, $path) { Log::info("Encoded to: {$path}"); Log::info("VMAF score: {$result->getOutput()}"); }) ->save('output.mp4');
Debugging
Get the command that will be executed:
$command = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->getCommand(); echo $command; // Output: ab-av1 auto-encode -i input.mp4 --preset 6 --min-vmaf 95
Or dump and die:
AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->dd();
Configuration
Environment Variables
AB_AV1_BINARY_PATH- Path to ab-av1 binary (default: 'ab-av1')FFMPEG_BINARY_PATH- Path to ffmpeg binary with libsvtav1, libvmaf, libopus (default: 'ffmpeg')AB_AV1_LOG_CHANNEL- Log channel to use (false to disable, null for default)AB_AV1_TIMEOUT- Maximum time in seconds for encoding commands (default: 14400)AB_AV1_PRESET- Default encoder preset 0-13 for svt-av1 (default: 6)AB_AV1_MIN_VMAF- Minimum VMAF score to target (default: 80)AB_AV1_MAX_PERCENT- Maximum encoded file size as percentage (default: 300)AB_AV1_TEMPORARY_FILES_ROOT- Directory for temporary files (default: storage/app/av1/temp)
Error Handling
try { $result = AV1::open('input.mp4') ->abav1() ->vmafEncode() ->preset('6') ->minVmaf(95) ->export() ->save('output.mp4'); if ($result->isSuccessful()) { echo "Encoding successful!"; } else { echo "Encoding failed: " . $result->getErrorOutput(); } } catch (\Exception $e) { echo "Error: " . $e->getMessage(); }
Available Commands
vmafEncode()
Automatically finds the optimal CRF value to achieve a target VMAF score, then encodes the full video at that quality level.
Required options:
preset(string)- Encoder presetminVmaf(float)- Minimum VMAF score
Optional:
maxEncodedPercent(int)- Max size as percentage of inputsample(int)- Sample duration in secondsminCrf(int)- Minimum CRF to trymaxCrf(int)- Maximum CRF to try
crfSearch()
Searches for the optimal CRF value to achieve a target VMAF score without encoding the full video. Useful for testing before full encoding.
Required options:
preset(string)- Encoder preset (0-13 for svt-av1)minVmaf(float)- Target VMAF score (0-100)
Optional: Same as vmafEncode()
sampleEncode()
Encodes a sample portion of the video for testing settings before committing to a full encode.
Required options:
crf(int)- CRF value to use for encodingpreset(string)- Encoder preset (0-13 for svt-av1)
Optional:
sample(int)- Sample duration in seconds (default varies by encoder)
encode()
Encodes the entire video using a manually specified CRF value. Use this when you know the exact CRF you want.
Required options:
crf(int)- CRF value (lower = higher quality, larger file)preset(string)- Encoder preset (0-13 for svt-av1, higher = faster/larger)
vmaf()
Calculates the VMAF (Video Multimethod Assessment Fusion) quality score between a reference and distorted video.
Required options:
reference(string)- Reference (original) video pathdistorted(string)- Distorted (encoded) video path
Optional:
vmafModel(string)- Path to custom VMAF model file
xpsnr()
Calculates the XPSNR (Extended Peak Signal-to-Noise Ratio) quality score between a reference and distorted video.
Required options:
reference(string)- Reference (original) video pathdistorted(string)- Distorted (encoded) video path
Testing
composer test
Credits
- ab-av1 - The underlying encoding tool
- Laravel FFMpeg - Architecture inspiration
License
The MIT License (MIT). Please see License File for more information.