speech2speech-interface / interface /test_webrtc_playwright.py
marcosremar2's picture
Add WebRTC streaming interface with vast.ai deployment
e62aafd
Raw
History Blame Contribute Delete
7.36 kB
#!/usr/bin/env python3
"""
Teste WebRTC automatizado com Playwright headless
"""
import asyncio
from playwright.async_api import async_playwright
import sys
SERVER_URL = "http://62.107.25.198:47898"
async def test_webrtc():
print("="*60)
print("Teste WebRTC com Playwright (Headless)")
print("="*60)
async with async_playwright() as p:
# Iniciar browser headless
print("\n[1/6] Iniciando browser headless...")
browser = await p.chromium.launch(
headless=True,
args=[
'--use-fake-ui-for-media-stream',
'--use-fake-device-for-media-stream',
'--no-sandbox'
]
)
context = await browser.new_context(
permissions=['camera', 'microphone']
)
page = await context.new_page()
# Coletar logs do console e erros
console_logs = []
page_errors = []
page.on("console", lambda msg: console_logs.append(f"[{msg.type}] {msg.text}"))
page.on("pageerror", lambda exc: page_errors.append(f"ERROR: {exc}"))
# Capturar requests/responses
network_logs = []
def handle_response(response):
if '/offer' in response.url:
network_logs.append(f"POST /offer → Status: {response.status}")
if response.status != 200:
network_logs.append(f" Error: {response.status_text}")
page.on("response", handle_response)
# Navegar para a página
print(f"[2/6] Navegando para {SERVER_URL}...")
try:
await page.goto(SERVER_URL, timeout=10000)
print("✓ Página carregada")
except Exception as e:
print(f"✗ Erro ao carregar página: {e}")
await browser.close()
return False
# Verificar se a página carregou
print("[3/6] Verificando elementos...")
try:
await page.wait_for_selector('#btnConnect', timeout=5000)
print("✓ Botão 'Conectar' encontrado")
except Exception as e:
print(f"✗ Erro: {e}")
await browser.close()
return False
# Injetar código para capturar eventos ICE
print("[4/6] Configurando captura de eventos ICE...")
await page.evaluate("""
window.iceInfo = {
candidates: [],
states: [],
connectionStates: []
};
// Interceptar console.log de ICE candidates
const originalLog = console.log;
console.log = function(...args) {
if (args[0] === 'ICE Candidate:') {
window.iceInfo.candidates.push(args[1]);
} else if (args[0] === 'ICE State:') {
window.iceInfo.states.push(args[1]);
} else if (args[0] === 'Estado WebRTC:') {
window.iceInfo.connectionStates.push(args[1]);
}
originalLog.apply(console, args);
};
""")
# Clicar em conectar
print("[5/6] Clicando em 'Conectar'...")
await page.click('#btnConnect')
# Aguardar tentativa de conexão
print("[6/6] Aguardando conexão (15s)...")
await asyncio.sleep(15)
# Capturar informações ICE
ice_info = await page.evaluate("window.iceInfo")
# Capturar estado da conexão
webrtc_state = await page.evaluate("""
(() => {
const pc = window.pc;
if (!pc) return null;
return {
connectionState: pc.connectionState,
iceConnectionState: pc.iceConnectionState,
iceGatheringState: pc.iceGatheringState,
signalingState: pc.signalingState
};
})()
""")
# Resultados
print("\n" + "="*60)
print("RESULTADOS")
print("="*60)
if webrtc_state:
print(f"\nEstados WebRTC:")
print(f" Connection: {webrtc_state['connectionState']}")
print(f" ICE Connection: {webrtc_state['iceConnectionState']}")
print(f" ICE Gathering: {webrtc_state['iceGatheringState']}")
print(f" Signaling: {webrtc_state['signalingState']}")
else:
print("\n✗ Peer connection não foi criada!")
# Análise de candidatos ICE
candidates = ice_info.get('candidates', [])
print(f"\nCandidatos ICE: {len(candidates)}")
candidate_types = {}
for c in candidates:
ctype = c.get('type', 'unknown')
candidate_types[ctype] = candidate_types.get(ctype, 0) + 1
for ctype, count in candidate_types.items():
icon = "✓" if ctype == "relay" else "•"
print(f" {icon} {ctype}: {count}")
# Diagnóstico
print("\n" + "="*60)
print("DIAGNÓSTICO")
print("="*60)
success = False
if not webrtc_state:
print("\n✗ FALHA: Peer connection não foi criada")
print(" → Verificar JavaScript do frontend")
elif webrtc_state['connectionState'] == 'connected':
print("\n✓ SUCESSO: WebRTC conectado!")
success = True
elif webrtc_state['iceConnectionState'] == 'failed':
print("\n✗ FALHA: ICE connection failed")
if len(candidates) == 0:
print(" → Problema: Nenhum candidato ICE gerado")
print(" → Solução: Verificar configuração STUN/TURN")
elif 'relay' not in candidate_types:
print(" → Problema: Nenhum candidato TURN (relay)")
print(" → Solução: Servidores TURN não estão funcionando")
print(" → Tentar outros servidores TURN")
else:
print(" → Problema: Candidatos gerados mas não conectam")
print(" → Solução: Problema de firewall/NAT no servidor")
print(" → Verificar port mapping UDP no vast.ai")
elif webrtc_state['connectionState'] == 'connecting':
print("\n⚠ TIMEOUT: Conexão travada em 'connecting'")
print(" → Problema: ICE negotiation timeout")
print(" → Causa provável: Port mapping UDP não configurado")
print(" → Solução: Expor portas UDP no vast.ai ou usar ngrok")
# Erros de página
if page_errors:
print("\n" + "="*60)
print("ERROS JAVASCRIPT")
print("="*60)
for err in page_errors:
print(err)
# Logs de rede
if network_logs:
print("\n" + "="*60)
print("LOGS DE REDE")
print("="*60)
for log in network_logs:
print(log)
# Logs do console
if console_logs:
print("\n" + "="*60)
print("LOGS DO CONSOLE (últimos 20)")
print("="*60)
for log in console_logs[-20:]:
print(log)
await browser.close()
return success
async def main():
success = await test_webrtc()
sys.exit(0 if success else 1)
if __name__ == "__main__":
asyncio.run(main())