Skip to content

Commit a548a0a

Browse files
committed
[fix] exaone dockerfile 개선
1 parent 18642bd commit a548a0a

File tree

4 files changed

+326
-156
lines changed

4 files changed

+326
-156
lines changed

scenario/exaone/index.html

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
padding: 40px 20px;
1919
}
2020

21-
/* 헤더 */
2221
.header {
2322
max-width: 1400px;
2423
margin: 0 auto 40px;
@@ -46,7 +45,6 @@
4645
font-weight: 400;
4746
}
4847

49-
/* 단계 표시 */
5048
.steps {
5149
display: flex;
5250
gap: 20px;
@@ -93,7 +91,6 @@
9391
font-weight: 400;
9492
}
9593

96-
/* 메인 레이아웃 */
9794
.main-container {
9895
max-width: 1400px;
9996
margin: 0 auto;
@@ -117,7 +114,6 @@
117114
margin-bottom: 30px;
118115
}
119116

120-
/* 폼 스타일 */
121117
.form-group {
122118
margin-bottom: 30px;
123119
}
@@ -174,7 +170,6 @@
174170
line-height: 1.5;
175171
}
176172

177-
/* 버튼 */
178173
.generate-btn {
179174
width: 100%;
180175
padding: 16px;
@@ -205,7 +200,6 @@
205200
transform: none;
206201
}
207202

208-
/* 결과 영역 */
209203
.output-card {
210204
min-height: 400px;
211205
display: flex;
@@ -229,7 +223,6 @@
229223
font-style: italic;
230224
}
231225

232-
/* 로딩 */
233226
.loading {
234227
display: flex;
235228
flex-direction: column;
@@ -262,7 +255,6 @@
262255
font-size: 1em;
263256
}
264257

265-
/* 반응형 */
266258
@media (max-width: 1024px) {
267259
.main-container {
268260
grid-template-columns: 1fr;
@@ -277,7 +269,6 @@
277269
</style>
278270
</head>
279271
<body>
280-
<!-- 헤더 -->
281272
<div class="header">
282273
<div class="logo">
283274
<h1>GIGI</h1>
@@ -294,9 +285,7 @@ <h1>GIGI</h1>
294285
브랜드를 선택하고 영상 시나리오를 생성하세요
295286
</div>
296287

297-
<!-- 메인 컨테이너 -->
298288
<div class="main-container">
299-
<!-- 왼쪽: 입력 폼 -->
300289
<div class="card">
301290
<h2 class="card-title">브랜드 선택</h2>
302291

@@ -329,7 +318,6 @@ <h2 class="card-title">브랜드 선택</h2>
329318
</button>
330319
</div>
331320

332-
<!-- 오른쪽: 결과 -->
333321
<div class="card output-card">
334322
<h2 class="card-title">생성된 시나리오</h2>
335323

@@ -345,7 +333,6 @@ <h2 class="card-title">생성된 시나리오</h2>
345333
</div>
346334

347335
<script>
348-
// 페이지 로드 시 브랜드 목록 가져오기
349336
async function loadBrands() {
350337
try {
351338
const response = await fetch('/brands');
@@ -363,18 +350,15 @@ <h2 class="card-title">생성된 시나리오</h2>
363350
}
364351
}
365352

366-
// 시나리오 생성
367353
async function generateScenario() {
368354
const brand = document.getElementById('brand').value;
369355
const userQuery = document.getElementById('user-query').value;
370356

371-
// 유효성 검사
372357
if (!brand) {
373358
alert('브랜드를 선택해주세요.');
374359
return;
375360
}
376361

377-
// UI 업데이트
378362
const generateBtn = document.getElementById('generate-btn');
379363
const loading = document.getElementById('loading');
380364
const outputContent = document.getElementById('output-content');
@@ -402,15 +386,12 @@ <h2 class="card-title">생성된 시나리오</h2>
402386

403387
const data = await response.json();
404388

405-
// 결과 표시
406389
outputContent.textContent = data.scenario;
407390
outputContent.classList.remove('empty');
408391

409-
// 시나리오와 브랜드를 localStorage에 저장
410392
localStorage.setItem('scenario', data.scenario);
411393
localStorage.setItem('brand', brand);
412394

413-
// 다음 버튼 표시
414395
document.getElementById('next-btn').style.display = 'block';
415396

416397
} catch (error) {
@@ -424,12 +405,10 @@ <h2 class="card-title">생성된 시나리오</h2>
424405
}
425406
}
426407

427-
// 페이지 2로 이동
428408
function goToPage2() {
429409
window.location.href = '/page2';
430410
}
431411

432-
// 페이지 로드 시 브랜드 목록 로드
433412
loadBrands();
434413
</script>
435414
</body>

scenario/exaone/page2.html

Lines changed: 1 addition & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,6 @@
225225
font-size: 1em;
226226
}
227227

