oKen38461 commited on
Commit
ada2c6f
·
1 Parent(s): 910f2aa

app.pyに新しい機能を追加し、サンプルファイルの読み込み処理を改善しました。また、`requirements.txt`に新たに依存関係を追加しました。

Browse files
Files changed (2) hide show
  1. README_jp.md +124 -0
  2. test_performance.py +175 -0
README_jp.md ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # DittoTalkingHead プロジェクト
2
+
3
+ ## プロジェクト概要
4
+ このリポジトリは、音声から自然なトーキングヘッド動画を生成するDittoモデルの実装と、そのAPI化を行うプロジェクトです。単一の画像と音声ファイルから、音声に同期した自然な表情や口の動きを持つ動画を生成します。
5
+
6
+ ## 作業フロー
7
+ 本プロジェクトは、Statement of Work (SOW) ドキュメントを作成してから実装を行う段階的なアプローチを採用しています。
8
+
9
+ ### フェーズ構成
10
+ 1. **Phase 1**: 基本実装 - Hugging Face Spacesへのデプロイ
11
+ 2. **Phase 2**: API実装 - REST API化とクライアント実装
12
+ 3. **Phase 3**: パフォーマンス最適化 - 処理速度の大幅改善
13
+
14
+ ## ディレクトリ構造
15
+
16
+ ### `/` ルートディレクトリ
17
+ - `README.md` - Hugging Face Spaces用のメタデータ付きREADME
18
+ - `README_jp.md` - 日本語プロジェクト説明(このファイル)
19
+ - `README_ditto-talkinghead.md` - Dittoモデルの技術詳細
20
+ - `README_hf_space.md` - Hugging Face Spacesデプロイメント説明
21
+ - `app.py` - Gradio Webアプリケーションのメインファイル
22
+ - `inference.py` - モデル推論の実装
23
+ - `model_manager.py` - モデルファイルの管理・ダウンロード
24
+ - `test_api.py` - API機能のテストスクリプト
25
+ - `test_api_client.py` - APIクライアントの実装
26
+ - `test_performance.py` - パフォーマンステストツール
27
+ - `requirements.txt` - Python依存関係
28
+ - `environment.yaml` - Conda環境設定
29
+ - `packages.txt` - システムパッケージ依存関係
30
+
31
+ ### `/ToDo` 計画ドキュメント
32
+ - `plan-v0.md` - 初期調査報告と実装計画
33
+ - `0717-1_Phase1_SOW_revised.md` - Phase 1 実装仕様書(基本実装)
34
+ - `0717-2_Phase2_API_SOW.md` - Phase 2 実装仕様書(API化)
35
+ - `0717-3_Phase3_Performance_SOW.md` - Phase 3 実装仕様書(高速化)
36
+
37
+ ### `/core` コアモデル実装
38
+ - `/atomic_components` - モデルの基本コンポーネント
39
+ - `audio2motion.py` - 音声から動きへの変換
40
+ - `avatar_registrar.py` - アバター登録処理
41
+ - `wav2feat.py` - 音声特徴抽出
42
+ - `warp_f3d.py` - 3D特徴のワーピング
43
+ - 他多数の処理モジュール
44
+ - `/aux_models` - 補助モデル(顔検出、ランドマーク検出等)
45
+ - `face_mesh.py` - 顔メッシュ検出
46
+ - `hubert_stream.py` - HuBERT音声モデル
47
+ - `mediapipe_landmark478.py` - MediaPipeランドマーク
48
+ - `/models` - メインモデル実装
49
+ - `appearance_extractor.py` - 外観特徴抽出
50
+ - `decoder.py` - デコーダー
51
+ - `lmdm.py` - ランドマーク拡散モデル
52
+ - `/modules` - モデルモジュール群
53
+ - `/utils` - ユーティリティ関数
54
+ - `crop.py` - 画像クロップ処理
55
+ - `load_model.py` - モデルロード
56
+ - `tensorrt_utils.py` - TensorRT最適化
57
+
58
+ ### `/docs` ドキュメント
59
+ - `APIドキュメント.md` - API仕様書(日本語)
60
+ - `api_documentation.md` - API仕様書(英語)
61
+ - `deployment_guide.md` - デプロイメントガイド
62
+ - `model_upload_guide.md` - モデルアップロードガイド
63
+
64
+ ### `/example` サンプルファイル
65
+ - `audio.wav` - サンプル音声
66
+ - `image.png` - サンプル画像
67
+ - `2025-07-17_22-12-46.mp4` - 生成サンプル動画
68
+
69
+ ### `/scripts` ユーティリティスクリプト
70
+ - `cvt_onnx_to_trt.py` - ONNXからTensorRTへの変換
71
+
72
+ ### `/stream_pipeline_*` リアルタイム処理
73
+ - `stream_pipeline_online.py` - オンラインストリーミング処理
74
+ - `stream_pipeline_offline.py` - オフライン処理
75
+
76
+ ## 主要な機能
77
+
78
+ ### 1. 基本的な動画生成
79
+ - 音声ファイル(WAV)とソース画像(PNG/JPG)から動画生成
80
+ - 自然な口の動きと表情の同期
81
+ - 高品質な動画出力
82
+
83
+ ### 2. API機能
84
+ - REST APIエンドポイント(`/process_talking_head`)
85
+ - 画像の事前アップロード機能(`/prepare_avatar`)
86
+ - 非同期処理とキャッシュサポート
87
+
88
+ ### 3. パフォーマンス最適化(Phase 3で実装予定)
89
+ - 解像度320×320固定による高速化
90
+ - 画像埋め込みの事前計算とキャッシュ
91
+ - TensorRT/ONNX最適化
92
+ - 目標: 16秒の音声を10秒以内で処理
93
+
94
+ ## 使用方法
95
+
96
+ ### Web UI経由
97
+ 1. Hugging Face Spaces(https://huggingface.co/spaces/O-ken5481/talkingAvater_bgk)にアクセス
98
+ 2. 音声ファイルと画像をアップロード
99
+ 3. 「生成」ボタンをクリック
100
+
101
+ ### API経由
102
+ ```python
103
+ from gradio_client import Client, handle_file
104
+
105
+ client = Client("O-ken5481/talkingAvater_bgk")
106
+ result = client.predict(
107
+ audio_file=handle_file("path/to/audio.wav"),
108
+ source_image=handle_file("path/to/image.png"),
109
+ api_name="/process_talking_head"
110
+ )
111
+ ```
112
+
113
+ ## 技術スタック
114
+ - **モデル**: Ditto TalkingHead(Ant Group Research)
115
+ - **フレームワーク**: PyTorch, ONNX Runtime, TensorRT
116
+ - **WebUI**: Gradio
117
+ - **インフラ**: Hugging Face Spaces(GPU: A100)
118
+ - **補助モデル**: HuBERT(音声特徴)、MediaPipe(顔ランドマーク)
119
+
120
+ ## 今後の展開
121
+ - Phase 3の高速化実装(TensorRT最適化、キャッシュシステム)
122
+ - リアルタイムストリーミング対応
123
+ - 複数話者の対応
124
+ - より高解像度での生成オプション
test_performance.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ パフォーマンステストスクリプト
4
+ 動画生成の各ステップの実行時間を計測
5
+ """
6
+
7
+ import time
8
+ import logging
9
+ from test_api_client import TalkingHeadAPIClient
10
+ import os
11
+
12
+ # ロギング設定
13
+ logging.basicConfig(
14
+ level=logging.INFO,
15
+ format='%(asctime)s - %(message)s',
16
+ datefmt='%Y-%m-%d %H:%M:%S'
17
+ )
18
+
19
+ class TimingStats:
20
+ def __init__(self):
21
+ self.stats = {}
22
+ self.start_times = {}
23
+
24
+ def start(self, name):
25
+ self.start_times[name] = time.time()
26
+
27
+ def end(self, name):
28
+ if name in self.start_times:
29
+ duration = time.time() - self.start_times[name]
30
+ self.stats[name] = duration
31
+ return duration
32
+ return None
33
+
34
+ def report(self):
35
+ print("\n=== パフォーマンス計測結果 ===")
36
+ total_time = sum(self.stats.values())
37
+ for name, duration in self.stats.items():
38
+ percentage = (duration / total_time) * 100 if total_time > 0 else 0
39
+ print(f"{name}: {duration:.2f}秒 ({percentage:.1f}%)")
40
+ print(f"\n合計時間: {total_time:.2f}秒")
41
+
42
+ # 音声ファイルの長さを取得
43
+ try:
44
+ import librosa
45
+ audio_path = "example/audio.wav"
46
+ y, sr = librosa.load(audio_path, sr=None)
47
+ audio_duration = len(y) / sr
48
+ print(f"音声ファイルの長さ: {audio_duration:.2f}秒")
49
+ print(f"処理時間比率: {total_time/audio_duration:.2f}x")
50
+ except Exception as e:
51
+ print(f"音声長さの取得失敗: {e}")
52
+
53
+ def test_performance():
54
+ """パフォーマンステストを実行"""
55
+ timer = TimingStats()
56
+
57
+ # 全体の開始時間
58
+ timer.start("全体処理")
59
+
60
+ # クライアント初期化
61
+ timer.start("API接続")
62
+ try:
63
+ client = TalkingHeadAPIClient()
64
+ timer.end("API接続")
65
+ except Exception as e:
66
+ logging.error(f"クライアント初期化失敗: {e}")
67
+ return
68
+
69
+ # サンプルファイル
70
+ audio_path = "example/audio.wav"
71
+ image_path = "example/image.png"
72
+
73
+ # ファイル情報を表示
74
+ audio_size = os.path.getsize(audio_path) / 1024 / 1024 # MB
75
+ image_size = os.path.getsize(image_path) / 1024 / 1024 # MB
76
+ print(f"\n入力ファイル情報:")
77
+ print(f"- 音声: {audio_path} ({audio_size:.2f} MB)")
78
+ print(f"- 画像: {image_path} ({image_size:.2f} MB)")
79
+
80
+ # 動画生成
81
+ timer.start("動画生成(API呼び出し)")
82
+ try:
83
+ result = client.generate_video(audio_path, image_path)
84
+ video_data, status = result
85
+ timer.end("動画生成(API呼び出し)")
86
+
87
+ if video_data:
88
+ # 保存処理
89
+ timer.start("動画保存")
90
+ if isinstance(video_data, dict) and 'video' in video_data:
91
+ saved_path = client.save_with_timestamp(video_data['video'])
92
+ timer.end("動画保存")
93
+
94
+ # 出力ファイル情報
95
+ output_size = os.path.getsize(saved_path) / 1024 / 1024 # MB
96
+ print(f"\n出力ファイル情報:")
97
+ print(f"- 動画: {saved_path} ({output_size:.2f} MB)")
98
+
99
+ timer.end("全体処理")
100
+ timer.report()
101
+
102
+ print(f"\n✅ テスト成功!")
103
+ print(f"ステータス: {status}")
104
+ else:
105
+ print(f"\n❌ テスト失敗")
106
+ print(f"ステータス: {status}")
107
+
108
+ except Exception as e:
109
+ logging.error(f"エラー発生: {e}")
110
+ import traceback
111
+ traceback.print_exc()
112
+
113
+ def test_multiple_runs(runs=3):
114
+ """複数回実行して平均時間を計測"""
115
+ print(f"\n=== {runs}回連続実行テスト ===")
116
+
117
+ times = []
118
+ for i in range(runs):
119
+ print(f"\n--- 実行 {i+1}/{runs} ---")
120
+ start = time.time()
121
+
122
+ try:
123
+ client = TalkingHeadAPIClient()
124
+ result = client.generate_video("example/audio.wav", "example/image.png")
125
+ if result[0]:
126
+ duration = time.time() - start
127
+ times.append(duration)
128
+ print(f"実行時間: {duration:.2f}秒")
129
+ except Exception as e:
130
+ print(f"エラー: {e}")
131
+
132
+ if times:
133
+ avg_time = sum(times) / len(times)
134
+ min_time = min(times)
135
+ max_time = max(times)
136
+ print(f"\n=== 統計 ===")
137
+ print(f"平均時間: {avg_time:.2f}秒")
138
+ print(f"最小時間: {min_time:.2f}秒")
139
+ print(f"最大時間: {max_time:.2f}秒")
140
+
141
+ def analyze_bottlenecks():
142
+ """ボトルネック分析のための詳細テスト"""
143
+ print("\n=== ボトルネック分析 ===")
144
+
145
+ # ローカルファイルの読み込み時間
146
+ start = time.time()
147
+ with open("example/audio.wav", "rb") as f:
148
+ audio_data = f.read()
149
+ with open("example/image.png", "rb") as f:
150
+ image_data = f.read()
151
+ local_read_time = time.time() - start
152
+ print(f"ローカルファイル読み込み: {local_read_time:.3f}秒")
153
+
154
+ # ネットワーク遅延の推定(Hugging Face Spaceへのping相当)
155
+ import requests
156
+ start = time.time()
157
+ try:
158
+ response = requests.get("https://o-ken5481-talkingavater-bgk.hf.space", timeout=10)
159
+ network_time = time.time() - start
160
+ print(f"ネットワーク遅延(推定): {network_time:.3f}秒")
161
+ except:
162
+ print("ネットワーク遅延の測定失敗")
163
+
164
+ if __name__ == "__main__":
165
+ print("DittoTalkingHead パフォーマンステスト")
166
+ print("=" * 50)
167
+
168
+ # 1. 詳細な時間計測
169
+ test_performance()
170
+
171
+ # 2. 複数回実行テスト
172
+ # test_multiple_runs(3)
173
+
174
+ # 3. ボトルネック分析
175
+ analyze_bottlenecks()