oKen38461 commited on
Commit
55535c7
·
1 Parent(s): 2089ecf

出力ディレクトリの作成とUUIDを用いたファイル名生成を追加しました。また、クリーンアップ機能の初期化と状態確認ボタンをGradioインターフェースに追加しました。これにより、ファイル管理が改善され、ユーザーがクリーンアップ状況を確認できるようになりました。

Browse files
Files changed (4) hide show
  1. app.py +9 -4
  2. app_optimized.py +21 -3
  3. app_streaming.py +9 -2
  4. cleanup_old_files.py +167 -0
app.py CHANGED
@@ -7,6 +7,10 @@ from model_manager import ModelManager
7
 
8
  # サンプルファイルのディレクトリを定義(絶対パスに解決)
9
  EXAMPLES_DIR = (Path(__file__).parent / "example").resolve()
 
 
 
 
10
 
11
  # インポートエラーのデバッグ情報を表示
12
  try:
@@ -60,9 +64,10 @@ def process_talking_head(audio_file, source_image):
60
  return None, "ソース画像をアップロードしてください。"
61
 
62
  try:
63
- # 一時ファイルの作成
64
- with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as tmp_output:
65
- output_path = tmp_output.name
 
66
 
67
  # 処理実行
68
  print(f"処理開始: audio={audio_file}, image={source_image}")
@@ -149,5 +154,5 @@ if __name__ == "__main__":
149
  server_name="0.0.0.0",
150
  server_port=7860,
151
  share=False,
152
- allowed_paths=[str(EXAMPLES_DIR)]
153
  )
 
7
 
8
  # サンプルファイルのディレクトリを定義(絶対パスに解決)
9
  EXAMPLES_DIR = (Path(__file__).parent / "example").resolve()
10
+ OUTPUT_DIR = (Path(__file__).parent / "output").resolve()
11
+
12
+ # 出力ディレクトリの作成
13
+ OUTPUT_DIR.mkdir(exist_ok=True)
14
 
15
  # インポートエラーのデバッグ情報を表示
16
  try:
 
64
  return None, "ソース画像をアップロードしてください。"
65
 
66
  try:
67
+ # 出力ファイルの作成(出力ディレクトリ内)
68
+ import uuid
69
+ output_filename = f"{uuid.uuid4()}.mp4"
70
+ output_path = str(OUTPUT_DIR / output_filename)
71
 
72
  # 処理実行
73
  print(f"処理開始: audio={audio_file}, image={source_image}")
 
154
  server_name="0.0.0.0",
155
  server_port=7860,
156
  share=False,
157
+ allowed_paths=[str(EXAMPLES_DIR), str(OUTPUT_DIR)]
158
  )
app_optimized.py CHANGED
@@ -25,9 +25,17 @@ from core.optimization import (
25
  ParallelInference,
26
  OptimizedInferenceWrapper
27
  )
 
28
 
29
  # サンプルファイルのディレクトリを定義
30
  EXAMPLES_DIR = (Path(__file__).parent / "example").resolve()
 
 
 
 
 
 
 
31
 
32
  # 初期化フラグ
33
  print("=== Phase 3 最適化版 - 初期化開始 ===")
@@ -202,9 +210,10 @@ def process_talking_head_optimized(
202
  try:
203
  start_time = time.time()
204
 
205
- # 一時ファイルの作成
206
- with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as tmp_output:
207
- output_path = tmp_output.name
 
208
 
209
  # アバタートークンから埋め込みを取得
210
  if avatar_token:
@@ -425,6 +434,7 @@ with gr.Blocks(title="DittoTalkingHead - Phase 3 最適化版") as demo:
425
  with gr.Row():
426
  clear_inference_cache_btn = gr.Button("🗑️ 推論キャッシュをクリア", variant="secondary")
427
  clear_avatar_cache_btn = gr.Button("🗑️ アバターキャッシュをクリア", variant="secondary")
 
428
 
429
  cache_status = gr.Textbox(label="キャッシュ操作ステータス", lines=2)
430
 
@@ -497,9 +507,17 @@ with gr.Blocks(title="DittoTalkingHead - Phase 3 最適化版") as demo:
497
  fn=clear_avatar_cache,
498
  outputs=[cache_status]
499
  )
 
 
 
 
 
