LaravelPackages.net
Acme Inc.
Toggle sidebar
christyoga123/video-optimizer

A fluent Laravel package for optimizing videos - resize, convert formats (MP4, WebM, AVI), compress and reduce file size while maintaining quality

924
0
v1.1.0
About christyoga123/video-optimizer

christyoga123/video-optimizer is a Laravel package for a fluent laravel package for optimizing videos - resize, convert formats (mp4, webm, avi), compress and reduce file size while maintaining quality. It currently has 0 GitHub stars and 924 downloads on Packagist (latest version v1.1.0). Install it with composer require christyoga123/video-optimizer. Discover more Laravel packages by christyoga123 or browse all Laravel packages to compare alternatives.

Last updated

Laravel Video Optimizer

A fluent Laravel package for optimizing videos - resize, convert formats (MP4, WebM, AVI), compress and reduce file size while maintaining quality.

Latest Version on Packagist License

Features

  • 🎬 Format Conversion - Convert videos to MP4, WebM, OGG, MOV, MKV, AVI

  • πŸ“ Smart Resize - Resize with max width/height while maintaining aspect ratio

  • 🎚️ Quality Control - Adjustable bitrate, CRF, and preset settings

  • πŸ”§ Fluent API - Chain methods for clean, readable code

  • βš™οΈ Configurable - Publish and customize default settings

  • πŸ–ΌοΈ Thumbnail Generation - Extract thumbnails from videos

  • πŸ”‡ Audio Control - Option to remove or keep audio

  • 🎡 Smart Audio Codecs - Auto-detects best audio codecs (fixes WebM/Ogg issues on macOS/Homebrew)

  • πŸ“Š Video Info - Get duration, dimensions, codec info

  • 🧹 Auto Cleanup - Automatic temporary file cleanup with dontCleanup() option

  • πŸ“¦ Queueable Job - Built-in job for background processing

Requirements

  • PHP 8.1+
  • Laravel 10.x, 11.x, or 12.x
  • FFmpeg installed on your server

Installing FFmpeg

macOS:

brew install ffmpeg

Ubuntu/Debian:

sudo apt update
sudo apt install ffmpeg

Windows: Download from ffmpeg.org and add to PATH.

Installation

Install the package via Composer:

composer require christyoga123/video-optimizer

The package will automatically register its service provider.

Publish Configuration (Optional)

php artisan vendor:publish --tag=video-optimizer-config

This will create a config/video-optimizer.php file with all available options.

Usage

Basic Usage

use Christyoga123\VideoOptimizer\VideoOptimizer;

// Process uploaded file and get optimized temp path
$tempPath = VideoOptimizer::make()
    ->toMp4()
    ->maxDimensions(1920, 1080)
    ->videoBitrate(1500)
    ->process($uploadedFile);

// Do something with the optimized file
Storage::disk('public')->put('videos/video.mp4', file_get_contents($tempPath));

Using Facade

use Christyoga123\VideoOptimizer\Facades\VideoOptimizer;

$tempPath = VideoOptimizer::make()
    ->toMp4()
    ->crf(23)
    ->preset('fast')
    ->process($request->file('video'));

From Request Input

$tempPath = VideoOptimizer::make()
    ->toWebm()
    ->videoBitrate(2000)
    ->processFromRequest('video');

if ($tempPath) {
    // File was uploaded and processed
    $post->update(['video' => Storage::putFile('videos', $tempPath)]);
}

From File Path

$tempPath = VideoOptimizer::make()
    ->toMp4()
    ->maxDimensions(1280, 720)
    ->crf(28)
    ->processFromPath('/path/to/original/video.mov');

With Default Settings

Apply all defaults from config at once:

$tempPath = VideoOptimizer::make()
    ->withDefaults()
    ->process($uploadedFile);

With Thumbnail Generation

$optimizer = VideoOptimizer::make()
    ->toMp4()
    ->withThumbnail(5); // Capture at 5 seconds

$videoPath = $optimizer->process($uploadedFile);
$thumbnailPath = $optimizer->getThumbnailPath();

// Store both video and thumbnail
Storage::disk('public')->put('videos/video.mp4', file_get_contents($videoPath));
Storage::disk('public')->put('thumbnails/thumb.jpg', file_get_contents($thumbnailPath));

Remove Audio

$tempPath = VideoOptimizer::make()
    ->toMp4()
    ->noAudio()
    ->process($uploadedFile);

Get Video Information

$optimizer = VideoOptimizer::make();

// Get video info before processing
$info = $optimizer->getVideoInfo($uploadedFile->getRealPath());

// Result:
// [
//     'duration' => 120.5,
//     'bitrate' => 2500000,
//     'size' => 37500000,
//     'format' => 'mov,mp4,m4a,3gp,3g2,mj2',
//     'width' => 1920,
//     'height' => 1080,
//     'video_codec' => 'h264',
//     'audio_codec' => 'aac',
//     'frame_rate' => '30/1',
// ]

Get Size Comparison

$optimizer = VideoOptimizer::make()
    ->toMp4()
    ->crf(28)
    ->maxDimensions(1280, 720);

