diff --git a/app/Http/Controllers/Rd/CmSongController.php b/app/Http/Controllers/Rd/CmSongController.php new file mode 100644 index 00000000..ff035123 --- /dev/null +++ b/app/Http/Controllers/Rd/CmSongController.php @@ -0,0 +1,147 @@ +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); + } + } +} diff --git a/resources/views/rd/cm-song/index.blade.php b/resources/views/rd/cm-song/index.blade.php new file mode 100644 index 00000000..889d92d0 --- /dev/null +++ b/resources/views/rd/cm-song/index.blade.php @@ -0,0 +1,348 @@ +@extends('layouts.app') + +@section('title', 'AI CM송 제작') + +@section('content') + +
+

+ + AI CM송 제작 +

+ + R&D 대시보드 + +
+ + +
+ +
+

+ + CM송 정보 입력 +

+ +
+ +
+ + +
+ + +
+ + +
+ + +
+ +
+ + + + +
+
+ + + +
+
+ + +
+

+ + 생성된 CM송 +

+ +
+ +
+ +

정보를 입력하고 버튼을 누르면
이곳에 CM송이 나타납니다.

+
+ + + + + + +
+
+
+@endsection + +@push('scripts') + +@endpush diff --git a/resources/views/rd/index.blade.php b/resources/views/rd/index.blade.php index b177fce4..9bd7a1a2 100644 --- a/resources/views/rd/index.blade.php +++ b/resources/views/rd/index.blade.php @@ -94,6 +94,23 @@ + + +
+
+ +
+
+

AI CM송 제작

+

회사명과 업종을 입력하면 AI가 CM송 가사를 작성하고 목소리를 입혀줍니다.

+
+ Gemini TTS + 음성 생성 +
+
+
+
+
diff --git a/routes/web.php b/routes/web.php index 2a4654ad..79dc67f1 100644 --- a/routes/web.php +++ b/routes/web.php @@ -50,6 +50,7 @@ use App\Http\Controllers\ProfileController; use App\Http\Controllers\ProjectManagementController; use App\Http\Controllers\QuoteFormulaController; +use App\Http\Controllers\Rd\CmSongController; use App\Http\Controllers\RdController; use App\Http\Controllers\RoadmapController; use App\Http\Controllers\RoleController; @@ -379,6 +380,13 @@ Route::get('/ai-quotation/{id}/document', [RdController::class, 'documentQuotation'])->name('ai-quotation.document'); Route::get('/ai-quotation/{id}/edit', [RdController::class, 'editQuotation'])->name('ai-quotation.edit'); Route::get('/ai-quotation/{id}', [RdController::class, 'showQuotation'])->name('ai-quotation.show'); + + // CM송 제작 + Route::prefix('cm-song')->name('cm-song.')->group(function () { + Route::get('/', [CmSongController::class, 'index'])->name('index'); + Route::post('/generate-lyrics', [CmSongController::class, 'generateLyrics'])->name('generate-lyrics'); + Route::post('/generate-audio', [CmSongController::class, 'generateAudio'])->name('generate-audio'); + }); }); // 일일 스크럼 (Blade 화면만)