baseUrl = config('services.gemini.base_url'); $this->apiKey = config('services.gemini.api_key'); } /** * CM송 제작 페이지 */ public function index(Request $request): View|\Illuminate\Http\Response { if ($request->header('HX-Request')) { return response('', 200)->header('HX-Redirect', route('rd.cm-song.index')); } return view('rd.cm-song.index'); } /** * CM송 가사 생성 (Gemini API) */ public function generateLyrics(Request $request): JsonResponse { $request->validate([ 'company_name' => 'required|string|max:100', 'industry' => 'required|string|max:200', 'mood' => 'required|string|max:50', ]); $prompt = "당신은 전문 CM송 작사가입니다. 다음 정보를 바탕으로 짧고 기억에 남는 15초 분량의 라디오 CM송 가사를 작성해주세요. 회사명: {$request->company_name} 업종/제품: {$request->industry} 분위기: {$request->mood} 조건: - 3~4줄로 짧게 작성 - 운율을 살려서 작성 - 지시문(예: (음악 소리), (밝은 목소리로)) 없이 오직 읽을 수 있는 가사 텍스트만 출력할 것."; try { $response = Http::timeout(30)->post( "{$this->baseUrl}/models/gemini-2.5-flash:generateContent?key={$this->apiKey}", [ 'contents' => [ ['parts' => [['text' => $prompt]]], ], ] ); if (! $response->successful()) { return response()->json([ 'success' => false, 'error' => '가사 생성에 실패했습니다: '.$response->status(), ], 500); } $data = $response->json(); $text = $data['candidates'][0]['content']['parts'][0]['text'] ?? ''; return response()->json([ 'success' => true, 'lyrics' => trim($text), ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'error' => '가사 생성 중 오류: '.$e->getMessage(), ], 500); } } /** * TTS 음성 생성 (Gemini TTS API) */ public function generateAudio(Request $request): JsonResponse { $request->validate([ 'lyrics' => 'required|string|max:2000', ]); try { $response = Http::timeout(60)->post( "{$this->baseUrl}/models/gemini-2.5-flash-preview-tts:generateContent?key={$this->apiKey}", [ 'contents' => [ ['parts' => [['text' => $request->lyrics]]], ], 'generationConfig' => [ 'responseModalities' => ['AUDIO'], 'speechConfig' => [ 'voiceConfig' => [ 'prebuiltVoiceConfig' => [ 'voiceName' => 'Kore', ], ], ], ], ] ); if (! $response->successful()) { return response()->json([ 'success' => false, 'error' => '음성 생성에 실패했습니다: '.$response->status(), ], 500); } $data = $response->json(); $inlineData = $data['candidates'][0]['content']['parts'][0]['inlineData'] ?? null; if (! $inlineData || empty($inlineData['data'])) { return response()->json([ 'success' => false, 'error' => '음성 데이터를 받지 못했습니다.', ], 500); } return response()->json([ 'success' => true, 'audio_data' => $inlineData['data'], 'mime_type' => $inlineData['mimeType'] ?? 'audio/L16;rate=24000', ]); } catch (\Exception $e) { return response()->json([ 'success' => false, 'error' => '음성 생성 중 오류: '.$e->getMessage(), ], 500); } } }