receiver.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. """
  2. This script is the receiver component of a remote microphone streaming system.
  3. It connects to a specified WebSocket server, receives audio data streamed from a sender,
  4. and plays it back in real-time. It uses pyaudio for audio playback and numpy for
  5. manipulation of the audio data.
  6. Usage:
  7. Run the script with Python 3.x. It will automatically connect to the WebSocket server
  8. specified in the WS_URL variable and start playing received audio data.
  9. To stop the script, focus on the terminal and press Ctrl+C.
  10. """
  11. import pyaudio
  12. import websocket
  13. import threading
  14. import numpy as np
  15. from multiprocessing import Process
  16. from vosk import Model, KaldiRecognizer
  17. import hashlib
  18. import json
  19. import logging
  20. import numpy as np
  21. import os
  22. import pathlib
  23. import pyaudio
  24. import subprocess
  25. import threading
  26. import websocket
  27. # Audio configuration
  28. FORMAT = pyaudio.paInt16
  29. CHANNELS = 1
  30. RATE = 16000
  31. CHUNK = 8000
  32. # WebSocket
  33. WS_URL = (
  34. "ws://192.168.0.196/ws?password=demopassword"
  35. )
  36. logging.basicConfig()
  37. log = logging.getLogger("vosk")
  38. log_level = os.getenv("VOSK_LOG_LEVEL", "DEBUG")
  39. log.info(f"{log_level}: log_level")
  40. log.setLevel(log_level)
  41. log.info("Starting")
  42. model = Model("/home/oleg/.local/share/chezmoi/vosk/small_model")
  43. rec = KaldiRecognizer(model, RATE)
  44. def listen(data):
  45. while True:
  46. if (rec.AcceptWaveform(data)) and (len(data) > 0):
  47. answer = json.loads(rec.Result())
  48. log.debug(answer)
  49. if answer["text"]:
  50. yield answer["text"]
  51. def on_message(ws, message):
  52. # Convert the message data to a numpy array of the correct type
  53. data = np.frombuffer(message, dtype=np.int16)
  54. bytes = data.tobytes()
  55. stream.write(bytes)
  56. # while True:
  57. # data = message
  58. # rec.AcceptWaveform(data)
  59. # answer = json.loads(rec.Result())
  60. # log.debug(answer)
  61. # # if answer["text"]:
  62. # # yield answer["text"]
  63. # if (rec.AcceptWaveform(data)) and (len(data) > 0):
  64. # answer = json.loads(rec.Result())
  65. # if answer["text"]:
  66. # yield answer["text"]
  67. # something = stream.read(4000, exception_on_overflow=True)
  68. rec.AcceptWaveform(bytes)
  69. output = json.loads(rec.Result())
  70. if output['text'] is not "":
  71. log.debug(output['text'])
  72. # if (rec.AcceptWaveform(data)) and (len(data) > 0):
  73. # answer = json.loads(rec.Result())
  74. # if answer["text"]:
  75. # yield answer["text"]
  76. def on_error(ws, error):
  77. print(error)
  78. def on_open(ws):
  79. log.debug("Opened connection")
  80. def send_panic_and_exit():
  81. log.info("Panic! Sending 'panic' message...")
  82. ws.send("panic")
  83. ws.close()
  84. stream.stop_stream()
  85. stream.close()
  86. p.terminate()
  87. log.info("Terminated. Exiting.")
  88. exit()
  89. if __name__ == "__main__":
  90. ws = websocket.WebSocketApp(
  91. WS_URL, on_message=on_message, on_error=on_error
  92. )
  93. p = pyaudio.PyAudio()
  94. stream = p.open(
  95. format=FORMAT,
  96. channels=CHANNELS,
  97. rate=RATE,
  98. output=True,
  99. frames_per_buffer=CHUNK,
  100. )
  101. wst = threading.Thread(target=lambda: ws.run_forever())
  102. wst.daemon = True
  103. wst.start()
  104. log.info("Receiving... Press Ctrl+C to stop")
  105. try:
  106. while True:
  107. pass # Keep the main thread alive
  108. except KeyboardInterrupt:
  109. send_panic_and_exit()