| import grpc |
| import time |
| import sys |
| import wave |
| from concurrent.futures import ThreadPoolExecutor, as_completed |
|
|
| sys.path.insert(0, 'server/grpc') |
| import avatar_pb2 |
| import avatar_pb2_grpc |
|
|
| |
| audio_path = 'data/audio/orpheus_demo_3_phrases.wav' |
| with wave.open(audio_path, 'rb') as wf: |
| sample_rate = wf.getframerate() |
| audio_data = wf.readframes(wf.getnframes()) |
|
|
| audio_duration = len(audio_data) / (sample_rate * 2) |
| print(f'Audio: {audio_duration:.2f}s') |
| print() |
|
|
| def run_session(session_id, stub): |
| def audio_chunks(): |
| chunk_size = 4800 |
| for i in range(0, len(audio_data), chunk_size): |
| yield avatar_pb2.AudioChunk( |
| session_id=f'user_{session_id}', |
| audio_data=audio_data[i:i+chunk_size], |
| sample_rate=sample_rate, |
| is_final=(i + chunk_size >= len(audio_data)) |
| ) |
| |
| start = time.time() |
| first_frame_time = None |
| frame_count = 0 |
| |
| try: |
| for response in stub.StreamingGenerate(audio_chunks()): |
| if first_frame_time is None: |
| first_frame_time = time.time() - start |
| frame_count += 1 |
| except Exception as e: |
| return {'error': str(e), 'session_id': session_id} |
| |
| total_time = time.time() - start |
| fps = frame_count / total_time if total_time > 0 else 0 |
| |
| return { |
| 'session_id': session_id, |
| 'ttff': first_frame_time * 1000 if first_frame_time else 0, |
| 'frames': frame_count, |
| 'fps': fps, |
| 'total_time': total_time |
| } |
|
|
| def test_concurrent_users(num_users): |
| channel = grpc.insecure_channel('localhost:8080') |
| stub = avatar_pb2_grpc.AvatarServiceStub(channel) |
| |
| results = [] |
| with ThreadPoolExecutor(max_workers=num_users) as executor: |
| futures = [executor.submit(run_session, i, stub) for i in range(num_users)] |
| for future in as_completed(futures): |
| results.append(future.result()) |
| |
| return results |
|
|
| |
| print('=' * 70) |
| print('TESTE DE CAPACIDADE MULTI-USUARIO (torch.compile ENABLED)') |
| print('=' * 70) |
| print(f'Users | Avg TTFF | Avg FPS | Min FPS | Real-time?') |
| print('-' * 70) |
|
|
| realtime_fps = 25 |
|
|
| for num_users in [1, 2, 3, 4, 5, 6, 8]: |
| results = test_concurrent_users(num_users) |
| valid = [r for r in results if 'error' not in r] |
| |
| if valid: |
| avg_ttff = sum(r['ttff'] for r in valid) / len(valid) |
| avg_fps = sum(r['fps'] for r in valid) / len(valid) |
| min_fps = min(r['fps'] for r in valid) |
| is_realtime = 'YES' if min_fps >= realtime_fps else 'NO' |
| |
| print(f'{num_users:>5} | {avg_ttff:>8.0f}ms | {avg_fps:>7.1f} | {min_fps:>7.1f} | {is_realtime}') |
| else: |
| print(f'{num_users:>5} | ERROR') |
| |
| time.sleep(2) |
|
|
| print('=' * 70) |
| print(f'Real-time threshold: {realtime_fps} FPS (video is 25 FPS)') |
| print('=' * 70) |
|
|