Compare commits

...

3 commits

Author SHA1 Message Date
7f0b6309ab antani 2020-11-05 11:28:24 +01:00
e4854e9548 update examples 2020-04-19 20:12:29 +02:00
fe23d233a0 add transmit function 2020-04-19 20:03:03 +02:00
6 changed files with 178 additions and 1 deletions

View file

@ -2,6 +2,7 @@ mumble-bot
========== ==========
prende l'audio del canale, ne fa stdout. prende l'audio del canale, ne fa stdout.
prende l'audio da stdin, lo manda nel canale.
Install Install
-------- --------
@ -58,3 +59,10 @@ samplerate: 48000,
``` ```
Poi entri in chat e fai il comando `/start` per iniziare la diretta, `/stop` per fermarla. Poi entri in chat e fai il comando `/start` per iniziare la diretta, `/stop` per fermarla.
Client headless
===============
```
parecord --channels=1 --rate=48000 --format=s16le --raw | python3 bot.py --transmit --stream | paplay --raw --rate 48000 --format=s16le --channels=2
```

View file

@ -1,8 +1,11 @@
import argparse import argparse
import audioop import audioop
import logging import logging
import math
import sys import sys
import struct
import time import time
import threading
from functools import partial from functools import partial
import pymumble_py3 as pymumble import pymumble_py3 as pymumble
@ -11,6 +14,32 @@ from pymumble_py3.constants import PYMUMBLE_CLBK_TEXTMESSAGERECEIVED
is_streaming = False is_streaming = False
silence_time = 0 silence_time = 0
SHORT_NORMALIZE = (1.0/32768.0)
## peak detection
def get_rms( block ):
# RMS amplitude is defined as the square root of the
# mean over time of the square of the amplitude.
# so we need to convert this string of bytes into
# a string of 16-bit samples...
# we will get one short out for each
# two chars in the string.
count = len(block)/2
format = "%dh"%(count)
shorts = struct.unpack( format, block )
# iterate over the block.
sum_squares = 0.0
for sample in shorts:
# sample is a signed short in +/- 32768.
# normalize it to 1.0
n = sample * SHORT_NORMALIZE
sum_squares += n*n
return math.sqrt( sum_squares / count )
def message_received(mumble, message): def message_received(mumble, message):
global is_streaming global is_streaming
@ -41,6 +70,11 @@ def get_parser():
action="store_true", action="store_true",
help="Ignore commands in chat and stream everything", help="Ignore commands in chat and stream everything",
) )
parser.add_argument(
"--transmit",
action="store_true",
help="Transmit from your stdin",
)
parser.add_argument( parser.add_argument(
"--auto-suspend-stream", "--auto-suspend-stream",
action="store_true", action="store_true",
@ -63,6 +97,22 @@ def get_parser():
return parser return parser
def transmit(name, mumble, chunk_size):
buffer = 0
while True:
try:
data = sys.stdin.buffer.read(int(chunk_size))
if(get_rms(data) > 0.09):
mumble.sound_output.add_sound(data)
buffer = 1000
else:
# keep the audio open for one second
if(buffer >= 0):
mumble.sound_output.add_sound(data)
buffer -= 10
except IOError as e:
print( " Error recording: %s"3%e 0)
def main(): def main():
global is_streaming global is_streaming
global silence_time global silence_time
@ -89,7 +139,8 @@ def main():
mumble.start() mumble.start()
mumble.is_ready() # Wait for client is ready mumble.is_ready() # Wait for client is ready
mumble.channels.find_by_tree(channel.split('/')).move_in() mumble.channels.find_by_tree(channel.split('/')).move_in()
mumble.users.myself.mute() if not args.transmit:
mumble.users.myself.mute()
if is_streaming: if is_streaming:
mumble.users.myself.recording() mumble.users.myself.recording()
@ -103,6 +154,10 @@ def main():
silent = b"\x00" * int(STEREO_CHUNK_SIZE) silent = b"\x00" * int(STEREO_CHUNK_SIZE)
cursor_time = time.time() - BUFFER cursor_time = time.time() - BUFFER
if args.transmit:
transmit_thread = threading.Thread(target=transmit, args=(1,mumble, MONO_CHUNK_SIZE))
transmit_thread.start()
while mumble.is_alive(): while mumble.is_alive():
if cursor_time < time.time() - BUFFER: if cursor_time < time.time() - BUFFER:
base_sound = None base_sound = None

0
mumble-bot/bot.pya Normal file
View file

57
mumble-bot/bot2.py Normal file
View file

@ -0,0 +1,57 @@
import pymumble_py3 as pymumble
import subprocess as sp
import time
import sys
import os
import fcntl
import audioop
pwd = "" # password
server = "mumble.esiliati.org" # server address
nick = "TubiaBot2"
channel = "radiospore"
port = 64738 # port number
# Spin up a client and connect to mumble server
mumble = pymumble.Mumble(server, nick, password=pwd, port=port)
# set up callback called when PCS event occurs
mumble.set_receive_sound(1) # Enable receiving sound from mumble server
mumble.start()
mumble.is_ready() # Wait for client is ready
mumble.channels.find_by_name(channel).move_in()
mumble.users.myself.mute()
BUFFER = 0.2
BITRATE = 48000
RESOLUTION = 10 # in ms
FLOAT_RESOLUTION = float(RESOLUTION) / 1000
MONO_CHUNK_SIZE = BITRATE * 2 * RESOLUTION / 1000
STEREO_CHUNK_SIZE = MONO_CHUNK_SIZE * 2
silent = b"\x00" * int(STEREO_CHUNK_SIZE)
cursor_time = None
cursor_time = time.time() - BUFFER
while mumble.is_alive():
if cursor_time < time.time() - BUFFER: # it's time to check audio
base_sound = None
try:
for user in mumble.users.values(): # check the audio queue of each user
if(user.sound.is_sound()):
print(user["name"])
while ( user.sound.is_sound() and int(user.sound.first_sound().time) < int(cursor_time)):
print("perdona e dimentica"+str(user.sound.first_sound().timestamp)+" "+str(cursor_time))
user.sound.get_sound(FLOAT_RESOLUTION) # forget about too old sounds
if user.sound.is_sound():
print(user["name"]+" estraggo")
sound = user.sound.get_sound(FLOAT_RESOLUTION)
except RuntimeError:
eprint("ignored exception in stderr...")
cursor_time += FLOAT_RESOLUTION
else:
time.sleep(FLOAT_RESOLUTION)

34
mumble-bot/silent-bot.py Normal file
View file

@ -0,0 +1,34 @@
import pymumble_py3 as pymumble
import subprocess as sp
from time import sleep
import sys
import os
import fcntl
import pyaudio
pwd = "" # password
server = "mumble.esiliati.org" # server address
nick = "TubiaBotSilente"
channel = "radiospore_onair"
port = 64738 # port number
# pyaudio set up
CHUNK = 1024
FORMAT = pyaudio.paInt16 # pymumble soundchunk.pcm is 16 bits
CHANNELS = 1
RATE = 48000 # pymumble soundchunk.pcm is 48000Hz
# Spin up a client and connect to mumble server
mumble = pymumble.Mumble(server, nick, password=pwd, port=port)
# set up callback called when PCS event occurs
mumble.set_receive_sound(0) # Enable receiving sound from mumble server
mumble.start()
mumble.is_ready() # Wait for client is ready
mumble.channels.find_by_name(channel).move_in()
#mumble.users.myself.mute()
# constant capturing sound and sending it to mumble server
while True:
mumble.sound_output.add_sound(bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]))

23
mumble-bot/testparams.py Normal file
View file

@ -0,0 +1,23 @@
import argparse
import sys
pwd=""
server = "mumble.esiliati.org" # server address
nick = "TubiaBot"
channel = "radiospore"
port = 64738 # port number
is_streaming=False
stream_always=False
parser = argparse.ArgumentParser(description='Regia pienamente automatizzata')
parser.add_argument('--channel', help='Set channel')
parser.add_argument('--name', help='Set bot nickname', default="RadioRobbot")
parser.add_argument('--server', help='Set server', default="mumble.esiliati.org")
parser.add_argument('--port', help='Set port', type=int)
parser.add_argument('--stream', action='store_true', help='Ignore commands in chat and stream everything')
sys.argv.pop(0)
args = parser.parse_args(sys.argv)
print(args.name)