- Added authentication controllers (Login, Register) - Added UserController for user profile management - Added VideoController with full CRUD operations - Added Video model with relationships (user, likes, views) - Added User model enhancements (avatar, video relationships) - Added database migrations for video_likes, video_views, user_avatar, video_visibility - Added CompressVideoJob for video processing - Added VideoUploaded mail notification - Added authentication routes - Updated web routes with video and user routes - Added layout templates (app, plain, partials) - Added user views (profile, settings, channel, history, liked) - Added video views (create, edit, index, show) - Added email templates
96 lines
3.4 KiB
PHP
96 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Jobs;
|
|
|
|
use App\Models\Video;
|
|
use FFMpeg\FFMpeg;
|
|
use FFMpeg\Format\Video\X264;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class CompressVideoJob implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
public $video;
|
|
|
|
public function __construct(Video $video)
|
|
{
|
|
$this->video = $video;
|
|
}
|
|
|
|
public function handle()
|
|
{
|
|
$video = $this->video;
|
|
|
|
// Get original file path
|
|
$originalPath = storage_path('app/' . $video->path);
|
|
|
|
if (!file_exists($originalPath)) {
|
|
Log::error('CompressVideoJob: Original file not found: ' . $originalPath);
|
|
return;
|
|
}
|
|
|
|
// Create compressed filename
|
|
$compressedFilename = 'compressed_' . $video->filename;
|
|
$compressedPath = storage_path('app/public/videos/' . $compressedFilename);
|
|
|
|
try {
|
|
$ffmpeg = FFMpeg::create();
|
|
$ffmpegVideo = $ffmpeg->open($originalPath);
|
|
|
|
// Use CRF 18 for high quality (lower = better quality, 18-23 is good range)
|
|
// Use 'slow' preset for better compression efficiency
|
|
$format = new X264('aac', 'libx264');
|
|
$format->setKiloBitrate(0); // 0 = use CRF
|
|
$format->setAudioKiloBitrate(192);
|
|
|
|
// Add CRF option for high quality
|
|
$ffmpegVideo->save($format, $compressedPath);
|
|
|
|
// Check if compressed file was created and is smaller
|
|
if (file_exists($compressedPath)) {
|
|
$originalSize = filesize($originalPath);
|
|
$compressedSize = filesize($compressedPath);
|
|
|
|
// Only use compressed file if it's smaller
|
|
if ($compressedSize < $originalSize) {
|
|
// Delete original and rename compressed
|
|
unlink($originalPath);
|
|
rename($compressedPath, $originalPath);
|
|
|
|
// Update video record
|
|
$video->update([
|
|
'size' => $compressedSize,
|
|
'filename' => $video->filename, // Keep same filename
|
|
'mime_type' => 'video/mp4',
|
|
]);
|
|
|
|
Log::info('CompressVideoJob: Video compressed successfully', [
|
|
'video_id' => $video->id,
|
|
'original_size' => $originalSize,
|
|
'compressed_size' => $compressedSize,
|
|
'saved' => round(($originalSize - $compressedSize) / $originalSize * 100) . '%'
|
|
]);
|
|
} else {
|
|
// Compressed file is larger, delete it
|
|
unlink($compressedPath);
|
|
Log::info('CompressVideoJob: Compression made file larger, keeping original');
|
|
}
|
|
}
|
|
|
|
$video->update(['status' => 'ready']);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('CompressVideoJob failed: ' . $e->getMessage());
|
|
$video->update(['status' => 'ready']); // Mark as ready anyway
|
|
}
|
|
}
|
|
}
|
|
|