500
 
501
  if __name__ == "__main__":
502
  # Cold Start最適化設定でGradioを起動
503
  launch_settings = cold_start_optimizer.optimize_gradio_settings()
504
 
 
 
 
505
  demo.launch(**launch_settings)
 
25
  ParallelInference,
26
  OptimizedInferenceWrapper
27
  )
28
+ from cleanup_old_files import initialize_cleanup, get_cleanup_status
29
 
30
  # サンプルファイルのディレクトリを定義
31
  EXAMPLES_DIR = (Path(__file__).parent / "example").resolve()
32
+ OUTPUT_DIR = (Path(__file__).parent / "output").resolve()
33
+
34
+ # 出力ディレクトリの作成
35
+ OUTPUT_DIR.mkdir(exist_ok=True)
36
+
37
+ # ファイルクリーンアップの初期化(24時間後に自動削除)
38
+ initialize_cleanup(OUTPUT_DIR, max_age_hours=24)
39
 
40
  # 初期化フラグ
41
  print("=== Phase 3 最適化版 - 初期化開始 ===")
 
210
  try:
211
  start_time = time.time()
212
 
213
+ # 出力ファイルの作成(出力ディレクトリ内)
214
+ import uuid
215
+ output_filename = f"{uuid.uuid4()}.mp4"
216
+ output_path = str(OUTPUT_DIR / output_filename)
217
 
218
  # アバタートークンから埋め込みを取得
219
  if avatar_token:
 
434
  with gr.Row():
435
  clear_inference_cache_btn = gr.Button("🗑️ 推論キャッシュをクリア", variant="secondary")
436
  clear_avatar_cache_btn = gr.Button("🗑️ アバターキャッシュをクリア", variant="secondary")
437
+ cleanup_status_btn = gr.Button("📊 クリーンアップ状態", variant="secondary")
438
 
439
  cache_status = gr.Textbox(label="キャッシュ操作ステータス", lines=2)
440
 
 
507
  fn=clear_avatar_cache,
508
  outputs=[cache_status]
509
  )
510
+
511
+ cleanup_status_btn.click(
512
+ fn=lambda: get_cleanup_status(),
513
+ outputs=[cache_status]
514
+ )
515
 
516
  if __name__ == "__main__":
517
  # Cold Start最適化設定でGradioを起動
518
  launch_settings = cold_start_optimizer.optimize_gradio_settings()
519
 
520
+ # allowed_pathsを追加
521
+ launch_settings['allowed_paths'] = [str(EXAMPLES_DIR), str(OUTPUT_DIR)]
522
+
523
  demo.launch(**launch_settings)
app_streaming.py CHANGED
@@ -12,6 +12,10 @@ DATA_ROOT = "checkpoints/ditto_pytorch"
12
 
13
  # サンプルファイルのディレクトリ
14
  EXAMPLES_DIR = (Path(__file__).parent / "example").resolve()
 
 
 
 
15
 
16
  # グローバルで一度だけロード(concurrency_count=1 前提)
17
  sdk: StreamSDK | None = None
@@ -44,7 +48,9 @@ def generator(mic, src_img):
44
  sdk = init_sdk()
45
 
46
  # setup: online_mode=True でストリーミング
47
- tmp_out = tempfile.mktemp(suffix=".mp4")
 
 
48
  sdk.setup(src_img, tmp_out, online_mode=True, max_size=1024)
49
  N_total = int(np.ceil(len(wav_full) / sr * 20)) # 概算フレーム数
50
  sdk.setup_Nd(N_total)
