| |
| |
| |
|
|
| import { AvatarStreamSDK, StreamStatus, StreamMetrics } from '../src'; |
|
|
| |
| const canvas = document.getElementById('avatar-canvas') as HTMLCanvasElement; |
|
|
| |
| const statusEl = document.getElementById('status')!; |
| const latencyEl = document.getElementById('latency')!; |
| const fpsEl = document.getElementById('fps')!; |
| const videoDurationEl = document.getElementById('video-duration')!; |
| const audioDurationEl = document.getElementById('audio-duration')!; |
| const syncDiffEl = document.getElementById('sync-diff')!; |
|
|
| |
| const avatar = new AvatarStreamSDK({ |
| wsUrl: 'ws://localhost:8080/ws', |
| canvas, |
|
|
| |
| onStatusChange: (status: StreamStatus) => { |
| console.log('Status:', status); |
| statusEl.textContent = status; |
|
|
| |
| statusEl.className = ''; |
| if (status === 'playing') statusEl.classList.add('status-playing'); |
| else if (status === 'error') statusEl.classList.add('status-error'); |
| else if (status === 'completed') statusEl.classList.add('status-completed'); |
| }, |
|
|
| |
| onMetricsUpdate: (metrics: StreamMetrics) => { |
| fpsEl.textContent = metrics.currentFps.toFixed(0); |
| videoDurationEl.textContent = metrics.videoDuration.toFixed(2) + 's'; |
| audioDurationEl.textContent = metrics.audioDuration.toFixed(2) + 's'; |
|
|
| |
| const diff = metrics.syncDiff; |
| syncDiffEl.textContent = (diff >= 0 ? '+' : '') + diff.toFixed(2) + 's'; |
|
|
| if (Math.abs(diff) < 0.1) { |
| syncDiffEl.style.color = 'green'; |
| } else if (Math.abs(diff) < 0.5) { |
| syncDiffEl.style.color = 'orange'; |
| } else { |
| syncDiffEl.style.color = 'red'; |
| } |
| }, |
|
|
| |
| onFirstFrame: (latencyMs: number) => { |
| console.log(`Primeiro frame: ${latencyMs}ms`); |
| }, |
|
|
| |
| onPlaybackStart: (latencyMs: number) => { |
| console.log(`Playback iniciado: ${latencyMs}ms`); |
| latencyEl.textContent = latencyMs + 'ms'; |
| }, |
|
|
| |
| onComplete: (summary) => { |
| console.log('Stream completo:', summary); |
| console.log(`Total frames: ${summary.totalFrames}`); |
| console.log(`Duração: ${summary.durationSeconds.toFixed(2)}s`); |
| console.log(`Sync final: ${summary.finalSyncDiff.toFixed(3)}s`); |
| }, |
|
|
| |
| onError: (error) => { |
| console.error('Erro:', error); |
| alert(`Erro: ${error.message}`); |
| }, |
| }); |
|
|
| |
| document.getElementById('btn-connect')?.addEventListener('click', async () => { |
| try { |
| await avatar.connect(); |
| console.log('Conectado!'); |
| } catch (e) { |
| console.error('Erro ao conectar:', e); |
| } |
| }); |
|
|
| |
| document.getElementById('btn-generate')?.addEventListener('click', async () => { |
| const text = (document.getElementById('text-input') as HTMLTextAreaElement)?.value; |
| const voice = (document.getElementById('voice-select') as HTMLSelectElement)?.value; |
|
|
| if (!text) { |
| alert('Digite um texto!'); |
| return; |
| } |
|
|
| try { |
| await avatar.generate(text, voice); |
| } catch (e) { |
| console.error('Erro ao gerar:', e); |
| } |
| }); |
|
|
| |
| document.getElementById('btn-stop')?.addEventListener('click', () => { |
| avatar.stop(); |
| }); |
|
|
| |
| document.getElementById('btn-disconnect')?.addEventListener('click', () => { |
| avatar.disconnect(); |
| }); |
|
|
| |
| avatar.connect().then(() => { |
| console.log('Conectado automaticamente'); |
| }).catch(e => { |
| console.log('Auto-connect falhou:', e); |
| }); |
|
|