使用nova-s3-multipart-upload Laravel Nova包上传至S3时,如何自动为视频或图片添加水印
Hey there! Let's figure out how to add automatic watermarks to your images and videos when using the nova-s3-multipart-upload package for Laravel Nova. Here's a practical, step-by-step approach that integrates smoothly into your workflow:
First, we need tools to handle image and video processing:
For images: Use Intervention Image, a popular Laravel image manipulation library. Install it via Composer:
composer require intervention/imageLaravel 5.5+ auto-discovers the package, but if you're on an older version, add the service provider and facade to your
config/app.php.For videos: Use php-ffmpeg, which wraps FFmpeg for PHP. Install it with:
composer require php-ffmpeg/php-ffmpegImportant: Ensure your server has FFmpeg installed (check with
ffmpeg -vin the terminal) and note the path to the binaries for later configuration.
The nova-s3-multipart-upload field allows you to override the default store method, which is where we'll inject our watermarking logic. In your Nova resource's fields method:
use Ahmedkandel\NovaS3MultipartUpload\S3MultipartUpload; use Illuminate\Http\Request; public function fields(Request $request) { return [ // Your other Nova fields... S3MultipartUpload::make('Media Files') ->disk('s3') ->acceptedTypes('image/*,video/*') ->store(function (Request $request, $model) { $uploadedPaths = []; $files = $request->file('media_files'); foreach ($files as $file) { // Process the file with watermark first $processedFile = $this->addWatermark($file); // Upload the processed file to S3 $path = $processedFile->store('uploads', 's3'); $uploadedPaths[] = $path; // Optional: Clean up the temporary processed file unlink($processedFile->getPathname()); } return $uploadedPaths; }), ]; }
Add a private method to your Nova resource to handle both image and video watermarking. This method takes the uploaded file, processes it, and returns the processed file for upload:
use Intervention\Image\Facades\Image; use FFMpeg\FFMpeg; use FFMpeg\Format\Video\X264; use Illuminate\Http\File; private function addWatermark($file) { $mime = $file->getMimeType(); $watermarkPath = storage_path('app/public/watermark.png'); // Update this to your watermark's path // Handle image files if (str_starts_with($mime, 'image/')) { $image = Image::make($file->getRealPath()); $watermark = Image::make($watermarkPath); // Resize watermark to 15% of the image's width (adjust as needed) $watermark->resize($image->width() * 0.15, null, function ($constraint) { $constraint->aspectRatio(); }); // Place watermark in the bottom-right corner with 10px padding $image->insert($watermark, 'bottom-right', 10, 10); // Save processed image to a temporary file $tempFile = tempnam(sys_get_temp_dir(), 'watermarked_img_'); $image->save($tempFile); return new File($tempFile); } // Handle video files if (str_starts_with($mime, 'video/')) { $ffmpeg = FFMpeg::create([ 'ffmpeg.binaries' => '/usr/bin/ffmpeg', // Update to your server's FFmpeg path 'ffprobe.binaries' => '/usr/bin/ffprobe', // Update to your server's FFprobe path ]); $video = $ffmpeg->open($file->getRealPath()); // Add watermark to bottom-right corner with 10px padding $video->filters()->watermark($watermarkPath, [ 'position' => 'relative', 'bottom' => 10, 'right' => 10, ]); // Save processed video to a temporary file $tempFile = tempnam(sys_get_temp_dir(), 'watermarked_vid_') . '.' . $file->getClientOriginalExtension(); $video->save(new X264(), $tempFile); return new File($tempFile); } // Return original file if it's not an image/video return $file; }
- Watermark Preparation: Use a PNG watermark with transparency for best results, and place it in
storage/app/public(runphp artisan storage:linkto make it accessible). - Server Configuration: For video processing, double-check FFmpeg paths and ensure your server has enough memory/CPU to handle large video files.
- Upload Limits: Adjust PHP's
upload_max_filesize,post_max_size, andmemory_limitin your php.ini to accommodate large media files. - Temporary Files: The code above cleans up temporary processed files after upload, but you can also rely on your server's temp file cleanup mechanism if preferred.
内容的提问来源于stack exchange,提问作者Sargis

