diff --git a/multilang_translator/config.py b/multilang_translator/config.py index e850d5b..597928f 100644 --- a/multilang_translator/config.py +++ b/multilang_translator/config.py @@ -1,39 +1,39 @@ import os +from dataclasses import dataclass, field +from auracast import auracast_config ANNOUNCEMENT_DIR = os.path.join(os.path.dirname(__file__), 'announcements') VENV_DIR = os.path.join(os.path.dirname(__file__), '../venv') PIPER_EXE_PATH = f'{VENV_DIR}/bin/piper' -FRAME_DUR_MS = 10 -SAMPLING_RATE_HZ = int(16e3) -BITRATE_BPS = int(32e3) -LANG_CONFIG = { - "de": { - "filepath_wav": f"{ANNOUNCEMENT_DIR}/announcement_de.wav", - "filepath_wav_resamp": f"{ANNOUNCEMENT_DIR}/announcement_de_resamp.wav", - "tts": 'de_DE-kerstin-low', - }, - "en": { - "filepath_wav": f"{ANNOUNCEMENT_DIR}/announcement_en.wav", - "filepath_wav_resamp": f"{ANNOUNCEMENT_DIR}/announcement_en_resamp.wav", - "tts": 'en_US-lessac-medium' - }, - "fr": { - "filepath_wav": f"{ANNOUNCEMENT_DIR}/announcement_fr.wav", - "filepath_wav_resamp": f"{ANNOUNCEMENT_DIR}/announcement_fr_resamp.wav", - "tts": 'fr_FR-siwis-medium' - }, - # "es": { - # "filepath_wav": f"{ANNOUNCEMENT_DIR}/announcement_es.wav", - # "tts": 'es_ES-sharvard-medium' - # }, - # "it": { - # "filepath_wav": f"{ANNOUNCEMENT_DIR}/announcement_it.wav", - # "tts": 'it_IT-paola-medium' - # } -} +# TODO: TRANSLATOR_LLM = 'llama3.2:3b-instruct-q4_0' +@dataclass +class TranslatorConfigDe(): + big: auracast_config.AuracastBigConfig = field(default_factory=auracast_config.AuracastBigConfigDe) + tts_system: str = 'piper' + tts_model: str ='de_DE-kerstin-low' -os.makedirs(ANNOUNCEMENT_DIR, exist_ok=True) +@dataclass +class TranslatorConfigEn(): + big: auracast_config.AuracastBigConfig = field(default_factory=auracast_config.AuracastBigConfigEn) + tts_system: str = 'piper' + tts_model: str = 'en_US-lessac-medium' -# TODO. use dataclasses from Multicaster with inherit \ No newline at end of file +@dataclass +class TranslatorConfigFr(): + big: auracast_config.AuracastBigConfig = field(default_factory=auracast_config.AuracastBigConfigFr) + tts_system: str = 'piper' + tts_model: str = 'fr_FR-siwis-medium' + +@dataclass +class TranslatorConfigEs(): + big: auracast_config.AuracastBigConfig = field(default_factory=auracast_config.AuracastBigConfigEs) + tts_system: str = 'piper' + tts_model: str = 'es_ES-sharvard-medium' + +@dataclass +class TranslatorConfigIt(): + big: auracast_config.AuracastBigConfig = field(default_factory=auracast_config.AuracastBigConfigIt) + tts_system: str = 'piper', + tts_model: str = 'it_IT-paola-medium' diff --git a/multilang_translator/main_local.py b/multilang_translator/main_local.py index a9adc42..cdf5084 100644 --- a/multilang_translator/main_local.py +++ b/multilang_translator/main_local.py @@ -4,6 +4,7 @@ list prompt example """ from __future__ import print_function, unicode_literals +from typing import List from dataclasses import asdict import asyncio from copy import copy @@ -11,13 +12,12 @@ import time import logging as log import aioconsole +import config from utils import resample from translator import llm_translator, test_content from text_to_speech import text_to_speech -from encode import encode_lc3 from auracast import multicast_control from auracast import auracast_config -from config import LANG_CONFIG, SAMPLING_RATE_HZ from translator.test_content import TESTSENTENCE # TODO: look for a end to end translation solution @@ -26,35 +26,29 @@ def transcribe(): pass # TODO: Implement transcribing input audio e.g. with whisper -def syntesize_resample(text, tts_model, file_wav, file_wav_resamp): - audio_dur = text_to_speech.synthesize(text, tts_model, file_wav) - resample.resample_file(file_wav, file_wav_resamp, target_rate=SAMPLING_RATE_HZ) - return audio_dur - - async def announcement_from_german_text( + global_config: auracast_config.AuracastGlobalConfig, + translator_config: List[config.TranslatorConfigDe], caster: multicast_control.Multicaster, text_de ): TRANSLATOR_LLM = 'llama3.2:3b-instruct-q4_0' - config = copy(LANG_CONFIG) - base_lang = "de" + base_lang = "deu" - for i, d in enumerate(config.items()): - key, val = d - if key == base_lang: + for i, trans in enumerate(translator_config): + if trans.big.language == base_lang: text = text_de else: - text = llm_translator.translate_de_to_x(text_de, key, model=TRANSLATOR_LLM) + text = llm_translator.translate_de_to_x(text_de, trans.big.language, model=TRANSLATOR_LLM) log.info('%s', text) lc3_audio = text_to_speech.synthesize( text, - SAMPLING_RATE_HZ, - 'piper', - val['tts'], + global_config.auracast_sampling_rate_hz, + trans.big.tts_system, + trans.big.tts_model, return_lc3=True ) caster.big_conf[i].audio_source = lc3_audio @@ -103,22 +97,25 @@ async def main(): #global_conf.transport='serial:/dev/serial/by-id/usb-SEGGER_J-Link_001057705357-if02,1000000,rtscts' # transport for nrf54l15dk global_conf.transport='serial:/dev/serial/by-id/usb-ZEPHYR_Zephyr_HCI_UART_sample_81BD14B8D71B5662-if00,115200,rtscts' #nrf52dongle hci_uart usb cdc - big_conf = [ - auracast_config.broadcast_de, - auracast_config.broadcast_en, - auracast_config.broadcast_fr, + translator_conf = [ + config.TranslatorConfigDe(), + config.TranslatorConfigEn(), + config.TranslatorConfigFr(), #auracast_config.broadcast_es, #auracast_config.broadcast_it, ] - for i, conf in enumerate(big_conf): - conf.loop = False + for i, conf in enumerate(translator_conf): + conf.big.loop = False - caster = multicast_control.Multicaster(global_conf, big_conf) + caster = multicast_control.Multicaster(global_conf, [conf.big for conf in translator_conf]) await caster.init_broadcast() - #await announcement_from_german_text(caster, test_content.TESTSENTENCE.DE_HELLO) - #await asyncio.wait([caster.streamer.task]) - await command_line_ui(caster) + await announcement_from_german_text( + caster, + test_content.TESTSENTENCE.DE_HELLO + ) + await asyncio.wait([caster.streamer.task]) + #await command_line_ui(caster) if __name__ == '__main__': asyncio.run(main()) diff --git a/multilang_translator/translator/syspromts.py b/multilang_translator/translator/syspromts.py index 562099d..0c523b3 100644 --- a/multilang_translator/translator/syspromts.py +++ b/multilang_translator/translator/syspromts.py @@ -1,4 +1,6 @@ -TRANSLATOR_DE_EN = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Englische. Antworte nur mit der übersetzten Satz.\n' -TRANSLATOR_DE_FR = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Französische. Antworte nur mit der übersetzten Satz.\n' -TRANSLATOR_DE_ES = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Spanische. Antworte nur mit der übersetzten Satz.\n' -TRANSLATOR_DE_IT = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Italienische. Antworte nur mit der übersetzten Satz.\n' + +# TODO: make this more elegant. this can probably be generated and the base lang be assumed by the llm? +TRANSLATOR_DEU_ENG = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Englische. Antworte nur mit der übersetzten Satz.\n' +TRANSLATOR_DEU_FRA = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Französische. Antworte nur mit der übersetzten Satz.\n' +TRANSLATOR_DEU_SPA = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Spanische. Antworte nur mit der übersetzten Satz.\n' +TRANSLATOR_DEU_ITA = 'Du bist ein Übersetzer. Übersetze die folgende Satz aus dem Deutschen ins Italienische. Antworte nur mit der übersetzten Satz.\n'