228-
.timeline {
229-
margin-top: 30px;
230-
}
231-
232228
.timeline-item {
233229
background: #f8f9fa;
234230
border-radius: 12px;
@@ -372,7 +368,6 @@ <h2 class="card-title">타임테이블 결과</h2>
372368
</div>
373369

374370
<script>
375-
// 페이지 로드 시 시나리오 불러오기
376371
window.onload = function() {
377372
const scenario = localStorage.getItem('scenario');
378373
const brand = localStorage.getItem('brand');
@@ -386,7 +381,6 @@ <h2 class="card-title">타임테이블 결과</h2>
386381
document.getElementById('scenario-display').textContent = scenario;
387382
};
388383

389-
// 타임테이블 생성 (스트리밍 방식)
390384
async function generateTimetable() {
391385
const scenario = localStorage.getItem('scenario');
392386
const brand = localStorage.getItem('brand') || '';
@@ -397,7 +391,6 @@ <h2 class="card-title">타임테이블 결과</h2>
397391
return;
398392
}
399393

400-
// UI 업데이트
401394
const generateBtn = document.getElementById('generate-btn');
402395
const resultCard = document.getElementById('result-card');
403396
const loading = document.getElementById('loading');
@@ -408,12 +401,10 @@ <h2 class="card-title">타임테이블 결과</h2>
408401
loading.classList.remove('hidden');
409402
timelineContent.innerHTML = '';
410403

411-
// 스트리밍 데이터 저장
412404
let streamData = {
413405
total_duration: videoDuration,
414406
scene_count: 0,
415-
timetable: [],
416-
image_paths: []
407+
timetable: []
417408
};
418409

419410
try {
@@ -445,33 +436,27 @@ <h2 class="card-title">타임테이블 결과</h2>
445436
buffer += decoder.decode(value, { stream: true });
446437
const lines = buffer.split('\n\n');
447438

448-
// 마지막 불완전한 줄은 버퍼에 보관
449439
buffer = lines.pop() || '';
450440

451441
for (const line of lines) {
452442
if (line.startsWith('data: ')) {
453443
const eventData = JSON.parse(line.slice(6));
454444

455445
if (eventData.type === 'metadata') {
456-
// 메타데이터 수신
457446
streamData.scene_count = eventData.data.scene_count;
458447
loading.querySelector('.loading-text').textContent =
459448
`타임테이블 생성 중... (총 ${eventData.data.scene_count}개 장면)`;
460449

461450
} else if (eventData.type === 'scene') {
462-
// 장면 데이터 수신 - 즉시 화면에 추가
463451
const sceneData = eventData.data;
464452
streamData.timetable.push(sceneData);
465453

466-
// 실시간으로 장면 표시
467454
appendScene(sceneData, sceneData.index);
468455

469-
// 진행상황 업데이트
470456
loading.querySelector('.loading-text').textContent =
471457
`타임테이블 생성 중... (${sceneData.index + 1}/${streamData.scene_count})`;
472458

473459
} else if (eventData.type === 'complete') {
474-
// 완료
475460
console.log('타임테이블 생성 완료!');
476461

477462
} else if (eventData.type === 'error') {
@@ -490,11 +475,9 @@ <h2 class="card-title">타임테이블 결과</h2>
490475
}
491476
}
492477

493-
// 장면을 하나씩 추가하는 함수
494478
function appendScene(item, index) {
495479
const timelineContent = document.getElementById('timeline-content');
496480

497-
// 첫 번째 장면이면 헤더 추가
498481
if (index === 0) {
499482
const headerHtml = `<div style="margin-bottom: 20px; color: #636e72; font-weight: 600;">
500483
장면을 생성하는 중...
@@ -519,17 +502,6 @@ <h3 style="color: #2d3436; font-size: 1.1em;">장면 ${index + 1}</h3>
519502
<div style="color: #856404; font-size: 1.05em; line-height: 1.6;">
520503
"${item.dialogue || '(발화 없음)'}"
521504
</div>
522-
${item.narration ? `
523-
<div style="margin-top: 10px; padding-top: 10px; border-top: 1px solid #ffeaa7;">
524-
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 5px;">
525-
<span style="font-size: 1.1em;">🎙️</span>
526-
<strong style="color: #856404; font-size: 0.9em;">나레이션</strong>
527-
</div>
528-
<div style="color: #856404; font-size: 0.95em; font-style: italic;">
529-
${item.narration}
530-
</div>
531-
</div>
532-
` : ''}
533505
</div>
534506
535507
<div class="prompt-section">
@@ -586,117 +558,12 @@ <h3 style="color: #2d3436; font-size: 1.1em;">장면 ${index + 1}</h3>
586558

587559
timelineContent.insertAdjacentHTML('beforeend', sceneHtml);
588560

589-
// 스크롤을 새로 추가된 장면으로 이동
590561
const newScene = document.getElementById(`scene-${index}`);
591562
if (newScene) {
592563
newScene.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
593564
}
594565
}
595566

596-
// 타임테이블 표시
597-
function displayTimetable(data) {
598-
const timelineContent = document.getElementById('timeline-content');
599-
600-
let html = `<div style="margin-bottom: 20px; color: #636e72;">
601-
${data.scene_count}개 장면 / ${data.total_duration}
602-
</div>`;
603-
604-
data.timetable.forEach((item, index) => {
605-
html += `
606-
<div class="timeline-item">
607-
<div class="timeline-header">
608-
<h3 style="color: #2d3436; font-size: 1.1em;">장면 ${index + 1}</h3>
609-
<div class="timeline-time">${item.time_start}s - ${item.time_end}s</div>
610-
</div>
611-
612-
<div class="scene-desc">${item.scene_description}</div>
613-
614-
<div style="background: #fff3cd; padding: 15px; border-radius: 8px; margin: 15px 0; border-left: 4px solid #ffc107;">
615-
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
616-
<span style="font-size: 1.2em;">💬</span>
617-
<strong style="color: #856404;">지지의 발화</strong>
618-
</div>
619-
<div style="color: #856404; font-size: 1.05em; line-height: 1.6;">
620-
"${item.dialogue || '(발화 없음)'}"
621-
</div>
622-
${item.narration ? `
623-
<div style="margin-top: 10px; padding-top: 10px; border-top: 1px solid #ffeaa7;">
624-
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 5px;">
625-
<span style="font-size: 1.1em;">🎙️</span>
626-
<strong style="color: #856404; font-size: 0.9em;">나레이션</strong>
627-
</div>
628-
<div style="color: #856404; font-size: 0.95em; font-style: italic;">
629-
${item.narration}
630-
</div>
631-
</div>
632-
` : ''}
633-
</div>
634-
635-
${data.image_paths && data.image_paths[index] ? `
636-
<div style="margin: 20px 0;">
637-
<img src="/${data.image_paths[index]}"
638-
alt="Scene ${index + 1}"
639-
style="width: 100%; max-width: 600px; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
640-
</div>
641-
` : ''}
642-
643-
<div class="prompt-section">
644-
<div class="prompt-title">
645-
<span class="prompt-badge">T2I</span>
646-
Text-to-Image Prompt
647-
</div>
648-
<div class="prompt-content">
649-
<div class="prompt-field">
650-
<div class="prompt-field-name">Background:</div>
651-
<div class="prompt-field-value">${item.t2i_prompt.background}</div>
652-
</div>
653-
<div class="prompt-field">
654-
<div class="prompt-field-name">Character Pose & Gaze:</div>
655-
<div class="prompt-field-value">${item.t2i_prompt.character_pose_and_gaze}</div>
656-
</div>
657-
<div class="prompt-field">
658-
<div class="prompt-field-name">Product:</div>
659-
<div class="prompt-field-value">${item.t2i_prompt.product}</div>
660-
</div>
661-
<div class="prompt-field">
662-
<div class="prompt-field-name">Camera Angle:</div>
663-
<div class="prompt-field-value">${item.t2i_prompt.camera_angle}</div>
664-
</div>
665-
</div>
666-
</div>
667-
668-
<div class="prompt-section" style="margin-top: 15px;">
669-
<div class="prompt-title">
670-
<span class="prompt-badge" style="background: #fd79a8;">Edit</span>
671-
Image Edit Prompt
672-
</div>
673-
<div class="prompt-content">
674-
<div class="prompt-field">
675-
<div class="prompt-field-name">Pose Change:</div>
676-
<div class="prompt-field-value">${item.image_edit_prompt.pose_change}</div>
677-
</div>
678-
<div class="prompt-field">
679-
<div class="prompt-field-name">Gaze Change:</div>
680-
<div class="prompt-field-value">${item.image_edit_prompt.gaze_change}</div>
681-
</div>
682-
<div class="prompt-field">
683-
<div class="prompt-field-name">Expression:</div>
684-
<div class="prompt-field-value">${item.image_edit_prompt.expression}</div>
685-
</div>
686-
<div class="prompt-field">
687-
<div class="prompt-field-name">Additional Edits:</div>
688-
<div class="prompt-field-value">${item.image_edit_prompt.additional_edits}</div>
689-
</div>
690-
</div>
691-
</div>
692-
</div>
693-
`;
694-
});
695-
696-
timelineContent.innerHTML = html;
697-
}
698-
699-
// 이전 페이지로
700567
function goBack() {
701568
window.location.href = '/';
702569
}

0 commit comments

Comments
 (0)