add ducking feature.

This commit is contained in:
Terry Geng 2020-02-08 18:40:59 +08:00
parent ce2dae9048
commit c5fa90b78d
3 changed files with 46 additions and 12 deletions

View File

@ -33,6 +33,10 @@ max_track_playlist = 20
# Maximum music duration (minutes) # Maximum music duration (minutes)
max_track_duration = 60 max_track_duration = 60
# If ducking is enabled, the bot will automatically attenuate its volume when someone is talking.
ducking = False
ducking_volume = 0.05
[webinterface] [webinterface]
enabled = False enabled = False
is_web_proxified = True is_web_proxified = True

View File

@ -243,11 +243,11 @@ def post():
elif action == "clear": elif action == "clear":
var.botamusique.stop() var.botamusique.stop()
elif action == "volume_up": elif action == "volume_up":
if var.botamusique.volume + 0.03 < 1.0: if var.botamusique.volume_set + 0.03 < 1.0:
var.botamusique.volume = var.botamusique.volume + 0.03 var.botamusique.volume_set = var.botamusique.volume_set + 0.03
else: else:
var.botamusique.volume = 1.0 var.botamusique.volume_set = 1.0
logging.info("web: volume up to %d" % (var.botamusique.volume * 100)) logging.info("web: volume up to %d" % (var.botamusique.volume_set * 100))
elif action == "volume_down": elif action == "volume_down":
if var.botamusique.volume - 0.03 > 0: if var.botamusique.volume - 0.03 > 0:
var.botamusique.volume = var.botamusique.volume - 0.03 var.botamusique.volume = var.botamusique.volume - 0.03

View File

@ -4,6 +4,7 @@
import threading import threading
import time import time
import sys import sys
import math
import signal import signal
import configparser import configparser
import audioop import audioop
@ -67,9 +68,11 @@ version = 5
class MumbleBot: class MumbleBot:
def __init__(self, args): def __init__(self, args):
signal.signal(signal.SIGINT, self.ctrl_caught) signal.signal(signal.SIGINT, self.ctrl_caught)
self.volume = var.config.getfloat('bot', 'volume') self.volume_set = var.config.getfloat('bot', 'volume')
if db.has_option('bot', 'volume'): if db.has_option('bot', 'volume'):
self.volume = var.db.getfloat('bot', 'volume') self.volume_set = var.db.getfloat('bot', 'volume')
self.volume = self.volume_set
self.channel = args.channel self.channel = args.channel
@ -116,6 +119,7 @@ class MumbleBot:
tt.daemon = True tt.daemon = True
tt.start() tt.start()
if args.host: if args.host:
host = args.host host = args.host
else: else:
@ -160,6 +164,14 @@ class MumbleBot:
self.mumble.channels.find_by_name(self.channel).move_in() self.mumble.channels.find_by_name(self.channel).move_in()
self.mumble.set_bandwidth(200000) self.mumble.set_bandwidth(200000)
self.is_ducking = False
self.on_ducking = False
if var.config.getboolean("bot", "ducking"):
self.is_ducking = True
self.ducking_volume = var.config.getfloat("bot", "ducking_volume")
self.mumble.callbacks.set_callback(pymumble.constants.PYMUMBLE_CLBK_SOUNDRECEIVED, self.ducking_sound_received)
self.mumble.set_receive_sound(True)
# Set the CTRL+C shortcut # Set the CTRL+C shortcut
def ctrl_caught(self, signal, frame): def ctrl_caught(self, signal, frame):
logging.info( logging.info(
@ -173,7 +185,6 @@ class MumbleBot:
# All text send to the chat is analysed by this function # All text send to the chat is analysed by this function
def message_received(self, text): def message_received(self, text):
message = text.message.strip() message = text.message.strip()
user = self.mumble.users[text.actor]['name'] user = self.mumble.users[text.actor]['name']
@ -506,14 +517,14 @@ class MumbleBot:
elif command == var.config.get('command', 'volume'): elif command == var.config.get('command', 'volume'):
# The volume is a percentage # The volume is a percentage
if parameter is not None and parameter.isdigit() and 0 <= int(parameter) <= 100: if parameter is not None and parameter.isdigit() and 0 <= int(parameter) <= 100:
self.volume = float(float(parameter) / 100) self.volume_set = float(float(parameter) / 100)
self.send_msg(var.config.get('strings', 'change_volume') % ( self.send_msg(var.config.get('strings', 'change_volume') % (
int(self.volume * 100), self.mumble.users[text.actor]['name']), text) int(self.volume_set * 100), self.mumble.users[text.actor]['name']), text)
var.db.set('bot', 'volume', str(self.volume)) var.db.set('bot', 'volume', str(self.volume_set))
logging.info('bot: volume set to %d' % (self.volume * 100)) logging.info('bot: volume set to %d' % (self.volume_set * 100))
else: else:
self.send_msg(var.config.get( self.send_msg(var.config.get(
'strings', 'current_volume') % int(self.volume * 100), text) 'strings', 'current_volume') % int(self.volume_set * 100), text)
elif command == var.config.get('command', 'current_music'): elif command == var.config.get('command', 'current_music'):
if len(var.playlist.playlist) > 0: if len(var.playlist.playlist) > 0:
@ -710,6 +721,7 @@ class MumbleBot:
self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480) self.thread = sp.Popen(command, stdout=sp.PIPE, bufsize=480)
self.is_playing = True self.is_playing = True
self.is_pause = False self.is_pause = False
self.last_volume_cycle_time = time.time()
def download_music(self, index=-1): def download_music(self, index=-1):
if index == -1: if index == -1:
@ -856,6 +868,23 @@ class MumbleBot:
th.daemon = True th.daemon = True
th.start() th.start()
def volume_cycle(self):
delta = time.time() - self.last_volume_cycle_time
if delta > 0.001:
if self.is_ducking and self.on_ducking:
self.volume = (self.volume - self.ducking_volume) * math.exp(- delta / 0.2) + self.ducking_volume
if self.ducking_release > time.time():
self.on_ducking = False
else:
self.volume = self.volume_set - (self.volume_set - self.volume) * math.exp(- delta / 0.5)
self.last_volume_cycle_time = time.time()
def ducking_sound_received(self, user, sound):
self.on_ducking = True
self.ducking_release = time.time() + 1 # ducking release after 0.5s
@staticmethod @staticmethod
# Parse the html from the message to get the URL # Parse the html from the message to get the URL
def get_url_from_input(string): def get_url_from_input(string):
@ -881,6 +910,7 @@ class MumbleBot:
raw_music = self.thread.stdout.read(480) raw_music = self.thread.stdout.read(480)
if raw_music: if raw_music:
# Adjust the volume and send it to mumble # Adjust the volume and send it to mumble
self.volume_cycle()
self.mumble.sound_output.add_sound( self.mumble.sound_output.add_sound(
audioop.mul(raw_music, 2, self.volume)) audioop.mul(raw_music, 2, self.volume))
else: else: