Update app.py
Browse files
app.py
CHANGED
|
@@ -1032,10 +1032,6 @@ if IN_HF_SPACE and 'spaces' in globals():
|
|
| 1032 |
|
| 1033 |
process = process_with_gpu
|
| 1034 |
else:
|
| 1035 |
-
|
| 1036 |
-
|
| 1037 |
-
|
| 1038 |
-
|
| 1039 |
def process(input_image, prompt, n_prompt, seed, total_second_length, use_teacache):
|
| 1040 |
global stream
|
| 1041 |
assert input_image is not None, '入力画像がありません!'
|
|
@@ -1047,8 +1043,6 @@ else:
|
|
| 1047 |
rs = 0.0
|
| 1048 |
gpu_memory_preservation = 6
|
| 1049 |
|
| 1050 |
-
|
| 1051 |
-
|
| 1052 |
# UI状態の初期化
|
| 1053 |
yield None, None, '', '', gr.update(interactive=False), gr.update(interactive=True)
|
| 1054 |
|
|
@@ -1169,19 +1163,16 @@ def make_custom_css():
|
|
| 1169 |
margin: 0 auto;
|
| 1170 |
}
|
| 1171 |
|
| 1172 |
-
/* 言語切り替えボタンのスタイル */
|
| 1173 |
-
|
| 1174 |
-
|
| 1175 |
-
|
| 1176 |
-
|
| 1177 |
-
|
| 1178 |
-
|
| 1179 |
-
|
| 1180 |
-
|
| 1181 |
-
|
| 1182 |
-
padding: 5px 10px;
|
| 1183 |
-
cursor: pointer;
|
| 1184 |
-
font-size: 14px;
|
| 1185 |
}
|
| 1186 |
|
| 1187 |
/* ページタイトルのスタイル */
|
|
@@ -1328,22 +1319,36 @@ with block:
|
|
| 1328 |
# 言語切り替え機能を追加
|
| 1329 |
gr.HTML("""
|
| 1330 |
<div id="app-container">
|
| 1331 |
-
<
|
| 1332 |
-
|
| 1333 |
-
|
| 1334 |
-
|
| 1335 |
-
|
| 1336 |
-
|
| 1337 |
-
|
| 1338 |
-
|
| 1339 |
-
|
| 1340 |
-
|
| 1341 |
-
|
| 1342 |
-
|
| 1343 |
-
|
| 1344 |
-
|
| 1345 |
-
|
| 1346 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1347 |
const translations = {
|
| 1348 |
"en": {
|
| 1349 |
"title": "FramePack_rotate_landscape - Rotating Landscape Video Generator",
|
|
@@ -1356,8 +1361,10 @@ with block:
|
|
| 1356 |
"teacache_info": "Faster speed, but may result in slightly worse finger and hand generation.",
|
| 1357 |
"negative_prompt": "Negative Prompt",
|
| 1358 |
"seed": "Seed",
|
|
|
|
| 1359 |
"next_latents": "Next Latents",
|
| 1360 |
"generated_video": "Generated Video",
|
|
|
|
| 1361 |
"sampling_note": "Note: Due to reversed sampling, ending actions will be generated before starting actions. If the starting action is not in the video, please wait, it will be generated later.",
|
| 1362 |
"error_message": "Error",
|
| 1363 |
"processing_error": "Processing error",
|
|
@@ -1378,9 +1385,10 @@ with block:
|
|
| 1378 |
"teacache_info": "処理速度が速くなりますが、指や手の生成品質が若干低下する可能性があります。",
|
| 1379 |
"negative_prompt": "ネガティブプロンプト",
|
| 1380 |
"seed": "シード値",
|
| 1381 |
-
"video_length": "動画の長さ(最大
|
| 1382 |
"next_latents": "次の潜在変数",
|
| 1383 |
"generated_video": "生成された動画",
|
|
|
|
| 1384 |
"sampling_note": "注意:逆順サンプリングのため、終了動作が開始動作より先に生成されます。開始動作が動画に表示されていない場合は、しばらくお待ちください。後で生成されます。",
|
| 1385 |
"error_message": "エラーメッセージ",
|
| 1386 |
"processing_error": "処理中にエラーが発生しました",
|
|
@@ -1392,67 +1400,202 @@ with block:
|
|
| 1392 |
}
|
| 1393 |
};
|
| 1394 |
|
| 1395 |
-
|
| 1396 |
-
|
| 1397 |
-
|
| 1398 |
-
|
| 1399 |
-
|
| 1400 |
-
|
| 1401 |
-
|
| 1402 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1403 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1404 |
}
|
| 1405 |
-
});
|
| 1406 |
-
|
| 1407 |
-
// ページ上の他の要素を更新
|
| 1408 |
-
document.querySelectorAll('.bilingual-label').forEach(el => {
|
| 1409 |
-
const enText = el.getAttribute('data-en');
|
| 1410 |
-
const jaText = el.getAttribute('data-ja');
|
| 1411 |
-
el.textContent = window.currentLang === 'en' ? enText : jaText;
|
| 1412 |
-
});
|
| 1413 |
-
|
| 1414 |
-
// エラーメッセージコンテナの処理
|
| 1415 |
-
document.querySelectorAll('[data-lang]').forEach(el => {
|
| 1416 |
-
el.style.display = el.getAttribute('data-lang') === window.currentLang ? 'block' : 'none';
|
| 1417 |
-
});
|
| 1418 |
-
}
|
| 1419 |
-
|
| 1420 |
-
// ページロード後の初期化
|
| 1421 |
-
document.addEventListener('DOMContentLoaded', function() {
|
| 1422 |
-
// 国際化が必要な要素にdata-i18n属性を追加
|
| 1423 |
-
setTimeout(() => {
|
| 1424 |
-
// すべてのラベルにi18n属性を追加
|
| 1425 |
-
const labelMap = {
|
| 1426 |
-
"Upload Image": "upload_image",
|
| 1427 |
-
"画像をアップロード": "upload_image",
|
| 1428 |
-
"Prompt": "prompt",
|
| 1429 |
-
"プロンプト": "prompt",
|
| 1430 |
-
"Quick Prompts": "quick_prompts",
|
| 1431 |
-
"クイックプロンプト一覧": "quick_prompts",
|
| 1432 |
-
"Generate": "start_generation",
|
| 1433 |
-
"生成開始": "start_generation",
|
| 1434 |
-
"Stop": "stop_generation",
|
| 1435 |
-
"停止": "stop_generation",
|
| 1436 |
-
// 他のラベルマッピングを追加...
|
| 1437 |
-
};
|
| 1438 |
|
| 1439 |
-
//
|
| 1440 |
-
|
| 1441 |
-
|
| 1442 |
-
|
| 1443 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1444 |
}
|
| 1445 |
});
|
| 1446 |
|
| 1447 |
-
//
|
| 1448 |
-
|
| 1449 |
-
|
| 1450 |
-
|
| 1451 |
-
|
| 1452 |
-
|
| 1453 |
-
|
| 1454 |
-
|
| 1455 |
-
</script>
|
| 1456 |
""")
|
| 1457 |
|
| 1458 |
# タイトルにはJavaScriptで切り替えられるようにdata-i18n属性を使用
|
|
@@ -1561,7 +1704,7 @@ with block:
|
|
| 1561 |
error_message = gr.HTML('', elem_id='error-message', visible=True)
|
| 1562 |
|
| 1563 |
# 処理関数
|
| 1564 |
-
ips = [input_image, prompt, n_prompt, seed, total_second_length,use_teacache]
|
| 1565 |
|
| 1566 |
# 開始と終了ボタンのイベント
|
| 1567 |
start_button.click(fn=process, inputs=ips, outputs=[result_video, preview_image, progress_desc, progress_bar, start_button, end_button])
|
|
@@ -1633,4 +1776,4 @@ def create_error_html(error_msg, is_timeout=False):
|
|
| 1633 |
}})();
|
| 1634 |
</script>
|
| 1635 |
"""
|
| 1636 |
-
|
|
|
|
| 1032 |
|
| 1033 |
process = process_with_gpu
|
| 1034 |
else:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1035 |
def process(input_image, prompt, n_prompt, seed, total_second_length, use_teacache):
|
| 1036 |
global stream
|
| 1037 |
assert input_image is not None, '入力画像がありません!'
|
|
|
|
| 1043 |
rs = 0.0
|
| 1044 |
gpu_memory_preservation = 6
|
| 1045 |
|
|
|
|
|
|
|
| 1046 |
# UI状態の初期化
|
| 1047 |
yield None, None, '', '', gr.update(interactive=False), gr.update(interactive=True)
|
| 1048 |
|
|
|
|
| 1163 |
margin: 0 auto;
|
| 1164 |
}
|
| 1165 |
|
| 1166 |
+
/* 言語切り替えボタンのスタイル - CSSは自動生成されるので不要です */
|
| 1167 |
+
|
| 1168 |
+
/* 言語切り替え用のクラス */
|
| 1169 |
+
body.lang-ja .lang-en,
|
| 1170 |
+
body.lang-en .lang-ja {
|
| 1171 |
+
display: none !important;
|
| 1172 |
+
}
|
| 1173 |
+
|
| 1174 |
+
body.lang-initialized .dual-lang-text {
|
| 1175 |
+
display: none !important;
|
|
|
|
|
|
|
|
|
|
| 1176 |
}
|
| 1177 |
|
| 1178 |
/* ページタイトルのスタイル */
|
|
|
|
| 1319 |
# 言語切り替え機能を追加
|
| 1320 |
gr.HTML("""
|
| 1321 |
<div id="app-container">
|
| 1322 |
+
<script>
|
| 1323 |
+
// 言語切り替え機能のJavaScriptコード
|
| 1324 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1325 |
+
console.log('DOM読み込み完了、言語切り替え初期化処理を開始します');
|
| 1326 |
+
|
| 1327 |
+
// グローバル変数、現在の言語を保存(デフォルトは日本語)
|
| 1328 |
+
window.currentLang = "ja";
|
| 1329 |
+
|
| 1330 |
+
// CSSを動的に追加
|
| 1331 |
+
const styleElement = document.createElement('style');
|
| 1332 |
+
styleElement.textContent = `
|
| 1333 |
+
/* 言語切り替え用のスタイル */
|
| 1334 |
+
body.lang-ja .lang-en,
|
| 1335 |
+
body.lang-en .lang-ja {
|
| 1336 |
+
display: none !important;
|
| 1337 |
+
}
|
| 1338 |
+
|
| 1339 |
+
/* スラッシュ付きのデュアル言語表示を非表示 */
|
| 1340 |
+
body.lang-initialized .dual-lang-text {
|
| 1341 |
+
display: none !important;
|
| 1342 |
+
}
|
| 1343 |
+
|
| 1344 |
+
/* 言語固有表示用クラス */
|
| 1345 |
+
.lang-ja, .lang-en {
|
| 1346 |
+
display: block;
|
| 1347 |
+
}
|
| 1348 |
+
`;
|
| 1349 |
+
document.head.appendChild(styleElement);
|
| 1350 |
+
|
| 1351 |
+
// 翻訳データ
|
| 1352 |
const translations = {
|
| 1353 |
"en": {
|
| 1354 |
"title": "FramePack_rotate_landscape - Rotating Landscape Video Generator",
|
|
|
|
| 1361 |
"teacache_info": "Faster speed, but may result in slightly worse finger and hand generation.",
|
| 1362 |
"negative_prompt": "Negative Prompt",
|
| 1363 |
"seed": "Seed",
|
| 1364 |
+
"video_length": "Video Length (max 1 seconds)",
|
| 1365 |
"next_latents": "Next Latents",
|
| 1366 |
"generated_video": "Generated Video",
|
| 1367 |
+
"preview": "Preview",
|
| 1368 |
"sampling_note": "Note: Due to reversed sampling, ending actions will be generated before starting actions. If the starting action is not in the video, please wait, it will be generated later.",
|
| 1369 |
"error_message": "Error",
|
| 1370 |
"processing_error": "Processing error",
|
|
|
|
| 1385 |
"teacache_info": "処理速度が速くなりますが、指や手の生成品質が若干低下する可能性があります。",
|
| 1386 |
"negative_prompt": "ネガティブプロンプト",
|
| 1387 |
"seed": "シード値",
|
| 1388 |
+
"video_length": "動画の長さ(最大1秒)",
|
| 1389 |
"next_latents": "次の潜在変数",
|
| 1390 |
"generated_video": "生成された動画",
|
| 1391 |
+
"preview": "プレビュー",
|
| 1392 |
"sampling_note": "注意:逆順サンプリングのため、終了動作が開始動作より先に生成されます。開始動作が動画に表示されていない場合は、しばらくお待ちください。後で生成されます。",
|
| 1393 |
"error_message": "エラーメッセージ",
|
| 1394 |
"processing_error": "処理中にエラーが発生しました",
|
|
|
|
| 1400 |
}
|
| 1401 |
};
|
| 1402 |
|
| 1403 |
+
// 言語切り替えボタンを作成
|
| 1404 |
+
const langToggleBtn = document.createElement('button');
|
| 1405 |
+
langToggleBtn.id = 'language-toggle';
|
| 1406 |
+
langToggleBtn.textContent = 'English / 英語';
|
| 1407 |
+
langToggleBtn.onclick = toggleLanguage;
|
| 1408 |
+
langToggleBtn.style.position = 'fixed';
|
| 1409 |
+
langToggleBtn.style.top = '10px';
|
| 1410 |
+
langToggleBtn.style.right = '10px';
|
| 1411 |
+
langToggleBtn.style.zIndex = '1000';
|
| 1412 |
+
langToggleBtn.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
|
| 1413 |
+
langToggleBtn.style.color = 'white';
|
| 1414 |
+
langToggleBtn.style.border = 'none';
|
| 1415 |
+
langToggleBtn.style.borderRadius = '4px';
|
| 1416 |
+
langToggleBtn.style.padding = '5px 10px';
|
| 1417 |
+
langToggleBtn.style.cursor = 'pointer';
|
| 1418 |
+
langToggleBtn.style.fontSize = '14px';
|
| 1419 |
+
document.body.appendChild(langToggleBtn);
|
| 1420 |
+
|
| 1421 |
+
// 言語切り替え関数
|
| 1422 |
+
window.toggleLanguage = function() {
|
| 1423 |
+
const newLang = window.currentLang === "en" ? "ja" : "en";
|
| 1424 |
+
window.currentLang = newLang;
|
| 1425 |
+
|
| 1426 |
+
// body要素に言語クラスを設定
|
| 1427 |
+
document.body.classList.remove('lang-ja', 'lang-en');
|
| 1428 |
+
document.body.classList.add(`lang-${newLang}`);
|
| 1429 |
+
|
| 1430 |
+
// ボタンのテキストを更新
|
| 1431 |
+
langToggleBtn.textContent = newLang === "en" ? '日本語 / Japanese' : 'English / 英語';
|
| 1432 |
+
|
| 1433 |
+
applyTranslations();
|
| 1434 |
+
console.log(`言語を ${newLang} に切り替えました`);
|
| 1435 |
+
}
|
| 1436 |
+
|
| 1437 |
+
// 翻訳を適用する関数
|
| 1438 |
+
function applyTranslations() {
|
| 1439 |
+
// 通常のラベル要素の処理
|
| 1440 |
+
const allLabels = document.querySelectorAll('label, span.label-wrap span, div.wrap span, h1, .gradio-button, .note');
|
| 1441 |
+
|
| 1442 |
+
allLabels.forEach(label => {
|
| 1443 |
+
const text = label.textContent.trim();
|
| 1444 |
+
|
| 1445 |
+
// スラッシュ付きのテキストなら分割して処理
|
| 1446 |
+
if (text.includes('/')) {
|
| 1447 |
+
// 初回のみ言語ごとの要素を作成する
|
| 1448 |
+
if (!label.classList.contains('processed-dual-lang')) {
|
| 1449 |
+
processSlashSeparatedText(label, text);
|
| 1450 |
+
label.classList.add('processed-dual-lang');
|
| 1451 |
+
label.classList.add('dual-lang-text');
|
| 1452 |
+
}
|
| 1453 |
+
} else {
|
| 1454 |
+
// 単一言語のテキストの場合、キーを検索して翻訳
|
| 1455 |
+
const key = getKeyFromText(text);
|
| 1456 |
+
if (key && translations[window.currentLang][key]) {
|
| 1457 |
+
label.textContent = translations[window.currentLang][key];
|
| 1458 |
+
}
|
| 1459 |
+
}
|
| 1460 |
+
});
|
| 1461 |
+
|
| 1462 |
+
// ボタン要素の特別処理
|
| 1463 |
+
const startBtn = document.querySelector('#start-button');
|
| 1464 |
+
if (startBtn) {
|
| 1465 |
+
startBtn.textContent = translations[window.currentLang].start_generation;
|
| 1466 |
+
}
|
| 1467 |
+
|
| 1468 |
+
const stopBtn = document.querySelector('#stop-button');
|
| 1469 |
+
if (stopBtn) {
|
| 1470 |
+
stopBtn.textContent = translations[window.currentLang].stop_generation;
|
| 1471 |
+
}
|
| 1472 |
+
|
| 1473 |
+
// チェックボックスの情報テキスト
|
| 1474 |
+
const infoTexts = document.querySelectorAll('.wrap p, .checkbox-container .wrap p');
|
| 1475 |
+
infoTexts.forEach(info => {
|
| 1476 |
+
const text = info.textContent.trim();
|
| 1477 |
+
if (text.includes('/')) {
|
| 1478 |
+
if (!info.classList.contains('processed-dual-lang')) {
|
| 1479 |
+
processSlashSeparatedText(info, text);
|
| 1480 |
+
info.classList.add('processed-dual-lang');
|
| 1481 |
+
info.classList.add('dual-lang-text');
|
| 1482 |
+
}
|
| 1483 |
+
} else {
|
| 1484 |
+
// TeaCacheのinfo文字列を特別に検出
|
| 1485 |
+
if (text.includes('指や手の生成品質') || text.includes('finger and hand generation')) {
|
| 1486 |
+
info.textContent = translations[window.currentLang].teacache_info;
|
| 1487 |
+
}
|
| 1488 |
+
}
|
| 1489 |
+
});
|
| 1490 |
+
|
| 1491 |
+
// エラーメッセージ処理
|
| 1492 |
+
document.querySelectorAll('[data-lang]').forEach(el => {
|
| 1493 |
+
el.style.display = el.getAttribute('data-lang') === window.currentLang ? 'block' : 'none';
|
| 1494 |
+
});
|
| 1495 |
+
}
|
| 1496 |
+
|
| 1497 |
+
// スラッシュ区切りテキストを処理して、言語ごとの要素を作成
|
| 1498 |
+
function processSlashSeparatedText(element, text) {
|
| 1499 |
+
// テキストをスラッシュで分割
|
| 1500 |
+
const parts = text.split('/');
|
| 1501 |
+
let jaText = parts[0].trim();
|
| 1502 |
+
let enText = parts.length > 1 ? parts[1].trim() : '';
|
| 1503 |
+
|
| 1504 |
+
// 親要素を取得
|
| 1505 |
+
const parent = element.parentNode;
|
| 1506 |
+
|
| 1507 |
+
// 言語ごとの要素を作成
|
| 1508 |
+
const jaElement = document.createElement('span');
|
| 1509 |
+
jaElement.textContent = jaText;
|
| 1510 |
+
jaElement.classList.add('lang-ja');
|
| 1511 |
+
|
| 1512 |
+
const enElement = document.createElement('span');
|
| 1513 |
+
enElement.textContent = enText;
|
| 1514 |
+
enElement.classList.add('lang-en');
|
| 1515 |
+
|
| 1516 |
+
// オリジナル要素の直後に挿入
|
| 1517 |
+
insertAfter(jaElement, element);
|
| 1518 |
+
insertAfter(enElement, jaElement);
|
| 1519 |
+
}
|
| 1520 |
+
|
| 1521 |
+
// 要素の後に新しい要素を挿入するヘルパー関数
|
| 1522 |
+
function insertAfter(newElement, referenceElement) {
|
| 1523 |
+
referenceElement.parentNode.insertBefore(newElement, referenceElement.nextSibling);
|
| 1524 |
+
}
|
| 1525 |
+
|
| 1526 |
+
// テキストからキーを取得する関数
|
| 1527 |
+
function getKeyFromText(text) {
|
| 1528 |
+
if (!text) return null;
|
| 1529 |
+
|
| 1530 |
+
// 複合テキスト(「日本語 / English」形式)を処理
|
| 1531 |
+
if (text.includes('/')) {
|
| 1532 |
+
const parts = text.split('/');
|
| 1533 |
+
const jaText = parts[0].trim();
|
| 1534 |
+
const enText = parts.length > 1 ? parts[1].trim() : '';
|
| 1535 |
+
|
| 1536 |
+
// 日本語テキストからキーを検索
|
| 1537 |
+
for (const [key, value] of Object.entries(translations.ja)) {
|
| 1538 |
+
if (value === jaText) return key;
|
| 1539 |
+
}
|
| 1540 |
+
|
| 1541 |
+
// 英語テキストからキーを検索
|
| 1542 |
+
for (const [key, value] of Object.entries(translations.en)) {
|
| 1543 |
+
if (value === enText) return key;
|
| 1544 |
+
}
|
| 1545 |
}
|
| 1546 |
+
|
| 1547 |
+
// 単一言語テキストからキーを検索
|
| 1548 |
+
for (const [key, value] of Object.entries(translations.ja)) {
|
| 1549 |
+
if (value === text) return key;
|
| 1550 |
+
}
|
| 1551 |
+
|
| 1552 |
+
for (const [key, value] of Object.entries(translations.en)) {
|
| 1553 |
+
if (value === text) return key;
|
| 1554 |
+
}
|
| 1555 |
+
|
| 1556 |
+
return null;
|
| 1557 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1558 |
|
| 1559 |
+
// Gradioの要素が完全に読み込まれるまで少し待ってから実行
|
| 1560 |
+
function initializeLanguage() {
|
| 1561 |
+
console.log('言語初期化処理を実行します');
|
| 1562 |
+
|
| 1563 |
+
// デフォルト言語を設定
|
| 1564 |
+
document.body.classList.add(`lang-${window.currentLang}`);
|
| 1565 |
+
document.body.classList.add('lang-initialized');
|
| 1566 |
+
|
| 1567 |
+
// 翻訳を適用
|
| 1568 |
+
applyTranslations();
|
| 1569 |
+
}
|
| 1570 |
+
|
| 1571 |
+
// 初期化を3回試行(Gradioの読み込みタイミングに合わせるため)
|
| 1572 |
+
setTimeout(initializeLanguage, 1000);
|
| 1573 |
+
setTimeout(initializeLanguage, 2000);
|
| 1574 |
+
setTimeout(initializeLanguage, 3000);
|
| 1575 |
+
|
| 1576 |
+
// MutationObserverでDOM変更を監視し、新しい要素にも翻訳を適用
|
| 1577 |
+
const observer = new MutationObserver(function(mutations) {
|
| 1578 |
+
let shouldUpdate = false;
|
| 1579 |
+
|
| 1580 |
+
mutations.forEach(function(mutation) {
|
| 1581 |
+
if (mutation.addedNodes.length) {
|
| 1582 |
+
shouldUpdate = true;
|
| 1583 |
+
}
|
| 1584 |
+
});
|
| 1585 |
+
|
| 1586 |
+
if (shouldUpdate) {
|
| 1587 |
+
setTimeout(applyTranslations, 100);
|
| 1588 |
}
|
| 1589 |
});
|
| 1590 |
|
| 1591 |
+
// 監視設定
|
| 1592 |
+
observer.observe(document.body, {
|
| 1593 |
+
childList: true,
|
| 1594 |
+
subtree: true
|
| 1595 |
+
});
|
| 1596 |
+
});
|
| 1597 |
+
</script>
|
| 1598 |
+
</div>
|
|
|
|
| 1599 |
""")
|
| 1600 |
|
| 1601 |
# タイトルにはJavaScriptで切り替えられるようにdata-i18n属性を使用
|
|
|
|
| 1704 |
error_message = gr.HTML('', elem_id='error-message', visible=True)
|
| 1705 |
|
| 1706 |
# 処理関数
|
| 1707 |
+
ips = [input_image, prompt, n_prompt, seed, total_second_length, use_teacache]
|
| 1708 |
|
| 1709 |
# 開始と終了ボタンのイベント
|
| 1710 |
start_button.click(fn=process, inputs=ips, outputs=[result_video, preview_image, progress_desc, progress_bar, start_button, end_button])
|
|
|
|
| 1776 |
}})();
|
| 1777 |
</script>
|
| 1778 |
"""
|
| 1779 |
+
|