UltronBasecamp commited on
Commit
a7cb8f5
·
verified ·
1 Parent(s): 4cbacf7

영상 스타일과 음악 스타일을 좀 더 세분화 해줘 - Follow Up Deployment

Browse files
Files changed (1) hide show
  1. index.html +106 -20
index.html CHANGED
@@ -6,6 +6,10 @@
6
  <title>Veo3 영상 제작 스튜디오</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
 
 
 
 
9
  <style>
10
  @keyframes float {
11
  0%, 100% { transform: translateY(0px); }
@@ -94,12 +98,23 @@
94
  </div>
95
 
96
  <div>
97
- <label class="block text-sm font-medium mb-2">스타일 선택</label>
98
  <select class="w-full px-3 py-2 bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
99
- <option>영화적</option>
100
  <option>다큐멘터리</option>
101
- <option>광고</option>
102
- <option>교육</option>
 
 
 
 
 
 
 
 
 
 
 
103
  </select>
104
  </div>
105
 
@@ -141,10 +156,25 @@
141
  <label class="block text-sm font-medium mb-2">음악 스타일</label>
142
  <select class="w-full px-3 py-2 bg-gray-800 rounded-lg">
143
  <option>에픽 오케스트라</option>
144
- <option>일렉트로닉</option>
145
- <option>재즈</option>
146
- <option>팝</option>
147
- <option>힙합</option>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  </select>
149
  </div>
150
 
@@ -238,25 +268,81 @@
238
  // Lucide 아이콘 초기화
239
  lucide.createIcons();
240
 
241
- // 진행률 시뮬레이션
242
  let progress = 0;
243
  const progressBar = document.getElementById('progressBar');
244
  const progressText = document.getElementById('progressText');
245
-
246
- function simulateProgress() {
247
- const interval = setInterval(() => {
248
- progress += Math.random() * 10;
249
- if (progress >= 100) {
250
- progress = 100;
251
- clearInterval(interval);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  setTimeout(() => {
253
  document.getElementById('modal').classList.remove('hidden');
254
  document.getElementById('modal').classList.add('flex');
255
  }, 500);
256
  }
257
- progressBar.style.width = progress + '%';
258
- progressText.textContent = Math.floor(progress) + '%';
259
- }, 500);
 
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
 
262
  // 드래그 앤 드롭
@@ -281,7 +367,7 @@
281
  });
282
 
283
  // AI 생성 버튼 클릭
284
- document.querySelector('button').addEventListener('click', simulateProgress);
285
 
286
  // 모달 닫기
