client.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. let socket = new WebSocket("ws://localhost:9001");
  2. let displayDiv = document.getElementById('textDisplay');
  3. let server_available = false;
  4. let mic_available = false;
  5. let fullSentences = [];
  6. const serverCheckInterval = 5000; // Check every 5 seconds
  7. function connectToServer() {
  8. socket = new WebSocket("ws://localhost:9001");
  9. socket.onopen = function(event) {
  10. server_available = true;
  11. start_msg();
  12. };
  13. socket.onmessage = function(event) {
  14. let data = JSON.parse(event.data);
  15. if (data.type === 'realtime') {
  16. displayRealtimeText(data.text, displayDiv);
  17. } else if (data.type === 'fullSentence') {
  18. fullSentences.push(data.text);
  19. displayRealtimeText("", displayDiv); // Refresh display with new full sentence
  20. }
  21. };
  22. socket.onclose = function(event) {
  23. server_available = false;
  24. };
  25. }
  26. socket.onmessage = function(event) {
  27. let data = JSON.parse(event.data);
  28. if (data.type === 'realtime') {
  29. displayRealtimeText(data.text, displayDiv);
  30. } else if (data.type === 'fullSentence') {
  31. fullSentences.push(data.text);
  32. displayRealtimeText("", displayDiv); // Refresh display with new full sentence
  33. }
  34. };
  35. function displayRealtimeText(realtimeText, displayDiv) {
  36. let displayedText = fullSentences.map((sentence, index) => {
  37. let span = document.createElement('span');
  38. span.textContent = sentence + " ";
  39. span.className = index % 2 === 0 ? 'yellow' : 'cyan';
  40. return span.outerHTML;
  41. }).join('') + realtimeText;
  42. displayDiv.innerHTML = displayedText;
  43. }
  44. function start_msg() {
  45. if (!mic_available)
  46. displayRealtimeText("🎤 please allow microphone access 🎤", displayDiv);
  47. else if (!server_available)
  48. displayRealtimeText("🖥️ please start server 🖥️", displayDiv);
  49. else
  50. displayRealtimeText("👄 start speaking 👄", displayDiv);
  51. };
  52. // Check server availability periodically
  53. setInterval(() => {
  54. if (!server_available) {
  55. connectToServer();
  56. }
  57. }, serverCheckInterval);
  58. start_msg()
  59. socket.onopen = function(event) {
  60. server_available = true;
  61. start_msg()
  62. };
  63. // Request access to the microphone
  64. navigator.mediaDevices.getUserMedia({ audio: true })
  65. .then(stream => {
  66. let audioContext = new AudioContext();
  67. let source = audioContext.createMediaStreamSource(stream);
  68. let processor = audioContext.createScriptProcessor(256, 1, 1);
  69. source.connect(processor);
  70. processor.connect(audioContext.destination);
  71. mic_available = true;
  72. start_msg()
  73. processor.onaudioprocess = function(e) {
  74. let inputData = e.inputBuffer.getChannelData(0);
  75. let outputData = new Int16Array(inputData.length);
  76. // Convert to 16-bit PCM
  77. for (let i = 0; i < inputData.length; i++) {
  78. outputData[i] = Math.max(-32768, Math.min(32767, inputData[i] * 32768));
  79. }
  80. // Send the 16-bit PCM data to the server
  81. if (socket.readyState === WebSocket.OPEN) {
  82. // Create a JSON string with metadata
  83. let metadata = JSON.stringify({ sampleRate: audioContext.sampleRate });
  84. // Convert metadata to a byte array
  85. let metadataBytes = new TextEncoder().encode(metadata);
  86. // Create a buffer for metadata length (4 bytes for 32-bit integer)
  87. let metadataLength = new ArrayBuffer(4);
  88. let metadataLengthView = new DataView(metadataLength);
  89. // Set the length of the metadata in the first 4 bytes
  90. metadataLengthView.setInt32(0, metadataBytes.byteLength, true); // true for little-endian
  91. // Combine metadata length, metadata, and audio data into a single message
  92. let combinedData = new Blob([metadataLength, metadataBytes, outputData.buffer]);
  93. socket.send(combinedData);
  94. }
  95. };
  96. })
  97. .catch(e => console.error(e));