Spaces:
Build error
Build error
| #!/usr/bin/env python3 | |
| """ | |
| Script de teste para a API do Montreal Forced Aligner Portuguese | |
| Testa todos os endpoints e funcionalidades da API | |
| """ | |
| import requests | |
| import json | |
| import time | |
| import os | |
| from pathlib import Path | |
| import wave | |
| import numpy as np | |
| from io import BytesIO | |
| # Configuração da API | |
| API_BASE_URL = "http://localhost:7860" # Para teste local | |
| # API_BASE_URL = "https://marcosremar2-ufpalign.hf.space" # Para Hugging Face Spaces | |
| def create_test_audio(filename="test_audio.wav", duration=3, sample_rate=16000): | |
| """ | |
| Cria um arquivo de áudio de teste simples (tom puro). | |
| Para teste real, use um arquivo WAV com fala em português. | |
| """ | |
| t = np.linspace(0, duration, int(sample_rate * duration), False) | |
| # Tom de 440 Hz (Lá) | |
| audio = np.sin(2 * np.pi * 440 * t) * 0.3 | |
| # Converter para 16-bit | |
| audio_int16 = (audio * 32767).astype(np.int16) | |
| # Salvar como WAV | |
| with wave.open(filename, 'w') as wav_file: | |
| wav_file.setnchannels(1) # Mono | |
| wav_file.setsampwidth(2) # 16-bit | |
| wav_file.setframerate(sample_rate) | |
| wav_file.writeframes(audio_int16.tobytes()) | |
| print(f"✅ Arquivo de áudio de teste criado: {filename}") | |
| return filename | |
| def test_health_check(): | |
| """Testa o endpoint de health check""" | |
| print("\n🔍 Testando Health Check...") | |
| try: | |
| response = requests.get(f"{API_BASE_URL}/health", timeout=10) | |
| if response.status_code == 200: | |
| data = response.json() | |
| print(f"✅ Health Check OK: {data}") | |
| return True | |
| else: | |
| print(f"❌ Health Check falhou: {response.status_code}") | |
| return False | |
| except Exception as e: | |
| print(f"❌ Erro no Health Check: {e}") | |
| return False | |
| def test_models_list(): | |
| """Testa o endpoint de listagem de modelos""" | |
| print("\n🔍 Testando listagem de modelos...") | |
| try: | |
| response = requests.get(f"{API_BASE_URL}/models", timeout=30) | |
| if response.status_code == 200: | |
| data = response.json() | |
| print(f"✅ Modelos disponíveis:") | |
| print(f" Acústicos: {data.get('acoustic_models', [])[:3]}...") | |
| print(f" G2P: {data.get('g2p_models', [])[:3]}...") | |
| return True | |
| else: | |
| print(f"❌ Falha ao listar modelos: {response.status_code}") | |
| return False | |
| except Exception as e: | |
| print(f"❌ Erro ao listar modelos: {e}") | |
| return False | |
| def test_alignment(audio_file=None, text="Esta é uma frase de teste em português"): | |
| """Testa o endpoint principal de alinhamento""" | |
| print("\n🔍 Testando alinhamento forçado...") | |
| # Usar arquivo de áudio fornecido ou criar um de teste | |
| if audio_file is None: | |
| audio_file = create_test_audio() | |
| if not os.path.exists(audio_file): | |
| print(f"❌ Arquivo de áudio não encontrado: {audio_file}") | |
| return False | |
| try: | |
| # Preparar dados para upload | |
| files = {'audio': open(audio_file, 'rb')} | |
| data = {'text': text} | |
| print(f"📝 Texto: {text}") | |
| print(f"🎵 Áudio: {audio_file}") | |
| print("⏳ Enviando para alinhamento...") | |
| # Fazer requisição | |
| response = requests.post( | |
| f"{API_BASE_URL}/align", | |
| files=files, | |
| data=data, | |
| timeout=300 # 5 minutos | |
| ) | |
| files['audio'].close() | |
| if response.status_code == 200: | |
| result = response.json() | |
| print(f"✅ Alinhamento concluído!") | |
| print(f" Arquivo: {result['filename']}") | |
| print(f" Duração: {result['duration']:.2f}s") | |
| print(f" Tiers: {len(result['tiers'])}") | |
| # Mostrar algumas informações dos tiers | |
| for tier in result['tiers']: | |
| print(f" - {tier['name']}: {len(tier['intervals'])} intervalos") | |
| return result | |
| else: | |
| error_data = response.json() if response.headers.get('content-type') == 'application/json' else response.text | |
| print(f"❌ Falha no alinhamento: {response.status_code}") | |
| print(f" Erro: {error_data}") | |
| return False | |
| except Exception as e: | |
| print(f"❌ Erro no alinhamento: {e}") | |
| return False | |
| finally: | |
| # Limpar arquivo de teste se foi criado | |
| if audio_file == "test_audio.wav" and os.path.exists(audio_file): | |
| os.remove(audio_file) | |
| def test_download(filename): | |
| """Testa o download do arquivo TextGrid""" | |
| print(f"\n🔍 Testando download do TextGrid: {filename}") | |
| try: | |
| # Remover extensão .TextGrid se presente | |
| base_filename = filename.replace('.TextGrid', '') | |
| response = requests.get(f"{API_BASE_URL}/download/{base_filename}", timeout=30) | |
| if response.status_code == 200: | |
| print(f"✅ Download concluído!") | |
| print(f" Tamanho: {len(response.content)} bytes") | |
| print(f" Tipo: {response.headers.get('content-type', 'unknown')}") | |
| # Salvar arquivo localmente para verificação | |
| download_filename = f"downloaded_{base_filename}.TextGrid" | |
| with open(download_filename, 'w', encoding='utf-8') as f: | |
| f.write(response.text) | |
| print(f" Salvo como: {download_filename}") | |
| return True | |
| else: | |
| print(f"❌ Falha no download: {response.status_code}") | |
| return False | |
| except Exception as e: | |
| print(f"❌ Erro no download: {e}") | |
| return False | |
| def test_web_interface(): | |
| """Testa se a interface web está acessível""" | |
| print("\n🔍 Testando interface web...") | |
| try: | |
| response = requests.get(API_BASE_URL, timeout=10) | |
| if response.status_code == 200: | |
| if "MFA Portuguese Alignment" in response.text: | |
| print("✅ Interface web acessível e funcionando") | |
| return True | |
| else: | |
| print("⚠️ Interface web acessível mas conteúdo inesperado") | |
| return False | |
| else: | |
| print(f"❌ Interface web inacessível: {response.status_code}") | |
| return False | |
| except Exception as e: | |
| print(f"❌ Erro na interface web: {e}") | |
| return False | |
| def run_full_test(audio_file=None, text=None): | |
| """Executa todos os testes da API""" | |
| print("🚀 Iniciando testes completos da API MFA Portuguese") | |
| print(f"🌐 URL base: {API_BASE_URL}") | |
| print("="*60) | |
| results = {} | |
| # Texto padrão em português | |
| if text is None: | |
| text = "Olá, este é um teste de alinhamento forçado para português brasileiro." | |
| # 1. Health Check | |
| results['health'] = test_health_check() | |
| # 2. Interface Web | |
| results['web'] = test_web_interface() | |
| # 3. Listar Modelos | |
| results['models'] = test_models_list() | |
| # 4. Alinhamento Principal | |
| alignment_result = test_alignment(audio_file, text) | |
| results['alignment'] = alignment_result is not False | |
| # 5. Download (se alinhamento foi bem-sucedido) | |
| if alignment_result and isinstance(alignment_result, dict): | |
| results['download'] = test_download(alignment_result['filename']) | |
| else: | |
| results['download'] = False | |
| print("\n⏭️ Pulando teste de download (alinhamento falhou)") | |
| # Relatório final | |
| print("\n" + "="*60) | |
| print("📊 RELATÓRIO FINAL DOS TESTES") | |
| print("="*60) | |
| total_tests = len(results) | |
| passed_tests = sum(1 for result in results.values() if result) | |
| for test_name, result in results.items(): | |
| status = "✅ PASSOU" if result else "❌ FALHOU" | |
| print(f"{test_name.upper():12} | {status}") | |
| print("-"*60) | |
| print(f"RESUMO: {passed_tests}/{total_tests} testes passaram") | |
| if passed_tests == total_tests: | |
| print("🎉 Todos os testes passaram! API funcionando perfeitamente.") | |
| return True | |
| else: | |
| print("⚠️ Alguns testes falharam. Verifique os logs acima.") | |
| return False | |
| def test_with_real_audio(): | |
| """ | |
| Exemplo de como testar com áudio real. | |
| Substitua pelos seus próprios arquivos. | |
| """ | |
| # Exemplo de uso com arquivo real | |
| audio_file = "exemplo.wav" # Substitua pelo seu arquivo | |
| text = "Transcrição exata do que está sendo falado no áudio" | |
| if os.path.exists(audio_file): | |
| print(f"\n🎯 Testando com áudio real: {audio_file}") | |
| return run_full_test(audio_file, text) | |
| else: | |
| print(f"⚠️ Arquivo {audio_file} não encontrado. Usando áudio de teste.") | |
| return run_full_test() | |
| if __name__ == "__main__": | |
| import argparse | |
| parser = argparse.ArgumentParser(description="Testa a API do MFA Portuguese") | |
| parser.add_argument("--url", default=API_BASE_URL, help="URL base da API") | |
| parser.add_argument("--audio", help="Arquivo de áudio para teste") | |
| parser.add_argument("--text", help="Texto para alinhamento") | |
| parser.add_argument("--real", action="store_true", help="Tenta usar áudio real") | |
| args = parser.parse_args() | |
| # Atualizar URL se fornecida | |
| API_BASE_URL = args.url | |
| if args.real: | |
| success = test_with_real_audio() | |
| else: | |
| success = run_full_test(args.audio, args.text) | |
| exit(0 if success else 1) |