287
  function closeModal() {
 
6
  <title>Veo3 영상 제작 스튜디오</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
9
+ <script src="https://apis.google.com/js/api.js"></script>
10
+ <script>
11
+ window.GOOGLE_API_KEY = "AIzaSyBt2gdFwXehWeYlcNetW89f5JHnQVXuhwI";
12
+ </script>
13
  <style>
14
  @keyframes float {
15
  0%, 100% { transform: translateY(0px); }
 
98
  </div>
99
 
100
  <div>
101
+ <label class="block text-sm font-medium mb-2">영상 스타일</label>
102
  <select class="w-full px-3 py-2 bg-gray-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500">
103
+ <option>영화적(시네마틱)</option>
104
  <option>다큐멘터리</option>
105
+ <option>광고(광고홍보)</option>
106
+ <option>교육(강의형)</option>
107
+ <option>브이로그</option>
108
+ <option>리뷰/언박싱</option>
109
+ <option>게임 스트리밍</option>
110
+ <option>셀프 인터뷰</option>
111
+ <option>모션그래픽</option>
112
+ <option>3D 애니메이션</option>
113
+ <option>2D 카툰/일러스트</option>
114
+ <option>브랜드 필름</option>
115
+ <option>프로모션 뮤직비디오</option>
116
+ <option>스톱모션</option>
117
+ <option>타임랩스/하이퍼랩스</option>
118
  </select>
119
  </div>
120
 
 
156
  <label class="block text-sm font-medium mb-2">음악 스타일</label>
157
  <select class="w-full px-3 py-2 bg-gray-800 rounded-lg">
158
  <option>에픽 오케스트라</option>
159
+ <option>시네마틱 트레일러</option>
160
+ <option>로파이 힙합</option>
161
+ <option>퓨처 베이스</option>
162
+ <option>하우스/테크노</option>
163
+ <option>드럼앤베이스</option>
164
+ <option>트랩/EDM</option>
165
+ <option>재즈 피아노</option>
166
+ <option>어쿠스틱 팝</option>
167
+ <option>인디록</option>
168
+ <option>발라드(감성)</option>
169
+ <option>국악 크로스오버</option>
170
+ <option>어린이 동요</option>
171
+ <option>성악/클래식</option>
172
+ <option>카페 재즈</option>
173
+ <option>레트로 신스웨이브</option>
174
+ <option>8비트 게임음악</option>
175
+ <option>뉴에이지 명상</option>
176
+ <option>펑크/소울</option>
177
+ <option>월드뮤직(아프리카/라틴)</option>
178
  </select>
179
  </div>
180
 
 
268
  // Lucide 아이콘 초기화
269
  lucide.createIcons();
270
 
271
+ // 실제 진행률
272
  let progress = 0;
273
  const progressBar = document.getElementById('progressBar');
274
  const progressText = document.getElementById('progressText');
275
+
276
+ // Veo API로 실제 영상 생성
277
+ async function generateVideo(prompt) {
278
+ const requestBody = {
279
+ instances: [{
280
+ prompt: prompt
281
+ }],
282
+ parameters: {
283
+ aspectRatio: "16:9",
284
+ durationSeconds: 8
285
+ }
286
+ };
287
+
288
+ const res = await fetch(
289
+ `https://generativelanguage.googleapis.com/v1beta/videos:generate?key=${API_KEY}`,
290
+ {
291
+ method: "POST",
292
+ headers: { "Content-Type": "application/json" },
293
+ body: JSON.stringify(requestBody)
294
+ }
295
+ );
296
+ const data = await res.json();
297
+ return data.name; // operation name
298
+ }
299
+
300
+ async function getOperationStatus(name) {
301
+ const res = await fetch(
302
+ `https://generativelanguage.googleapis.com/v1beta/${name}?key=${API_KEY}`
303
+ );
304
+ return await res.json();
305
+ }
306
+
307
+ async function pollUntilDone(name) {
308
+ progress = 0;
309
+ const check = setInterval(async () => {
310
+ const op = await getOperationStatus(name);
311
+ const state = op.done ? 100 : Math.min(op.metadata?.video?.videoProgressPercent || progress + 5, 95);
312
+ progress = state;
313
+ progressBar.style.width = progress + '%';
314
+ progressText.textContent = Math.floor(progress) + '%';
315
+
316
+ if (op.done) {
317
+ clearInterval(check);
318
+ progressBar.style.width = '100%';
319
+ progressText.textContent = '100%';
320
+
321
+ const videoUri = op.response?.video?.videoUri;
322
+ if (videoUri) {
323
+ document.querySelector('.aspect-video').innerHTML =
324
+ `<video class="w-full h-full rounded-lg" controls src="${videoUri}"></video>`;
325
+ }
326
  setTimeout(() => {
327
  document.getElementById('modal').classList.remove('hidden');
328
  document.getElementById('modal').classList.add('flex');
329
  }, 500);
330
  }
331
+ }, 2000);
332
+ }
333
+
334
+ async function handleGenerate() {
335
+ const prompt = document.querySelector('textarea').value.trim();
336
+ if (!prompt) {
337
+ alert('프롬프트를 입력하세요!');
338
+ return;
339
+ }
340
+ try {
341
+ const operationName = await generateVideo(prompt);
342
+ await pollUntilDone(operationName);
343
+ } catch (e) {
344
+ alert('영상 생성 실패: ' + e.message);
345
+ }
346
  }
347
 
348
  // 드래그 앤 드롭
 
367
  });
368
 
369
  // AI 생성 버튼 클릭
370
+ document.querySelector('button').addEventListener('click', handleGenerate);
371
 
372
  // 모달 닫기
373
  function closeModal() {