Spaces:
Running
on
Zero
Running
on
Zero
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 |
+
|