bot.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import pymumble_py3 as pymumble
  2. from pymumble_py3.constants import *
  3. import subprocess as sp
  4. import time
  5. import sys
  6. import os
  7. import fcntl
  8. import audioop
  9. import argparse
  10. def message_received(message):
  11. global is_streaming
  12. global silence_time
  13. command=message.message
  14. if command == "/start":
  15. is_streaming = True
  16. silence_time = 0
  17. mumble.my_channel().send_text_message("Diretta iniziata")
  18. mumble.users.myself.recording()
  19. elif command == "/stop":
  20. is_streaming = False
  21. mumble.my_channel().send_text_message("Diretta terminata")
  22. mumble.users.myself.unrecording()
  23. parser = argparse.ArgumentParser(description='Regia pienamente automatizzata')
  24. parser.add_argument('--channel', help='Set channel', default="")
  25. parser.add_argument('--name', help='Set bot nickname', default="RadioRobbot")
  26. parser.add_argument('--server', help='Set server', default="mumble.esiliati.org")
  27. parser.add_argument('--port', help='Set port', type=int, default=64738)
  28. parser.add_argument('--stream', action='store_true', help='Ignore commands in chat and stream everything')
  29. parser.add_argument('--auto-suspend-stream', action='store_true', help='Ignore commands in chat and stream everything')
  30. parser.add_argument('--max-silence-time', type=int, help='max silence time in seconds', default=30)
  31. sys.argv.pop(0)
  32. args = parser.parse_args(sys.argv)
  33. pwd = "" # password
  34. server = args.server
  35. nick = args.name
  36. channel = args.channel
  37. port = args.port
  38. is_streaming=False
  39. stream_always= args.stream
  40. auto_suspend_stream = args.auto_suspend_stream
  41. silence_limit = 30
  42. # Spin up a client and connect to mumble server
  43. mumble = pymumble.Mumble(server, nick, password=pwd, port=port)
  44. mumble.callbacks.set_callback(PYMUMBLE_CLBK_TEXTMESSAGERECEIVED, message_received)
  45. mumble.set_receive_sound(1) # Enable receiving sound from mumble server
  46. mumble.start()
  47. mumble.is_ready() # Wait for client is ready
  48. mumble.channels.find_by_name(channel).move_in()
  49. mumble.users.myself.mute()
  50. if is_streaming:
  51. mumble.users.myself.recording()
  52. BUFFER = 0.1
  53. BITRATE = 48000
  54. RESOLUTION = 10 # in ms
  55. FLOAT_RESOLUTION = float(RESOLUTION) / 1000
  56. MONO_CHUNK_SIZE = BITRATE * 2 * RESOLUTION / 1000
  57. STEREO_CHUNK_SIZE = MONO_CHUNK_SIZE * 2
  58. silent = b"\x00" * int(STEREO_CHUNK_SIZE)
  59. cursor_time = None
  60. cursor_time = time.time() - BUFFER
  61. silence_time = 0
  62. silence_limit_ms = silence_limit * 1000
  63. while mumble.is_alive():
  64. if cursor_time < time.time() - BUFFER:
  65. base_sound = None
  66. try:
  67. for user in mumble.users.values(): # check the audio queue of each user
  68. if user.sound.is_sound():
  69. # available sound is to be treated now and not later
  70. sound = user.sound.get_sound(FLOAT_RESOLUTION)
  71. stereo_pcm = audioop.tostereo(sound.pcm, 2, 1, 1)
  72. if base_sound == None:
  73. base_sound = stereo_pcm
  74. else:
  75. base_sound = audioop.add(base_sound, stereo_pcm, 2)
  76. except RuntimeError:
  77. print("ignored exception in stderr...", file=sys.stderr)
  78. if is_streaming or stream_always:
  79. if base_sound:
  80. silence_time = 0
  81. sys.stdout.buffer.write(base_sound)
  82. else:
  83. silence_time += RESOLUTION
  84. sys.stdout.buffer.write(silent)
  85. if auto_suspend_stream and (silence_time >= silence_limit_ms) and is_streaming:
  86. is_streaming = False
  87. mumble.my_channel().send_text_message("Diretta terminata in automatico dopo "+str(silence_limit)+" secondi circa di silenzio")
  88. mumble.users.myself.unrecording()
  89. cursor_time += FLOAT_RESOLUTION
  90. else:
  91. time.sleep(FLOAT_RESOLUTION)