def __init__(self): self.speech_engine = sr.Recognizer() self.speech_engine.pause_threshold = 0.5 with sr.Microphone(device_index=None) as source: self.speech_engine.adjust_for_ambient_noise(source) self.tts = Text_to_Speech() self.tts.start('male') audio.init()
def __init__(self, token, tiane): self.token = token self.tiane = tiane # Ne Verbindung zur Hauptklasse schadet nie ;) self.stt = Speech_to_Text([]) self.tts = Text_to_Speech(19000, 'de-DE') self.bot = telepot.Bot(token) self.bot.getMe() self.messages = []
class InstallationAudio: def __init__(self): self.speech_engine = sr.Recognizer() self.speech_engine.pause_threshold = 0.5 with sr.Microphone(device_index=None) as source: self.speech_engine.adjust_for_ambient_noise(source) self.tts = Text_to_Speech() self.tts.start('male') audio.init() def recognize_input(self): self.play_bling_sound() try: with sr.Microphone(device_index=None) as source: audio = self.speech_engine.listen(source) try: text = self.speech_engine.recognize_google(audio, language="de-DE") print(text) except: text = "Audio konnte nicht aufgenommen werden" return text except: traceback.print_exc() print("[WARNING] Text konnte nicht übersetzt werden...") return "Das habe ich leider nicht verstanden." def say(self, text): self.tts.say(text) while self.tts.is_reading: time.sleep(0.1) def play_bling_sound(self): TOP_DIR = os.path.dirname(os.path.abspath(__file__)) DETECT_DONG = os.path.join(TOP_DIR.rstrip('setup'), "resources/sounds/bling.wav") with open(DETECT_DONG, "rb") as wavfile: input_wav = wavfile.read() data = io.BytesIO(input_wav) track = audio.Sound(data) audio.Channel(0).play(track)
def __init__(self, voice): # The channel are splittet on the buffers: # Channel(0): notification # Channel(1): music # Channel(2): playback self.listen = False # music means "Backgroundmusic" or something like that self.music = [] # playback are similar to music, but don´t contain "music" self.playback = [] # notifications reduce the loudness from music but don´t pause it self.notification = [] # mixer0: notification, mixer1: music self.mixer = [] self.music_player = MusicPlayer(self) mixer.pre_init(44100, -16, 1, 512) self.tts = Text_to_Speech() self.tts.start(voice) self.stopped = True
class AudioOutput: """ ------------------------- AudioOutput: - responsible for the "normal" audio output - don´t use it for playing music (this is the task of the "MusicPlayer" class) ------------------------- """ def __init__(self, voice): # The channel are splittet on the buffers: # Channel(0): notification # Channel(1): music # Channel(2): playback self.listen = False # music means "Backgroundmusic" or something like that self.music = [] # playback are similar to music, but don´t contain "music" self.playback = [] # notifications reduce the loudness from music but don´t pause it self.notification = [] # mixer0: notification, mixer1: music self.mixer = [] self.music_player = MusicPlayer(self) mixer.pre_init(44100, -16, 1, 512) self.tts = Text_to_Speech() self.tts.start(voice) self.stopped = True def start(self): logging.info("[ACTION] Starting audio output module...") self.stopped = False mixer.init() time.sleep(2) ot = Thread(target=self.run) ot.daemon = True ot.start() return self def run(self): while not self.stopped: try: if self.listen: mixer.Channel(0).set_volume(0.1) mixer.Channel(1).set_volume(0.1) mixer.Channel(2).set_volume(0.1) self.music_player.set_volume(0.1) if not self.notification == [] and mixer.Channel( 0).get_busy() == 0 and not self.tts.is_reading: if mixer.Channel(0).get_busy() == 1: mixer.Channel(1).set_volume(0.10) mixer.Channel(2).set_volume(0.10) if isinstance(self.notification[0], str): logging.info(f'Saying "{self.notification[0]}"') # if the notification is a string (a message to say), pass through to tts self.tts.say(self.notification[0]) self.notification.pop(0) else: logging.info( f'Playing the track "{self.notification[0]}"') # else pass through to mixer-manager track = mixer.Sound(self.notification[0]) self.notification.pop(0) mixer.Channel(0).play(track) if not self.music == [] and mixer.Channel(2).get_busy() == 0: print(self.music) if isinstance(self.music[0], str): logging.info(f'Play music with name {self.music[0]}') topic = self.music[0] self.music.pop(0) self.music_player.play(by_name=topic) else: logging.info(f'Play track with path {self.music[0]}') track = mixer.Sound(self.music[0]) mixer.Channel(2).play(track) self.playback.pop(0) if not self.playback == [] and mixer.Channel( 1).get_busy() == 0: track = mixer.Sound(self.playback[0]) self.playback.pop(0) mixer.Channel(1).play(track) if not mixer.Channel(0).get_busy() is 1 and mixer.Channel( 1).get_volume != 1 and mixer.Channel( 2).get_volume != 1: mixer.Channel(1).set_volume(1) mixer.Channel(2).set_volume(1) time.sleep(0.2) except: traceback.print_exc() def say(self, text): # Forwards the given text to the text-to-speech function and waits # until the announcement has ended. if text == '' or text is None: text = 'Das sollte nicht passieren. Eines meiner internen Module antwortet nicht mehr.' self.notification.append(text) while text in self.notification: time.sleep(0.2) def detected_hotword(self): self.listen = True self.music_player.set_volume(10) def continue_after_hotword(self): self.listen = False self.music_player.set_volume(100) def play_music(self, name, as_next=False): if as_next: self.music.insert(0, name) else: self.music.append(name) def play_playback(self, buff, as_next): if not as_next: self.playback.append(buff) else: self.playback.insert(0, buff) def play_notification(self, buff, as_next): if not as_next: self.notification.append(buff) else: self.notification.insert(0, buff) def play_bling_sound(self): TOP_DIR = os.path.dirname(os.path.abspath(__file__)) DETECT_DONG = os.path.join(TOP_DIR, "resources/sounds/bling.wav") with open(DETECT_DONG, "rb") as wavfile: input_wav = wavfile.read() data = io.BytesIO(input_wav) self.play_notification(data, as_next=True) @staticmethod def pause(channel): mixer.Channel(channel).pause() @staticmethod def resume(channel): mixer.Channel(channel).unpause() @staticmethod def set_volume(channel, volume): mixer.Channel(channel).set_volume(volume) @staticmethod def stop_notification(): mixer.Channel(0).stop() @staticmethod def stop_music(): mixer.Channel(1).stop() @staticmethod def stop_playback(): mixer.Channel(2).stop() def stop(self): self.stopped = True self.music_player.stop() mixer.stop() self.tts.stop()
class TelegramInterface: def __init__(self, token, tiane): self.token = token self.tiane = tiane # Ne Verbindung zur Hauptklasse schadet nie ;) self.stt = Speech_to_Text([]) self.tts = Text_to_Speech(19000, 'de-DE') self.bot = telepot.Bot(token) self.bot.getMe() self.messages = [] def say(self, text, uid, conv_id, output='telegram'): try: user = self.tiane.local_storage['TIANE_telegram_id_to_name_table'][ uid] except: user = uid self.tiane.Log.write('ACTION', '--{}--@{} (Telegram): {}'.format( self.tiane.system_name.upper(), user, text), conv_id=conv_id, show=True) # Kann sehr einfach eine Nachricht senden... if not ('speech' in output.lower() or 'voice' in output.lower()): self.bot.sendMessage(uid, text, parse_mode='HTML') else: # ...oder sogar in eine Sprachnachricht umwandeln! _, voice_filename = mkstemp(prefix='voice-', suffix='.wav') _, converted_audio_filename = mkstemp(prefix='converted-audio-', suffix='.oga') wavformat, wav = self.tts.say(text) with wave.open(voice_filename, 'wb') as file: file.setnchannels(wavformat['channels']) file.setframerate(wavformat['rate']) file.setsampwidth(2) file.writeframes(wav) cmd = [ '/usr/bin/ffmpeg', '-y', '-loglevel', 'panic', '-i', voice_filename, '-acodec', 'libopus', converted_audio_filename ] subprocess.call(cmd, shell=False) self.bot.sendVoice(uid, open(converted_audio_filename, 'rb')) os.remove(converted_audio_filename) os.remove(voice_filename) def start(self): def on_chat_message(msg): content_type, chat_type, chat_id = telepot.glance(msg) if content_type == 'text': msg['content_type'] = 'text' elif content_type == 'voice': msg['content_type'] = 'voice' _, voice_filename = mkstemp(prefix='voice-', suffix='.oga') _, converted_audio_filename = mkstemp( prefix='converted-audio-', suffix='.wav') self.bot.download_file(msg['voice']['file_id'], voice_filename) cmd = [ '/usr/bin/ffmpeg', '-y', '-loglevel', 'panic', '-i', voice_filename, '-codec:a', 'pcm_s16le', converted_audio_filename ] subprocess.call(cmd, shell=False) msg['text'] = self.stt.recognize(converted_audio_filename) with open(voice_filename, 'rb') as file: msg['content'] = file.read() # self.bot.sendMessage(chat_id, msg['text']) os.remove(converted_audio_filename) os.remove(voice_filename) elif content_type == 'photo': msg['content_type'] = 'photo' file = BytesIO() self.bot.download_file(msg['photo'][-1]['file_id'], file) file.seek(0) msg['content'] = file.read() else: msg['content_type'] = content_type # Auf jeden Fall einen 'text' ergänzen (der bei manchen content_types einfach caption heißt) try: text = msg['text'] except KeyError: try: msg['text'] = msg['caption'] except KeyError: msg['text'] = 'TIMEOUT_OR_INVALID' self.messages.append(msg) def on_callback_query(msg): msg['text'] = msg['data'] msg['content_type'] = 'callback_query' self.messages.append(msg) MessageLoop(self.bot, { 'chat': on_chat_message, 'callback_query': on_callback_query }).run_as_thread()