$tempPath = $optimizer->process($uploadedFile);

$comparison = $optimizer->getSizeComparison($uploadedFile->getRealPath());

// Result:
// [
//     'original_size' => 50000000,
//     'optimized_size' => 12500000,
//     'saved_bytes' => 37500000,
//     'saved_percentage' => 75.0
// ]

echo "Saved: " . $optimizer->formatFileSize($comparison['saved_bytes']);
// Output: "Saved: 35.76 MB"

Helper Methods

$optimizer = VideoOptimizer::make();

// Get sanitized filename for storage
$filename = $optimizer->getOptimizedFilename($uploadedFile);
// "my_video.mp4"

// Get current format
$format = $optimizer->getFormat();
// "mp4"

// Get temp file path
$path = $optimizer->getTempPath();

// Get thumbnail path (if generated)
$thumbnail = $optimizer->getThumbnailPath();

// Get video duration
$duration = $optimizer->getDuration($uploadedFile->getRealPath());

// Get video dimensions
$dimensions = $optimizer->getDimensions($uploadedFile->getRealPath());
// ['width' => 1920, 'height' => 1080]

// Manual cleanup (usually not needed - destructor handles this)
$optimizer->cleanup();

Available Methods

Format Methods

| Method | Description | | ------------------------ | ---------------------------------------- | | format(string $format) | Set output format (mp4, webm, ogg, etc.) | | toMp4() | Convert to MP4 format (H.264 + AAC) | | toWebm() | Convert to WebM format (VP9 + Vorbis) | | toOgg() | Convert to OGG format (Theora + Vorbis) | | toMov() | Convert to MOV format (H.264 + AAC) | | toMkv() | Convert to MKV format (H.264 + AAC) | | toAvi() | Convert to AVI format (H.264 + MP3) |

Codec Methods

| Method | Description | | --------------------------- | --------------- | | videoCodec(string $codec) | Set video codec | | audioCodec(string $codec) | Set audio codec |

Resize Methods

| Method | Description | | ---------------------------------------- | ------------------------------------------- | | maxWidth(int $width) | Set maximum width (maintains aspect ratio) | | maxHeight(int $height) | Set maximum height (maintains aspect ratio) | | maxDimensions(int $width, int $height) | Set both max width and height |

Quality & Settings

| Method | Description | | ------------------------- | ------------------------------------------- | | videoBitrate(int $kbps) | Set video bitrate in kbps | | audioBitrate(int $kbps) | Set audio bitrate in kbps | | crf(int $value) | Set CRF (0-51, lower = better quality) | | preset(string $preset) | Set encoding preset (ultrafast to veryslow) | | tempDir(string $path) | Set custom temporary directory | | timeout(int $seconds) | Set processing timeout | | threads(int $count) | Set number of threads | | withDefaults() | Apply all defaults from config |

Audio Control

| Method | Description | | ------------- | ----------------------- | | noAudio() | Remove audio from video | | withAudio() | Keep audio in video |

Thumbnail Methods

| Method | Description | | ------------------------------ | -------------------------------------------- | | withThumbnail(int $atSecond) | Enable thumbnail generation at specific time | | getThumbnailPath() | Get generated thumbnail path |

Process Methods

| Method | Description | | ----------------------------------------- | ------------------------------- | | process(UploadedFile $file) | Process uploaded file | | processUploadedFile(UploadedFile $file) | Alias for process() | | processFromPath(string $path) | Process from file path | | processFromRequest(string $inputName) | Process from request input name |

Info Methods

| Method | Description | | ----------------------------- | ----------------------------- | | getDuration(string $path) | Get video duration in seconds | | getDimensions(string $path) | Get video width and height | | getVideoInfo(string $path) | Get complete video info |

Configuration

After publishing, you can customize these options in config/video-optimizer.php:

return [
    // FFmpeg binary paths (null = auto-detect)
    'ffmpeg_path' => env('VIDEO_OPTIMIZER_FFMPEG_PATH', null),
    'ffprobe_path' => env('VIDEO_OPTIMIZER_FFPROBE_PATH', null),

    // Processing timeout in seconds
    'timeout' => env('VIDEO_OPTIMIZER_TIMEOUT', 3600),

    // Number of threads (0 = auto)
    'threads' => env('VIDEO_OPTIMIZER_THREADS', 0),

    // Default output format
    'format' => env('VIDEO_OPTIMIZER_FORMAT', 'mp4'),

    // Default codecs
    'video_codec' => env('VIDEO_OPTIMIZER_VIDEO_CODEC', 'libx264'),
    'audio_codec' => env('VIDEO_OPTIMIZER_AUDIO_CODEC', 'aac'),

    // Default bitrates
    'video_bitrate' => env('VIDEO_OPTIMIZER_VIDEO_BITRATE', 1500),
    'audio_bitrate' => env('VIDEO_OPTIMIZER_AUDIO_BITRATE', 128),

    // Default max dimensions
    'max_width' => env('VIDEO_OPTIMIZER_MAX_WIDTH', 1920),
    'max_height' => env('VIDEO_OPTIMIZER_MAX_HEIGHT', 1080),

    // CRF (Constant Rate Factor) - lower = better quality
    'crf' => env('VIDEO_OPTIMIZER_CRF', 23),

    // Encoding preset
    'preset' => env('VIDEO_OPTIMIZER_PRESET', 'medium'),

    // Temporary directory
    'temp_dir' => env('VIDEO_OPTIMIZER_TEMP_DIR', storage_path('app/temp')),

    // Thumbnail generation
    'generate_thumbnail' => env('VIDEO_OPTIMIZER_GENERATE_THUMBNAIL', false),
    'thumbnail_time' => env('VIDEO_OPTIMIZER_THUMBNAIL_TIME', 1),
];

