This commit is contained in:
ct
2025-06-13 17:11:59 +08:00
parent 248a717898
commit 61923f4e1f
17 changed files with 515 additions and 41 deletions

View File

@@ -0,0 +1,191 @@
<?php
namespace App\Http\Controllers;
use App\Models\BackgroundMedia;
use Illuminate\Http\Request;
use Inertia\Inertia;
class AdminBackgroundGenerationController extends Controller
{
public function index(Request $request)
{
// Load a random record with status 'pending_media'
$pendingMedia = BackgroundMedia::where('status', 'pending_media')
->whereIn('list_type', ['residential', 'commercial'])
->inRandomOrder()
->first();
return Inertia::render('admin/background-gen', [
'pendingMedia' => $pendingMedia,
]);
}
public function generate(Request $request)
{
$request->validate([
'prompt' => 'required|string|max:1000',
'media_id' => 'required|exists:background_medias,id',
]);
$prompt = $request->input('prompt');
// Call Replicate API
$replicateResponse = $this->callReplicateAPI($prompt);
if (! $replicateResponse || ! isset($replicateResponse['urls']['get'])) {
return response()->json(['error' => 'Failed to start generation'], 500);
}
// Poll for result
$result = $this->pollReplicateResult($replicateResponse['urls']['get']);
if (! $result || ! isset($result['output'][0])) {
return response()->json(['error' => 'Generation failed or timed out'], 500);
}
return response()->json([
'success' => true,
'image_url' => $result['output'][0],
]);
}
public function delete($id)
{
try {
$media = BackgroundMedia::where('id', $id)
->where('status', 'pending_media')
->first();
if (! $media) {
return response()->json([
'success' => false,
'error' => 'Pending media not found or already processed',
], 404);
}
$media->delete();
return response()->json([
'success' => true,
'message' => 'Media deleted successfully',
]);
} catch (\Exception $e) {
\Log::error('Error deleting pending media: '.$e->getMessage());
return response()->json([
'success' => false,
'error' => 'An error occurred while deleting the media',
], 500);
}
}
public function save(Request $request)
{
$request->validate([
'media_id' => 'required|exists:background_medias,id',
'image_url' => 'required|url',
'prompt' => 'required|string',
]);
$backgroundMedia = BackgroundMedia::findOrFail($request->input('media_id'));
// try {
// Use MediaEngine to download and store the image
$media = \App\Helpers\FirstParty\MediaEngine\MediaEngine::addMedia(
'system-i',
'image',
'system_uploaded',
'replicate',
null,
$request->input('image_url'),
'download'
);
// Update the background media record
$backgroundMedia->update([
'status' => 'completed',
'media_uuid' => $media->uuid,
'media_url' => \App\Helpers\FirstParty\MediaEngine\MediaEngine::getMediaCloudUrl($media),
'prompt' => $request->input('prompt'),
]);
return response()->json(['success' => true]);
// } catch (\Exception $e) {
// return response()->json(['error' => 'Failed to save media: ' . $e->getMessage()], 500);
// }
}
private function callReplicateAPI($prompt)
{
$apiToken = config('services.replicate.api_token');
$data = [
'input' => [
'prompt' => $prompt,
'go_fast' => true,
'megapixels' => '1',
'num_outputs' => 1,
'aspect_ratio' => '1:1',
'output_format' => 'webp',
'output_quality' => 80,
'num_inference_steps' => 4,
],
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer '.$apiToken,
'Content-Type: application/json',
'Prefer: wait',
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 201) {
return false;
}
return json_decode($response, true);
}
private function pollReplicateResult($getUrl)
{
$maxAttempts = 30; // 5 minutes max (30 * 10 seconds)
$attempt = 0;
while ($attempt < $maxAttempts) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $getUrl);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer '.config('services.replicate.api_token'),
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
$result = json_decode($response, true);
if ($result['status'] === 'succeeded' && isset($result['output'][0])) {
return $result;
} elseif ($result['status'] === 'failed') {
return false;
}
}
$attempt++;
sleep(3); // Wait 10 seconds before next poll
}
return false; // Timeout
}
}