Files
wticreatorstudio/Modules/StudioPlus/Services/GoogleCloudPlatform.php
2024-05-16 15:14:42 +08:00

299 lines
12 KiB
PHP

<?php
namespace Modules\StudioPlus\Services;
use \FFMpeg\FFMpeg;
use \FFMpeg\FFProbe;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Config;
use Google\Cloud\Storage\StorageClient;
use Illuminate\Support\Facades\Storage;
use Modules\StudioPlus\Entities\StudioPlusVideo;
use Modules\StudioPlus\Entities\StudioPlusChannel;
use Modules\StudioPlus\Entities\StudioPlusVideoType;
class GoogleCloudPlatform
{
private $storageClient;
private $bucketName;
private $googleApiEndpoint;
public function __construct()
{
$this->storageClient = new StorageClient([
'keyFile' => json_decode(file_get_contents(module_path('StudioPlus', 'google-cloud-platform.json')), true)
]);
$this->bucketName = Config::get('studioplus.bucket_name');
$this->googleApiEndpoint = Config::get('studioplus.google_api_endpoint');
}
public function storeNewVideo(StudioPlusChannel $studioPlusChannel, string $title, string $fileName, array $params = [])
{
$params['title'] = $title;
$params['filename'] = $fileName;
if (!isset($params['amazon_total_reviews'])) {
$params['amazon_total_reviews'] = 0;
}
if((boolean)$params['video_type']['need_asin']){
$video = StudioPlusVideo::where('asin', $params['asin'])->first();
if ($video) {
if(!(boolean)$params['video_type']['need_job_request']){
$params['status'] = StudioPlusVideo::STATUS_EDITED;
}
if (isset($params['description'])) {
$params['description'] = "*DUPLICATE ASIN* " . $params['description'];
}
else {
$params['description'] = "*DUPLICATE ASIN* ";
}
}
}
if(permissionCheck('job_board.creator.index') && auth()->user()->role->type == 'staff') {
$badges = auth()->user()->staff->badges != null ? (array) json_decode(auth()->user()->staff->badges) : [];
//for 1st 10 badge only
if(in_array(1, $badges) && $params['studio_plus_video_type_id'] == 1){
$params['status'] = StudioPlusVideo::STATUS_EDITED;
}
}
return $studioPlusChannel->videos()->create($params);
}
public function uploadFileToGCP(string $pathToFile, string $objectName)
{
$bucket = $this->storageClient->bucket($this->bucketName);
$bucket->upload(
fopen($pathToFile, 'r'),
[
'name' => $objectName,
'metadata' => [
'contentDisposition' => 'attachment',
],
]
);
}
public function getGoogleStoragePath(StudioPlusVideo $studioPlusVideo): string
{
return "uploads/users/" . $studioPlusVideo->channel->user_id . "/videos/{$studioPlusVideo->id}";
}
private function getLocalStoragePath(StudioPlusVideo $studioPlusVideo): string
{
return "StudioPlus/" . $studioPlusVideo->channel->user_id . "/videos/" . $studioPlusVideo->id;
}
public function handleUploadVideox(Request $request, StudioPlusChannel $studioPlusChannel): StudioPlusVideo
{
$fileName = $request->file('video')->getClientOriginalName();
$fileName = str_replace(' ', '', $fileName);
$explodedFileName = explode('.', $fileName);
$title = collect(Arr::except($explodedFileName, array_key_last($explodedFileName)))->join(' ');
$upload = $this->storeNewVideo(
$studioPlusChannel,
$title,
$fileName
);
$gcpStoragePath = $this->getGoogleStoragePath($upload);
$objectName = "$gcpStoragePath/$fileName";
$this->uploadFileToGCP($request->file('video')->path(), $objectName);
$upload->original_video_url = $objectName;
$upload->video_url = $objectName;
$localStoragePath = $this->getLocalStoragePath($upload);
$videoLocalUrl = Storage::putFileAs($localStoragePath, $request->file('video'), $fileName);
VideoService::copyAndRescale(storage_path("app/$localStoragePath/$fileName"), storage_path("app/$localStoragePath/video.mp4"));
$ffmpeg = FFMpeg::create();
$video = $ffmpeg->open(storage_path("app/{$videoLocalUrl}"));
$ffprobe = FFProbe::create(get_ffprobe_config());
$codeAc = $ffprobe->format(storage_path("app/{$videoLocalUrl}"))->get('duration');
$upload->video_duration = round($codeAc, PHP_ROUND_HALF_UP);
$upload->save();
$timeFrameInSeconds = 2;
for ($i = 0; $i < 3; $i++) {
if ($timeFrameInSeconds < round($codeAc, PHP_ROUND_HALF_DOWN)) {
$thumbnailFilename = Str::random(10) . ".jpg";
$thumbnailFilePath = "$gcpStoragePath/thumbnails/$thumbnailFilename";
$video->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds($timeFrameInSeconds))
->save(storage_path("app/$localStoragePath/$thumbnailFilename"));
$this->uploadFileToGCP(storage_path("app/$localStoragePath/$thumbnailFilename"), $thumbnailFilePath);
Storage::delete("$localStoragePath/$thumbnailFilename");
$upload->thumbnails()->create([
'thumbnail_url' => "$thumbnailFilePath",
'filename' => $thumbnailFilename,
'is_active' => $i === 0
]);
$timeFrameInSeconds += 2;
}
}
Storage::delete($videoLocalUrl);
return $upload->load('thumbnails');
}
public function handleUploadVideo(Request $request, StudioPlusChannel $studioPlusChannel): StudioPlusVideo
{
$fileName = $request->file('video')->getClientOriginalName();
$fileName = str_replace(' ', '', $fileName);
$explodedFileName = explode('.', $fileName);
$title = collect(Arr::except($explodedFileName, array_key_last($explodedFileName)))->join(' ');
$upload = $this->storeNewVideo(
$studioPlusChannel,
$title,
$fileName
);
$gcpStoragePath = $this->getGoogleStoragePath($upload);
$objectName = "$gcpStoragePath/$fileName";
$this->uploadFileToGCP($request->file('video')->path(), $objectName);
$upload->original_video_url = $objectName;
$upload->video_url = $objectName;
$localStoragePath = $this->getLocalStoragePath($upload);
$videoLocalUrl = Storage::putFileAs($localStoragePath, $request->file('video'), $fileName);
VideoService::copyAndRescale(storage_path("app/$localStoragePath/$fileName"), storage_path("app/$localStoragePath/video.mp4"));
$ffmpeg = FFMpeg::create();
$video = $ffmpeg->open(storage_path("app/{$videoLocalUrl}"));
$ffprobe = FFProbe::create(get_ffprobe_config());
$codeAc = $ffprobe->format(storage_path("app/{$videoLocalUrl}"))->get('duration');
$upload->video_duration = round($codeAc, PHP_ROUND_HALF_UP);
$upload->save();
$timeFrameInSeconds = 2;
for ($i = 0; $i < 3; $i++) {
if ($timeFrameInSeconds < round($codeAc, PHP_ROUND_HALF_DOWN)) {
$thumbnailFilename = Str::random(10) . ".jpg";
$thumbnailFilePath = "$gcpStoragePath/thumbnails/$thumbnailFilename";
$video->frame(\FFMpeg\Coordinate\TimeCode::fromSeconds($timeFrameInSeconds))
->save(storage_path("app/$localStoragePath/$thumbnailFilename"));
$this->uploadFileToGCP(storage_path("app/$localStoragePath/$thumbnailFilename"), $thumbnailFilePath);
Storage::delete("$localStoragePath/$thumbnailFilename");
$upload->thumbnails()->create([
'thumbnail_url' => "$thumbnailFilePath",
'filename' => $thumbnailFilename,
'is_active' => $i === 0
]);
$timeFrameInSeconds += 2;
}
}
Storage::delete($videoLocalUrl);
return $upload->load('thumbnails');
}
public function handleUploadThumbnail(Request $request, StudioPlusChannel $studioPlusChannel, StudioPlusVideo $studioPlusVideo)
{
$fileName = $request->file('thumbnail')->getClientOriginalName();
$fullPath = "/uploads/users/" . auth()->id() . "/videos/{$studioPlusVideo->id}/thumbnails/$fileName";
$this->uploadFileToGCP($request->file('thumbnail'), $fullPath);
if($request->has('type') && $request->type == 'short'){
$uploadedThumbnail = $studioPlusVideo->thumbnails()->where('is_uploaded', 1)->where('is_short', 1)->first();
} else {
$uploadedThumbnail = $studioPlusVideo->thumbnails()->where('is_uploaded', 1)->first();
}
if ($uploadedThumbnail) {
$uploadedThumbnail->update([
'filename' => $fileName,
'thumbnail_url' => "$fullPath",
'is_short' => $request->has('type') ? true : false,
'is_uploaded' => true
]);
} else {
$studioPlusVideo->thumbnails()->create([
'filename' => $fileName,
'thumbnail_url' => "$fullPath",
'is_short' => $request->has('type') ? true : false,
'is_uploaded' => true
]);
}
}
public function updateVideo(StudioPlusVideo $studioPlusVideo)
{
$localStoragePath = $this->getLocalStoragePath($studioPlusVideo);
Storage::makeDirectory('CreatorStudio');
$globalSetting = $studioPlusVideo->globalSetting;
if ($globalSetting) {
$introLocalPath = storage_path('app/public/' . $globalSetting->details['intro']);
$outroLocalPath = storage_path('app/public/' . $globalSetting->details['outro']);
$outroOutputPath = storage_path("app/CreatorStudio/outro.mp4");
Storage::delete('CreatorStudio/outro.mp4');
VideoService::copyAndRescale($outroLocalPath, $outroOutputPath);
} else {
$introLocalPath = module_path('StudioPlus') . "/Storage/default.ts";
}
$introOutputPath = storage_path("app/CreatorStudio/intro.mp4");
Storage::delete('CreatorStudio/intro.mp4');
VideoService::copyAndRescale($introLocalPath, $introOutputPath);
$resultPath = storage_path("app/$localStoragePath/video.mp4");
$video = (new GCPService)->download($studioPlusVideo, public_path('CreatorStudio'));
$outroOutputPath = isset($outroOutputPath) ? $outroOutputPath : $introOutputPath;
VideoService::concat(
$introOutputPath,
$video,
$resultPath,
$outroOutputPath
);
$newFileName = Str::random() . ".mp4";
$objectName = $this->getGoogleStoragePath($studioPlusVideo) . "/$newFileName";
$this->uploadFileToGCP($resultPath, $objectName);
if (File::exists($video)) {
File::delete($video);
}
Storage::delete("$localStoragePath/video.mp4");
$studioPlusVideo->update([
'video_url' => $objectName,
'upload_status' => StudioPlusVideo::UPLOAD_STATUS_COMPLETE
]);
}
}