#!/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())