['upbeat_01.mp3', 'upbeat_02.mp3'], 'energetic' => ['energetic_01.mp3', 'energetic_02.mp3'], 'exciting' => ['exciting_01.mp3', 'exciting_02.mp3'], 'calm' => ['calm_01.mp3', 'calm_02.mp3'], 'dramatic' => ['dramatic_01.mp3', 'dramatic_02.mp3'], 'happy' => ['happy_01.mp3', 'happy_02.mp3'], 'sad' => ['sad_01.mp3', 'sad_02.mp3'], 'mysterious' => ['mysterious_01.mp3', 'mysterious_02.mp3'], 'inspiring' => ['inspiring_01.mp3', 'inspiring_02.mp3'], ]; /** * 분위기에 맞는 BGM 선택 * * @return string|null BGM 파일 경로 */ public function select(string $mood, string $savePath): ?string { $bgmDir = storage_path('app/bgm'); // 분위기 키워드 매칭 (부분 일치 지원) $matchedFiles = []; $moodLower = strtolower($mood); foreach ($this->moodMap as $key => $files) { if (str_contains($moodLower, $key)) { $matchedFiles = array_merge($matchedFiles, $files); } } // 매칭되는 분위기가 없으면 기본값 if (empty($matchedFiles)) { $matchedFiles = $this->moodMap['upbeat'] ?? ['default.mp3']; } // 랜덤 선택 $selectedFile = $matchedFiles[array_rand($matchedFiles)]; $sourcePath = "{$bgmDir}/{$selectedFile}"; // BGM 파일 존재 확인 if (! file_exists($sourcePath)) { Log::warning('BgmService: BGM 파일 없음', [ 'path' => $sourcePath, 'mood' => $mood, ]); // BGM 디렉토리에서 아무 파일이나 선택 return $this->selectFallback($bgmDir, $savePath); } $dir = dirname($savePath); if (! is_dir($dir)) { mkdir($dir, 0755, true); } copy($sourcePath, $savePath); Log::info('BgmService: BGM 선택 완료', [ 'mood' => $mood, 'file' => $selectedFile, ]); return $savePath; } /** * 폴백: BGM 디렉토리에서 아무 MP3 선택 */ private function selectFallback(string $bgmDir, string $savePath): ?string { if (! is_dir($bgmDir)) { Log::error('BgmService: BGM 디렉토리 없음', ['dir' => $bgmDir]); return null; } $files = glob("{$bgmDir}/*.mp3"); if (empty($files)) { Log::error('BgmService: BGM 파일이 하나도 없음'); return null; } $selected = $files[array_rand($files)]; $dir = dirname($savePath); if (! is_dir($dir)) { mkdir($dir, 0755, true); } copy($selected, $savePath); return $savePath; } /** * 무음 BGM 생성 (FFmpeg 사용, BGM 파일이 없을 때 폴백) */ public function generateSilence(int $durationSec, string $savePath): ?string { $dir = dirname($savePath); if (! is_dir($dir)) { mkdir($dir, 0755, true); } $cmd = sprintf( 'ffmpeg -y -f lavfi -i anullsrc=r=44100:cl=stereo -t %d -c:a libmp3lame -q:a 9 %s 2>&1', $durationSec, escapeshellarg($savePath) ); exec($cmd, $output, $returnCode); if ($returnCode !== 0) { Log::error('BgmService: 무음 BGM 생성 실패', ['output' => implode("\n", $output)]); return null; } return $savePath; } }