diff --git a/src/main/resources/templates/rework.html b/src/main/resources/templates/rework.html index 3f054f7..daa3e45 100644 --- a/src/main/resources/templates/rework.html +++ b/src/main/resources/templates/rework.html @@ -142,6 +142,9 @@ 원본 다운로드 + + 전사 + 영상 업로드·전사 @@ -527,11 +530,7 @@ } // 2단계: 전사(분리). 실패해도 다운로드(영상)는 유지 → 화면자막 OCR/재시도 가능. try { - const lang = document.getElementById('langSel').value; - const url = API + '/' + VIDEO_ID + '/transcribe-cached' + (lang ? ('?language=' + lang) : ''); - const s = await api(url, { method:'POST' }); - renderSegments(s.segments); - document.getElementById('transcript').value = s.transcript || ''; + const s = await runTranscribeCached(); status.style.color = '#4ade80'; status.textContent = '다운로드+전사 완료 · ' + (s.segments ? s.segments.length : 0) + '개 세그먼트' + (s.language ? (' · ' + s.language) : '') @@ -539,7 +538,39 @@ } catch(e){ status.style.color = '#fbbf24'; status.textContent = '다운로드는 완료 ✓ · 전사 실패(서버 혼잡일 수 있음): ' + e.message - + ' — 잠시 후 다시 전사하거나 ‘화면 자막 OCR’을 쓰세요'; + + ' — ‘전사’ 버튼으로 다시 시도하거나 ‘화면 자막 OCR’을 쓰세요'; + } finally { + btn.disabled = false; btn.style.opacity = ''; btn.innerHTML = orig; + if(window.lucide) lucide.createIcons(); + } + } + + // 받아둔 원본을 Whisper 로 전사(다운로드와 분리). 세그먼트를 렌더하고 응답을 반환. + async function runTranscribeCached(){ + const lang = document.getElementById('langSel').value; + const url = API + '/' + VIDEO_ID + '/transcribe-cached' + (lang ? ('?language=' + lang) : ''); + const s = await api(url, { method:'POST' }); + renderSegments(s.segments); + document.getElementById('transcript').value = s.transcript || ''; + return s; + } + + // '전사' 버튼: 받아둔 원본만 다시 전사(전사만 실패했을 때 재시도용). + async function transcribeCached(){ + const status = document.getElementById('transcribeStatus'); + const btn = document.getElementById('transcribeCachedBtn'); + const orig = btn.innerHTML; btn.disabled = true; btn.style.opacity = '0.6'; btn.innerHTML = '전사 중…'; + status.style.display = 'block'; status.style.color = '#facc15'; + status.textContent = '전사 중… (Shorts 기준 보통 20~60초, 서버 혼잡 시 더 걸림)'; + try { + const s = await runTranscribeCached(); + status.style.color = '#4ade80'; + status.textContent = '전사 완료 · ' + (s.segments ? s.segments.length : 0) + '개 세그먼트' + + (s.language ? (' · ' + s.language) : '') + + (s.duration ? (' · ' + mmss(s.duration)) : ''); + } catch(e){ + status.style.color = '#f87171'; + status.textContent = '전사 실패: ' + e.message; } finally { btn.disabled = false; btn.style.opacity = ''; btn.innerHTML = orig; if(window.lucide) lucide.createIcons(); @@ -549,11 +580,16 @@ // 서버 캐시 보유 상태 → '받은 원본 삭제' 버튼 표시 + 렌더 캐시 사용 여부(HAS_SERVER_FILE) 갱신 function updateCacheUI(cached, sizeBytes){ HAS_SERVER_FILE = !!cached; - const btn = document.getElementById('deleteDlBtn'); - if(btn){ - btn.style.display = cached ? '' : 'none'; + // 받아진 상태면 '원본 다운로드' 숨기고 '전사'·'받은 원본 삭제' 노출(없으면 반대) + const dl = document.getElementById('downloadBtn'); + const tr = document.getElementById('transcribeCachedBtn'); + const del = document.getElementById('deleteDlBtn'); + if(dl) dl.style.display = cached ? 'none' : ''; + if(tr) tr.style.display = cached ? '' : 'none'; + if(del){ + del.style.display = cached ? '' : 'none'; if(cached && sizeBytes){ - btn.title = '서버에 받아둔 원본(' + (sizeBytes/1048576).toFixed(1) + 'MB) 삭제(자막은 유지)'; + del.title = '서버에 받아둔 원본(' + (sizeBytes/1048576).toFixed(1) + 'MB) 삭제(자막은 유지)'; } } // 업로드본이 없을 때만 플레이어를 서버 원본/YouTube로 전환(업로드본이 우선)