Spaces:
Sleeping
Sleeping
Update static/script.js
Browse files- static/script.js +44 -13
static/script.js
CHANGED
|
@@ -9,6 +9,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 9 |
|
| 10 |
let speakerData = {};
|
| 11 |
|
|
|
|
|
|
|
|
|
|
| 12 |
// UI要素
|
| 13 |
const hamburger = document.querySelector('.hamburger');
|
| 14 |
const nav = document.querySelector('.nav');
|
|
@@ -69,8 +72,32 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 69 |
updateSpeakerColorUI();
|
| 70 |
});
|
| 71 |
|
|
|
|
| 72 |
socket.on('new_subtitle', (data) => {
|
| 73 |
if (!data || !subtitleContainer) return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
if (!speakerData[data.speaker_id]) {
|
| 76 |
socket.emit('request_speaker_profiles');
|
|
@@ -80,7 +107,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 80 |
const displayName = info.name;
|
| 81 |
const displayColor = info.color;
|
| 82 |
|
| 83 |
-
// 輝度判定
|
| 84 |
let logNameColor = displayColor;
|
| 85 |
const isDarkMode = document.body.classList.contains('dark-mode');
|
| 86 |
|
|
@@ -100,16 +127,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 100 |
const lum = getLuminance(logNameColor);
|
| 101 |
|
| 102 |
if (isDarkMode) {
|
| 103 |
-
if (lum < 60)
|
| 104 |
-
logNameColor = '#FFFFFF';
|
| 105 |
-
}
|
| 106 |
} else {
|
| 107 |
-
if (lum > 190)
|
| 108 |
-
logNameColor = '#000000';
|
| 109 |
-
}
|
| 110 |
}
|
| 111 |
|
| 112 |
-
// 履歴
|
| 113 |
if (historyList) {
|
| 114 |
const li = document.createElement('li');
|
| 115 |
li.innerHTML = `<span style="font-weight:bold; color:${logNameColor}">${displayName}:</span> ${data.translated}`;
|
|
@@ -117,7 +140,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 117 |
if (historyList.children.length > 30) historyList.removeChild(historyList.lastChild);
|
| 118 |
}
|
| 119 |
|
| 120 |
-
// 字幕
|
| 121 |
const p = document.createElement('p');
|
| 122 |
p.className = 'subtitle-line';
|
| 123 |
p.style.fontSize = currentFontSize;
|
|
@@ -127,13 +150,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 127 |
applySubtitleBackground(p);
|
| 128 |
subtitleContainer.appendChild(p);
|
| 129 |
|
|
|
|
| 130 |
while (subtitleContainer.children.length > 6) {
|
| 131 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
}
|
| 133 |
|
| 134 |
setTimeout(() => p.style.opacity = '0', 3500);
|
| 135 |
setTimeout(() => p.remove(), 4000);
|
| 136 |
});
|
|
|
|
| 137 |
|
| 138 |
socket.on("speaker_name_changed", data => {
|
| 139 |
const { id, new_name } = data;
|
|
@@ -332,13 +364,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 332 |
});
|
| 333 |
}
|
| 334 |
|
| 335 |
-
// ▼▼▼ シアターモード切替ロジック (修正) ▼▼▼
|
| 336 |
if (document.getElementById('video-container')) {
|
| 337 |
const container = document.getElementById('video-container');
|
| 338 |
|
| 339 |
if (theaterBtn) {
|
| 340 |
theaterBtn.addEventListener('click', () => {
|
| 341 |
-
document.body.classList.add('theater-active');
|
| 342 |
container.classList.add('theater-mode');
|
| 343 |
container.classList.remove('normal-mode');
|
| 344 |
});
|
|
@@ -346,7 +377,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 346 |
|
| 347 |
if (closeTheaterBtn) {
|
| 348 |
closeTheaterBtn.addEventListener('click', () => {
|
| 349 |
-
document.body.classList.remove('theater-active');
|
| 350 |
container.classList.remove('theater-mode');
|
| 351 |
container.classList.add('normal-mode');
|
| 352 |
});
|
|
|
|
| 9 |
|
| 10 |
let speakerData = {};
|
| 11 |
|
| 12 |
+
// ▼▼▼ 暫定表示用の要素ID ▼▼▼
|
| 13 |
+
const PREVIEW_ID = 'subtitle-preview-line';
|
| 14 |
+
|
| 15 |
// UI要素
|
| 16 |
const hamburger = document.querySelector('.hamburger');
|
| 17 |
const nav = document.querySelector('.nav');
|
|
|
|
| 72 |
updateSpeakerColorUI();
|
| 73 |
});
|
| 74 |
|
| 75 |
+
// ▼▼▼ 修正: 字幕受信ロジックの大幅変更 ▼▼▼
|
| 76 |
socket.on('new_subtitle', (data) => {
|
| 77 |
if (!data || !subtitleContainer) return;
|
| 78 |
+
|
| 79 |
+
// 1. 暫定結果 (Interim) の場合
|
| 80 |
+
if (!data.is_final) {
|
| 81 |
+
let p = document.getElementById(PREVIEW_ID);
|
| 82 |
+
if (!p) {
|
| 83 |
+
p = document.createElement('p');
|
| 84 |
+
p.id = PREVIEW_ID;
|
| 85 |
+
p.className = 'subtitle-line';
|
| 86 |
+
p.style.fontSize = currentFontSize;
|
| 87 |
+
p.style.color = '#AAAAAA'; // 薄いグレー
|
| 88 |
+
p.style.fontStyle = 'italic'; // 斜体
|
| 89 |
+
subtitleContainer.appendChild(p);
|
| 90 |
+
}
|
| 91 |
+
// 暫定翻訳を表示
|
| 92 |
+
p.textContent = `... ${data.translated}`;
|
| 93 |
+
applySubtitleBackground(p);
|
| 94 |
+
return; // 履歴には追加せず終了
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
// 2. 確定結果 (Final) の場合
|
| 98 |
+
// 暫定表示を消す
|
| 99 |
+
const previewEl = document.getElementById(PREVIEW_ID);
|
| 100 |
+
if (previewEl) previewEl.remove();
|
| 101 |
|
| 102 |
if (!speakerData[data.speaker_id]) {
|
| 103 |
socket.emit('request_speaker_profiles');
|
|
|
|
| 107 |
const displayName = info.name;
|
| 108 |
const displayColor = info.color;
|
| 109 |
|
| 110 |
+
// 輝度判定
|
| 111 |
let logNameColor = displayColor;
|
| 112 |
const isDarkMode = document.body.classList.contains('dark-mode');
|
| 113 |
|
|
|
|
| 127 |
const lum = getLuminance(logNameColor);
|
| 128 |
|
| 129 |
if (isDarkMode) {
|
| 130 |
+
if (lum < 60) logNameColor = '#FFFFFF';
|
|
|
|
|
|
|
| 131 |
} else {
|
| 132 |
+
if (lum > 190) logNameColor = '#000000';
|
|
|
|
|
|
|
| 133 |
}
|
| 134 |
|
| 135 |
+
// 履歴に追加
|
| 136 |
if (historyList) {
|
| 137 |
const li = document.createElement('li');
|
| 138 |
li.innerHTML = `<span style="font-weight:bold; color:${logNameColor}">${displayName}:</span> ${data.translated}`;
|
|
|
|
| 140 |
if (historyList.children.length > 30) historyList.removeChild(historyList.lastChild);
|
| 141 |
}
|
| 142 |
|
| 143 |
+
// 字幕表示
|
| 144 |
const p = document.createElement('p');
|
| 145 |
p.className = 'subtitle-line';
|
| 146 |
p.style.fontSize = currentFontSize;
|
|
|
|
| 150 |
applySubtitleBackground(p);
|
| 151 |
subtitleContainer.appendChild(p);
|
| 152 |
|
| 153 |
+
// 古い字幕を消す
|
| 154 |
while (subtitleContainer.children.length > 6) {
|
| 155 |
+
// プレビュー要素以外を消す
|
| 156 |
+
const first = subtitleContainer.firstChild;
|
| 157 |
+
if (first.id === PREVIEW_ID) {
|
| 158 |
+
if(subtitleContainer.children.length > 1) subtitleContainer.removeChild(subtitleContainer.children[1]);
|
| 159 |
+
else break;
|
| 160 |
+
} else {
|
| 161 |
+
subtitleContainer.removeChild(first);
|
| 162 |
+
}
|
| 163 |
}
|
| 164 |
|
| 165 |
setTimeout(() => p.style.opacity = '0', 3500);
|
| 166 |
setTimeout(() => p.remove(), 4000);
|
| 167 |
});
|
| 168 |
+
// ▲▲▲ 修正ここまで ▲▲▲
|
| 169 |
|
| 170 |
socket.on("speaker_name_changed", data => {
|
| 171 |
const { id, new_name } = data;
|
|
|
|
| 364 |
});
|
| 365 |
}
|
| 366 |
|
|
|
|
| 367 |
if (document.getElementById('video-container')) {
|
| 368 |
const container = document.getElementById('video-container');
|
| 369 |
|
| 370 |
if (theaterBtn) {
|
| 371 |
theaterBtn.addEventListener('click', () => {
|
| 372 |
+
document.body.classList.add('theater-active');
|
| 373 |
container.classList.add('theater-mode');
|
| 374 |
container.classList.remove('normal-mode');
|
| 375 |
});
|
|
|
|
| 377 |
|
| 378 |
if (closeTheaterBtn) {
|
| 379 |
closeTheaterBtn.addEventListener('click', () => {
|
| 380 |
+
document.body.classList.remove('theater-active');
|
| 381 |
container.classList.remove('theater-mode');
|
| 382 |
container.classList.add('normal-mode');
|
| 383 |
});
|