feat:생성 이력 상세보기 모달 + YouTube Shorts 텍스트 생성
- Veo3Controller에 show 엔드포인트 추가 (시나리오/프롬프트 상세 데이터 반환) - YouTube Shorts 제목/설명/해시태그 자동 생성 (완료된 영상) - DetailModal 컴포넌트: 탭 UI (시나리오/프롬프트 | YouTube 텍스트) - 이력 테이블 행 클릭 시 상세 모달 표시 - 복사 버튼으로 YouTube 텍스트 클립보드 복사 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -256,6 +256,95 @@ public function preview(int $id): Response|RedirectResponse|JsonResponse
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 생성 이력 상세 (시나리오, 프롬프트, YouTube 텍스트 등)
|
||||
*/
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$video = VideoGeneration::where('user_id', auth()->id())->findOrFail($id);
|
||||
|
||||
$scenario = $video->scenario ?? [];
|
||||
$scenes = $scenario['scenes'] ?? [];
|
||||
|
||||
// YouTube Shorts 텍스트 생성 (완료된 영상만)
|
||||
$youtubeText = null;
|
||||
if ($video->status === VideoGeneration::STATUS_COMPLETED) {
|
||||
$youtubeText = $this->buildYoutubeText($video, $scenario, $scenes);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'id' => $video->id,
|
||||
'keyword' => $video->keyword,
|
||||
'title' => $video->title,
|
||||
'status' => $video->status,
|
||||
'progress' => $video->progress,
|
||||
'current_step' => $video->current_step,
|
||||
'error_message' => $video->error_message,
|
||||
'cost_usd' => $video->cost_usd,
|
||||
'created_at' => $video->created_at?->toIso8601String(),
|
||||
'updated_at' => $video->updated_at?->toIso8601String(),
|
||||
'scenario' => $scenario,
|
||||
'scenes' => array_map(function ($scene) {
|
||||
return [
|
||||
'scene_number' => $scene['scene_number'] ?? null,
|
||||
'scene_type' => $scene['scene_type'] ?? null,
|
||||
'narration' => $scene['narration'] ?? '',
|
||||
'visual_prompt' => $scene['visual_prompt'] ?? '',
|
||||
'duration' => $scene['duration'] ?? 0,
|
||||
'mood' => $scene['mood'] ?? '',
|
||||
];
|
||||
}, $scenes),
|
||||
'clips_data' => $video->clips_data,
|
||||
'youtube_text' => $youtubeText,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* YouTube Shorts 제목 + 설명 텍스트 빌드
|
||||
*/
|
||||
private function buildYoutubeText(VideoGeneration $video, array $scenario, array $scenes): array
|
||||
{
|
||||
$title = $video->title ?? '';
|
||||
$keyword = $video->keyword ?? '';
|
||||
|
||||
// 해시태그 생성
|
||||
$hashtags = ['#shorts', '#쇼츠'];
|
||||
if ($keyword) {
|
||||
$hashtags[] = '#' . str_replace(' ', '', $keyword);
|
||||
}
|
||||
// 시나리오에서 추가 태그 추출
|
||||
$bgmMood = $scenario['bgm_mood'] ?? '';
|
||||
if ($bgmMood) {
|
||||
$hashtags[] = '#' . $bgmMood;
|
||||
}
|
||||
$hashtags = array_merge($hashtags, ['#건강', '#건강정보', '#헬스']);
|
||||
|
||||
// 설명란 텍스트
|
||||
$descLines = [];
|
||||
$descLines[] = $title;
|
||||
$descLines[] = '';
|
||||
|
||||
// 핵심 내용 요약 (나레이션에서 추출)
|
||||
foreach ($scenes as $scene) {
|
||||
$narration = $scene['narration'] ?? '';
|
||||
if ($narration && ($scene['scene_type'] ?? '') !== 'HOOK') {
|
||||
$descLines[] = '- ' . mb_substr($narration, 0, 60);
|
||||
}
|
||||
}
|
||||
|
||||
$descLines[] = '';
|
||||
$descLines[] = implode(' ', array_unique($hashtags));
|
||||
|
||||
return [
|
||||
'title' => $title,
|
||||
'description' => implode("\n", $descLines),
|
||||
'hashtags' => array_unique($hashtags),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 생성 이력 목록
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user