For Web Streaming (Balance)

VideoOptimizer::make()
    ->toMp4()
    ->crf(23)
    ->preset('medium')
    ->maxDimensions(1920, 1080)
    ->process($file);

For Small File Size

VideoOptimizer::make()
    ->toMp4()
    ->crf(28)
    ->preset('slow')
    ->maxDimensions(1280, 720)
    ->videoBitrate(1000)
    ->process($file);

For High Quality

VideoOptimizer::make()
    ->toMp4()
    ->crf(18)
    ->preset('slower')
    ->videoBitrate(4000)
    ->process($file);

For Fast Processing

VideoOptimizer::make()
    ->toMp4()
    ->preset('ultrafast')
    ->process($file);

Integration Examples

With Spatie Media Library

use Christyoga123\VideoOptimizer\VideoOptimizer;

// Optimize before adding to media collection
$tempPath = VideoOptimizer::make()
    ->toMp4()
    ->maxDimensions(1920, 1080)
    ->crf(23)
    ->process($request->file('video'));

$model->addMedia($tempPath)
    ->usingFileName('optimized-video.mp4')
    ->toMediaCollection('videos');

With Laravel Storage

$optimizer = VideoOptimizer::make()
    ->toMp4()
    ->crf(23)
    ->withThumbnail(3);

$tempPath = $optimizer->process($request->file('video'));
$filename = $optimizer->getOptimizedFilename($request->file('video'));

// Store video
$videoPath = Storage::disk('public')->putFileAs('uploads/videos', $tempPath, $filename);

// Store thumbnail
$thumbnailFilename = pathinfo($filename, PATHINFO_FILENAME) . '.jpg';
$thumbnailPath = Storage::disk('public')->putFileAs('uploads/thumbnails', $optimizer->getThumbnailPath(), $thumbnailFilename);

return response()->json([
    'video' => $videoPath,
    'thumbnail' => $thumbnailPath,
]);

In Form Request

// app/Http/Requests/StoreVideoRequest.php
public function passedValidation()
{
    if ($this->hasFile('video')) {
        $optimizer = VideoOptimizer::make()
            ->withDefaults()
            ->withThumbnail(1);

        $tempPath = $optimizer->process($this->file('video'));

        $this->merge([
            'optimized_video_path' => $tempPath,
            'thumbnail_path' => $optimizer->getThumbnailPath(),
        ]);
    }
}
    }
}

Queueable Job

The package includes a ready-to-use job for background processing:

use Christyoga123\VideoOptimizer\Jobs\OptimizeVideoJob;

// Dispatch job
OptimizeVideoJob::dispatch(
    $sourcePath,           // Full path to source file
    $destinationPath,      // Full path to save result (optional, overwrites source if null)
    [                      // Options array
        'format' => 'mp4',
        'crf' => 23,
        'preset' => 'fast'
    ],
    true                   // Delete source file after optimization? (default: false)
);

Manual Cleanup Control

By default, the optimizer cleans up temporary files when the object is destroyed. If you need to keep the file longer (e.g., passing between jobs), use dontCleanup():

$optimizer = VideoOptimizer::make()
    ->toMp4()
    ->dontCleanup() // Prevent auto-deletion
    ->process($file);

// ... do something time consuming ...

// Manually cleanup when done
$optimizer->cleanup();

Custom Job Implementation

In Queue Job

// app/Jobs/OptimizeVideo.php
class OptimizeVideo implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        public string $videoPath,
        public int $postId
    ) {}

    public function handle(): void
    {
        $optimizer = VideoOptimizer::make()
            ->toMp4()
            ->crf(23)
            ->maxDimensions(1920, 1080)
            ->withThumbnail(3);

        $tempPath = $optimizer->processFromPath($this->videoPath);

        // Store optimized video
        $filename = 'video_' . $this->postId . '.mp4';
        Storage::disk('public')->put('videos/' . $filename, file_get_contents($tempPath));

        // Store thumbnail
        $thumbFilename = 'thumb_' . $this->postId . '.jpg';
        Storage::disk('public')->put('thumbnails/' . $thumbFilename, file_get_contents($optimizer->getThumbnailPath()));

        // Update post
        Post::find($this->postId)->update([
            'video_path' => 'videos/' . $filename,
            'thumbnail_path' => 'thumbnails/' . $thumbFilename,
            'video_processed' => true,
        ]);

        // Delete original file
        @unlink($this->videoPath);
    }
}

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Comments