diff --git a/app/Jobs/TutorialVideoJob.php b/app/Jobs/TutorialVideoJob.php index a70addd3..e6107a15 100644 --- a/app/Jobs/TutorialVideoJob.php +++ b/app/Jobs/TutorialVideoJob.php @@ -241,9 +241,16 @@ public function handle( // === Step 5: 최종 합성 (80%) === $tutorial->updateProgress(TutorialVideo::STATUS_ASSEMBLING, 70, '영상 합성 중...'); - // ASS 자막 생성 + // ASS 자막 생성 (인트로/아웃트로 나레이션은 자막에서 제외) + $subtitleScenes = array_map(function ($scene) { + $sn = (int) ($scene['scene_number'] ?? 0); + if ($sn <= 1 || $sn === 999) { + $scene['narration'] = ''; + } + return $scene; + }, $scenes); $subtitlePath = "{$workDir}/subtitle.ass"; - $videoAssembly->generateAssSubtitle($scenes, $subtitlePath, $narrationDurations, 'landscape'); + $videoAssembly->generateAssSubtitle($subtitleScenes, $subtitlePath, $narrationDurations, 'landscape'); // 최종 MP4 합성 $finalOutputPath = "{$workDir}/final_tutorial.mp4"; diff --git a/app/Services/Video/VideoAssemblyService.php b/app/Services/Video/VideoAssemblyService.php index 644508e7..3530854d 100644 --- a/app/Services/Video/VideoAssemblyService.php +++ b/app/Services/Video/VideoAssemblyService.php @@ -260,11 +260,12 @@ public function generateAssSubtitle(array $scenes, string $outputPath, array $na foreach ($scenes as $scene) { $sceneDuration = $scene['duration'] ?? 8; - $sceneNum = $scene['scene_number'] ?? 0; + $sceneNum = (int) ($scene['scene_number'] ?? 0); $narration = $scene['narration'] ?? ''; - // 인트로/아웃트로 씬은 슬라이드에 텍스트가 포함되어 있으므로 자막 생략 - $isIntroOutro = $sceneNum === 1 || $sceneNum === 999; + // 인트로(1)/아웃트로(999) 씬은 슬라이드에 텍스트가 포함 → 자막 생략 + // 또한 scene_number < 100인 경우도 인트로로 간주 (안전장치) + $isIntroOutro = $sceneNum <= 1 || $sceneNum === 999; if (empty($narration) || $isIntroOutro) { $currentTime += $sceneDuration; @@ -435,8 +436,8 @@ public function assemble( $filterComplex = null; } - // 자막 비디오 필터 - $vf = sprintf("subtitles=%s", escapeshellarg($subtitlePath)); + // 자막 비디오 필터 (ass 필터: ASS 스타일(Alignment 등) 완전 보존) + $vf = sprintf("ass=%s", escapeshellarg($subtitlePath)); // FFmpeg 명령 조립 $cmd = 'ffmpeg -y ' . implode(' ', $inputs);