@@ -191,5 +197,6 @@ if __name__ == "__main__":
191
  demo.queue(concurrency_count=1, max_size=8).launch(
192
  server_name="0.0.0.0",
193
  server_port=7860,
194
- share=False
 
195
  )
 
12
 
13
  # サンプルファイルのディレクトリ
14
  EXAMPLES_DIR = (Path(__file__).parent / "example").resolve()
15
+ OUTPUT_DIR = (Path(__file__).parent / "output").resolve()
16
+
17
+ # 出力ディレクトリの作成
18
+ OUTPUT_DIR.mkdir(exist_ok=True)
19
 
20
  # グローバルで一度だけロード(concurrency_count=1 前提)
21
  sdk: StreamSDK | None = None
 
48
  sdk = init_sdk()
49
 
50
  # setup: online_mode=True でストリーミング
51
+ import uuid
52
+ output_filename = f"{uuid.uuid4()}.mp4"
53
+ tmp_out = str(OUTPUT_DIR / output_filename)
54
  sdk.setup(src_img, tmp_out, online_mode=True, max_size=1024)
55
  N_total = int(np.ceil(len(wav_full) / sr * 20)) # 概算フレーム数
56
  sdk.setup_Nd(N_total)
 
197
  demo.queue(concurrency_count=1, max_size=8).launch(
198
  server_name="0.0.0.0",
199
  server_port=7860,
200
+ share=False,
201
+ allowed_paths=[str(EXAMPLES_DIR), str(OUTPUT_DIR)]
202
  )
