Skip to content

Instantly share code, notes, and snippets.

@Nks
Last active February 15, 2024 02:18
Show Gist options
  • Save Nks/b3b1cd7398a560eda8ddb7e37901869e to your computer and use it in GitHub Desktop.
Save Nks/b3b1cd7398a560eda8ddb7e37901869e to your computer and use it in GitHub Desktop.
Laravel Media Library converting video to .mp4 after saving

How it works?

This listener will convert your .mov, .avi and a lot of others video files to .mp4 after adding media with https://github.com/spatie/laravel-medialibrary Feel free ask anything what you want.

Requirements

Usage

In EventServiceProvider add your event listener for spatie/laravel-medialibrary

protected $listen = [
        'Spatie\MediaLibrary\Events\MediaHasBeenAdded' => [
            'App\Listeners\MediaVideoConverterListener'
        ],

Want use other audio codec? Rewrite it by yourself in the code or just add this in the medialibrary.php config file with your codec.

'audio_codec'                 => 'libvo_aacenc',

Configure supervisord with following instructions:

[program:laravel_queue]
process_name=%(program_name)s_%(process_num)02d
command=/usr/bin/php /home/vagrant/Code/laravel/artisan queue:work --timeout=0 --memory=512 --tries=3
autostart=true
autorestart=true
user=vagrant
numprocs=3
redirect_stderr=true
stdout_logfile=/home/vagrant/Code/laravel/storage/logs/default_queue.log

numprocs <- How many queues will be work on your server. Depends on your memory, CPU, etc. This is how many files will processing in one time. By default 3 video files will be in processing. --memory=512 <- by default it's 128 Mb

<?php
namespace App\Listeners;
use App\Media;
use FFMpeg\FFMpeg;
use FFMpeg\Format\Video\X264;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\SerializesModels;
use Spatie\MediaLibrary\Events\MediaHasBeenAdded;
use Spatie\MediaLibrary\Helpers\File as MediaLibraryFileHelper;
class MediaVideoConverterListener implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
protected $media;
/**
* Create the event listener.
*
*/
public function __construct()
{
}
/**
* Handle the event.
*
* @return void
*/
public function handle(MediaHasBeenAdded $event)
{
$this->media = $event->media;
//prevent any events from media model
$this->media->flushEventListeners();
if ((!$this->isVideo())
|| $this->media->getCustomProperty('status') !== Media::MEDIA_STATUS_TO_CONVERT
|| strtolower($this->media->extension) == 'mp4' || strtolower($this->media->mime_type) == 'video/mp4'
) {
$this->media->setCustomProperty('status', Media::MEDIA_STATUS_READY);
$this->media->setCustomProperty('progress', 100);
$this->media->save();
return;
}
$this->media->setCustomProperty('status', Media::MEDIA_STATUS_PROCESSING);
$this->media->save();
try {
$fullPath = $this->media->getPath();
$newFileFullPath = pathinfo($fullPath, PATHINFO_DIRNAME)
. DIRECTORY_SEPARATOR . pathinfo($fullPath, PATHINFO_FILENAME)
. Media::MEDIA_VIDEO_EXT;
if (file_exists($newFileFullPath)) {
unlink($newFileFullPath);
}
$ffmpeg = FFMpeg::create([
'ffmpeg.binaries' => config('medialibrary.ffmpeg_binaries'),
'ffprobe.binaries' => config('medialibrary.ffprobe_binaries'),
'timeout' => 3600,
'ffmpeg.threads' => 12,
]);
$video = $ffmpeg->open($fullPath);
$format = new X264();
$format->on('progress', function ($video, $format, $percentage) use ($fullPath, $newFileFullPath) {
if ($percentage >= 100) {
$this->mediaConvertingCompleted($fullPath, $newFileFullPath);
} elseif (!($percentage % 10)) {
$this->media->setCustomProperty('progress', $percentage);
$this->media->save();
}
});
$format->setAudioCodec(config('medialibrary.audio_codec', 'libvo_aacenc'))
->setKiloBitrate(1000)
->setAudioChannels(2)
->setAudioKiloBitrate(256);
$video->save($format, $newFileFullPath);
} catch (\Exception $e) {
$this->media->setCustomProperty('status', Media::MEDIA_STATUS_FAILED);
$this->media->setCustomProperty('error', $e->getMessage());
$this->media->save();
}
}
/**
* @param $originalFilePath
* @param $convertedFilePath
*/
protected function mediaConvertingCompleted($originalFilePath, $convertedFilePath)
{
if (file_exists($originalFilePath)) {
unlink($originalFilePath);
}
$this->media->file_name = pathinfo($convertedFilePath, PATHINFO_BASENAME);
$this->media->mime_type = MediaLibraryFileHelper::getMimetype($convertedFilePath);
$this->media->size = filesize($convertedFilePath);
$this->media->setCustomProperty('status', Media::MEDIA_STATUS_READY);
$this->media->setCustomProperty('progress', 100);
$this->media->save();
}
/**
* Is media a video?
*
* @return bool
*/
protected function isVideo()
{
return (strpos($this->media->mime_type, 'video') !== false);
}
}
@horizonvert1027
Copy link

@Nks I have to play .mov file in Laravel. Uploading is running well. but I can't play .mov file.
How to play .mov file with this library?

@Nks
Copy link
Author

Nks commented Jan 25, 2023

@horizonvert1027, you need to convert the file to any playable file in the browser. I suggest using mp4 format for this and convert it to mp4 from mov using ffmpeg: ffmpeg -i input.mov -qscale 0 output.mp4

The provided solution should already be able to convert any supported files to mp4 though.

@horizonvert1027
Copy link

@Nks, Thank you for your reply.
I have made a Laravel framework. But I don't know what to do. Can you send me your contact information?
My e-mail is horizonvert.pu@gmail.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment