| <!doctype html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <link rel="icon" type="image/svg+xml" href="./favicon.ico" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
| <title>Translator</title> |
| <script type="module" crossorigin src="./assets/index-d7a7d66c.js"></script> |
| <link rel="stylesheet" href="./assets/index-a48dc1a0.css"> |
| </head> |
| <body> |
| <div id="app"></div> |
| </body> |
| <script> |
| async function startRecording() { |
| const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); |
| const audioContext = new AudioContext({ sampleRate: 16000 }); |
| const source = audioContext.createMediaStreamSource(stream); |
| const processor = audioContext.createScriptProcessor(4096, 1, 1); |
| |
| const wsUrl = "ws://localhost:9090/ws?from=zh&to=en"; |
| ws = new WebSocket(wsUrl); |
| |
| ws.binaryType = "arraybuffer"; |
| |
| ws.onopen = () => { |
| console.log("WebSocket opened"); |
| source.connect(processor); |
| processor.connect(audioContext.destination); |
| |
| processor.onaudioprocess = (e) => { |
| const input = e.inputBuffer.getChannelData(0); |
| const buffer = new Int16Array(input.length); |
| for (let i = 0; i < input.length; i++) { |
| buffer[i] = Math.max(-1, Math.min(1, input[i])) * 0x7FFF; |
| } |
| ws.send(buffer); |
| }; |
| }; |
| |
| ws.onmessage = (event) => { |
| try { |
| const msg = JSON.parse(event.data); |
| if (msg.result) { |
| addTranslation(msg.result); |
| } |
| } catch (e) { |
| console.error("Parse error:", e); |
| } |
| }; |
| |
| ws.onerror = (e) => console.error("WebSocket error:", e); |
| ws.onclose = () => { |
| console.log("WebSocket closed"); |
| processor.disconnect(); |
| source.disconnect(); |
| }; |
| } |
| </script> |
| </body> |
| </html> |
|
|