cleanup_old_files.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ 出力ディレクトリの古いファイルをクリーンアップする機能
3
+ """
4
+
5
+ import os
6
+ import time
7
+ from pathlib import Path
8
+ from datetime import datetime, timedelta
9
+ import threading
10
+ import logging
11
+
12
+ # ロギング設定
13
+ logging.basicConfig(level=logging.INFO)
14
+ logger = logging.getLogger(__name__)
15
+
16
+ class FileCleanupManager:
17
+ """定期的に古いファイルを削除するマネージャー"""
18
+
19
+ def __init__(self, output_dir: Path, max_age_hours: float = 24, check_interval_minutes: int = 60):
20
+ """
21
+ Args:
22
+ output_dir: 監視対象のディレクトリ
23
+ max_age_hours: ファイルを保持する最大時間(時間)
24
+ check_interval_minutes: チェック間隔(分)
25
+ """
26
+ self.output_dir = output_dir
27
+ self.max_age_seconds = max_age_hours * 3600
28
+ self.check_interval = check_interval_minutes * 60
29
+ self._running = False
30
+ self._thread = None
31
+
32
+ def start(self):
33
+ """クリーンアップ処理を開始"""
34
+ if self._running:
35
+ logger.warning("Cleanup manager is already running")
36
+ return
37
+
38
+ self._running = True
39
+ self._thread = threading.Thread(target=self._cleanup_loop, daemon=True)
40
+ self._thread.start()
41
+ logger.info(f"Started cleanup manager for {self.output_dir}")
42
+
43
+ def stop(self):
44
+ """クリーンアップ処理を停止"""
45
+ self._running = False
46
+ if self._thread:
47
+ self._thread.join()
48
+ logger.info("Stopped cleanup manager")
49
+
50
+ def _cleanup_loop(self):
51
+ """定期的にクリーンアップを実行"""
52
+ while self._running:
53
+ try:
54
+ self.cleanup_now()
55
+ except Exception as e:
56
+ logger.error(f"Error during cleanup: {e}")
57
+
58
+ # 次のチェックまで待機
59
+ time.sleep(self.check_interval)
60
+
61
+ def cleanup_now(self):
62
+ """今すぐクリーンアップを実行"""
63
+ if not self.output_dir.exists():
64
+ logger.warning(f"Output directory does not exist: {self.output_dir}")
65
+ return
66
+
67
+ current_time = time.time()
68
+ deleted_count = 0
69
+ deleted_size = 0
70
+
71
+ # MP4ファイルをチェック
72
+ for file_path in self.output_dir.glob("*.mp4"):
73
+ try:
74
+ # ファイルの最終変更時刻を取得
75
+ file_age = current_time - file_path.stat().st_mtime
76
+
77
+ if file_age > self.max_age_seconds:
78
+ file_size = file_path.stat().st_size
79
+ file_path.unlink()
80
+ deleted_count += 1
81
+ deleted_size += file_size
82
+ logger.debug(f"Deleted old file: {file_path.name} (age: {file_age/3600:.1f} hours)")
83
+
84
+ except Exception as e:
85
+ logger.error(f"Failed to delete {file_path}: {e}")
86
+
87
+ if deleted_count > 0:
88
+ logger.info(f"Cleanup completed: deleted {deleted_count} files, freed {deleted_size/1024/1024:.1f} MB")
89
+
90
+ def get_directory_stats(self):
91
+ """ディレクトリの統計情報を取得"""
92
+ if not self.output_dir.exists():
93
+ return {
94
+ "total_files": 0,
95
+ "total_size_mb": 0,
96
+ "oldest_file_hours": None
97
+ }
98
+
99
+ files = list(self.output_dir.glob("*.mp4"))
100
+ if not files:
101
+ return {
102
+ "total_files": 0,
103
+ "total_size_mb": 0,
104
+ "oldest_file_hours": None
105
+ }
106
+
107
+ total_size = sum(f.stat().st_size for f in files)
108
+ current_time = time.time()
109
+ oldest_age = max((current_time - f.stat().st_mtime) for f in files)
110
+
111
+ return {
112
+ "total_files": len(files),
113
+ "total_size_mb": total_size / 1024 / 1024,
114
+ "oldest_file_hours": oldest_age / 3600
115
+ }
116
+
117
+
118
+ # グローバルインスタンス(アプリケーションで使用)
119
+ cleanup_manager = None
120
+
121
+ def initialize_cleanup(output_dir: Path, max_age_hours: float = 24):
122
+ """クリーンアップマネージャーを初期化して開始"""
123
+ global cleanup_manager
124
+
125
+ if cleanup_manager is not None:
126
+ cleanup_manager.stop()
127
+
128
+ cleanup_manager = FileCleanupManager(output_dir, max_age_hours)
129
+ cleanup_manager.start()
130
+
131
+ return cleanup_manager
132
+
133
+
134
+ def get_cleanup_status():
135
+ """クリーンアップの状態を取得"""
136
+ if cleanup_manager is None:
137
+ return "Cleanup manager not initialized"
138
+
139
+ stats = cleanup_manager.get_directory_stats()
140
+ return f"""
141
+ クリーンアップ状態:
142
+ - ファイル数: {stats['total_files']}
143
+ - 合計サイズ: {stats['total_size_mb']:.1f} MB
144
+ - 最古のファイル: {stats['oldest_file_hours']:.1f} 時間前 (最古のファイルがある場合)
145
+ """
146
+
147
+
148
+ if __name__ == "__main__":
149
+ # テスト実行
150
+ output_dir = Path("./output")
151
+ output_dir.mkdir(exist_ok=True)
152
+
153
+ # テスト用のダミーファイルを作成
154
+ test_file = output_dir / "test.mp4"
155
+ test_file.write_text("dummy content")
156
+
157
+ # 古いファイルをシミュレート(2日前)
158
+ old_time = time.time() - (48 * 3600)
159
+ os.utime(test_file, (old_time, old_time))
160
+
161
+ # クリーンアップマネージャーを初期化
162
+ manager = FileCleanupManager(output_dir, max_age_hours=24)
163
+
164
+ # 即座にクリーンアップを実行
165
+ print("Before cleanup:", manager.get_directory_stats())
166
+ manager.cleanup_now()
167
+ print("After cleanup:", manager.get_directory_stats())