From 83330e63a7dabd0dcb44f4ba1895e762e28c5e1c Mon Sep 17 00:00:00 2001 From: pstruebi Date: Sun, 15 Dec 2024 14:25:07 +0100 Subject: [PATCH] restructure the project and start using pytest --- .vscode/settings.json | 7 ++ multilang_translator/__init__.py | 0 .../backend_controller/__init__.py | 0 .../backend_controller/broadcaster_config.py | 97 +++++++++++++++++++ .../broadcaster_play_once.py | 23 +++++ .../encode}/encode_lc3.py | 0 main.py => multilang_translator/main.py | 11 ++- .../test_content}/test_content.py | 0 .../text_to_speech}/piper_welcome.sh | 0 .../text_to_speech}/resample.py | 0 .../text_to_speech}/text_to_speech.py | 0 .../text_to_speech}/voices.json | 0 .../translator}/__init__.py | 0 .../translator}/credentials.py | 0 .../translator}/llm_translator.py | 4 + .../translator}/syspromts.py | 0 pyproject.toml | 12 +++ readme.md | 2 +- tests/__init__.py | 0 tests/test_backend.py | 10 ++ 20 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 multilang_translator/__init__.py create mode 100644 multilang_translator/backend_controller/__init__.py create mode 100644 multilang_translator/backend_controller/broadcaster_config.py create mode 100644 multilang_translator/backend_controller/broadcaster_play_once.py rename {encode => multilang_translator/encode}/encode_lc3.py (100%) rename main.py => multilang_translator/main.py (83%) rename {test_content => multilang_translator/test_content}/test_content.py (100%) rename {text_to_speech => multilang_translator/text_to_speech}/piper_welcome.sh (100%) rename {text_to_speech => multilang_translator/text_to_speech}/resample.py (100%) rename {text_to_speech => multilang_translator/text_to_speech}/text_to_speech.py (100%) rename {text_to_speech => multilang_translator/text_to_speech}/voices.json (100%) rename {translator => multilang_translator/translator}/__init__.py (100%) rename {translator => multilang_translator/translator}/credentials.py (100%) rename {translator => multilang_translator/translator}/llm_translator.py (92%) rename {translator => multilang_translator/translator}/syspromts.py (100%) create mode 100644 pyproject.toml create mode 100644 tests/__init__.py create mode 100644 tests/test_backend.py diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0d129b6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.testing.pytestArgs": [ + "." + ] +} \ No newline at end of file diff --git a/multilang_translator/__init__.py b/multilang_translator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/multilang_translator/backend_controller/__init__.py b/multilang_translator/backend_controller/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/multilang_translator/backend_controller/broadcaster_config.py b/multilang_translator/backend_controller/broadcaster_config.py new file mode 100644 index 0000000..52a3922 --- /dev/null +++ b/multilang_translator/backend_controller/broadcaster_config.py @@ -0,0 +1,97 @@ +import serial +import time + + +def write_to_serial_read_respone(port, cmd, timeout = 2): + # Initialize serial connection + ser = serial.Serial(timeout = timeout) + ser.port = port + ser.baudrate = 115200 + ser.bytesize = serial.EIGHTBITS + ser.parity = serial.PARITY_NONE + ser.stopbits = serial.STOPBITS_ONE + + try: + # Try to open the serial connection + #if not ser.is_open: + ser.open() + + # Send string to serial port and get response + command = f"{cmd.strip()}\r\n" + ser.write(command.encode()) + time.sleep(1) # wait a bit for response + + readlines = [] + for _ in range(20): + line = ser.readline().decode('utf-8').strip() + if not line: + ser.close() + break + else: + readlines.append(line) + + except serial.SerialException as e: + print(f"Error communicating with serial port: {e}") + finally: + # Close serial connection before returning + if ser.is_open: + ser.close() + return readlines + + + +def gen_broadcast_config_cmd(serial_port, preset, broadcast_config: dict): + """ + Writes broadcaster configuration to the given serial port. + + Args: + serial_port (str): Device path of the serial port (e.g., '/dev/ttyACM0') + preset (str): Preset string used in nac preset line + broadcast_names (list): List of names for each broadcast group + """ + cmds = [] + with serial.Serial(serial_port, 115200) as ser: + ser.write(f"nac stop".encode() + b'\r\n') + ser.write(f"nac clear".encode() + b'\r\n') + + time.sleep(.5) + + for ch, d in enumerate(broadcast_config.items()): + broadcast_name, file_name = d + + left_channel_file = file_name + right_channel_file = file_name + + cmds.append(f"nac preset {preset} {ch}") + cmds.append(f"nac broadcast_name {broadcast_name} {ch}") + cmds.append(f"nac file select_play_once {left_channel_file} {ch} 0 0") + cmds.append(f"nac file select_play_once {right_channel_file} {ch} 0 1") + + cmds.append(f"nac start") + + return cmds + +def broadcaster_config(): + serial_port = "/dev/ttyACM0" + broadcast_config = { + "broadcast1": "left24kHz_48kbps.lc3", + "broadcast2": "right-channel_24kHz_left_48kbps_10ms.lc3" + } + + #write_config_to_tty(serial_port, "24_2_1", broadcast_config) + # Example usage: + cmds = gen_broadcast_config_cmd(serial_port, "24_2_1", broadcast_config) + + for cmd in cmds: + ret = write_to_serial_read_respone(serial_port, cmd, timeout=0.1) + print("\n".join(ret)) + + ret = write_to_serial_read_respone(serial_port, "nac show", timeout=0.1) + print("\n".join(ret)) + + +if __name__ == "__main__": + broadcaster_config() + + + diff --git a/multilang_translator/backend_controller/broadcaster_play_once.py b/multilang_translator/backend_controller/broadcaster_play_once.py new file mode 100644 index 0000000..26d8a2c --- /dev/null +++ b/multilang_translator/backend_controller/broadcaster_play_once.py @@ -0,0 +1,23 @@ +#import broadcaster_config +from .broadcaster_config import write_to_serial_read_respone +import time + +def broadcaster_play_file(broadcast_ch, file): + serial_port = "/dev/ttyACM0" + ret = write_to_serial_read_respone(serial_port, f"nac file stream_close {broadcast_ch} 0 0", timeout=0.1) + print("\n".join(ret)) + + ret = write_to_serial_read_respone(serial_port, f"nac file select_play_once {file} {broadcast_ch} 0 0", timeout=0.1) + print("\n".join(ret)) + + +if __name__ == "__main__": + broadcast_ch = 0 + file = "left24kHz_48kbps.lc3" + broadcaster_play_file(broadcast_ch, file) + + time.sleep(1) + broadcast_ch = 1 + file = "right-channel_24kHz_left_48kbps_10ms.lc3" + + broadcaster_play_file(broadcast_ch, file) diff --git a/encode/encode_lc3.py b/multilang_translator/encode/encode_lc3.py similarity index 100% rename from encode/encode_lc3.py rename to multilang_translator/encode/encode_lc3.py diff --git a/main.py b/multilang_translator/main.py similarity index 83% rename from main.py rename to multilang_translator/main.py index e71a29b..0dfa84a 100644 --- a/main.py +++ b/multilang_translator/main.py @@ -16,6 +16,7 @@ from translator import llm_translator from encode import encode_lc3 ANNOUNCEMENT_DIR = os.path.join(os.path.dirname(__file__), 'announcements') +os.makedirs(ANNOUNCEMENT_DIR, exist_ok=True) def synthesize_resample_encode(text, tts_model, output_file): text_to_speech.synthesize(text, tts_model, output_file) @@ -23,16 +24,16 @@ def synthesize_resample_encode(text, tts_model, output_file): encode_lc3.encode_lc3(output_file) -def announcement_from_german_text(test_de): - synthesize_resample_encode(test_de, 'de_DE-kerstin-low', f'{ANNOUNCEMENT_DIR}/announcement_de.wav') +def announcement_from_german_text(text_de): + synthesize_resample_encode(text_de, 'de_DE-kerstin-low', f'{ANNOUNCEMENT_DIR}/announcement_de.wav') - text_en = llm_translator.translator_de_en(test_de) + text_en = llm_translator.translator_de_en(text_de) synthesize_resample_encode(text_en, 'en_US-lessac-medium', f'{ANNOUNCEMENT_DIR}/announcement_en.wav') - text_fr = llm_translator.translator_de_fr(test_de) + text_fr = llm_translator.translator_de_fr(text_de) synthesize_resample_encode(text_fr, 'fr_FR-siwis-medium', f'{ANNOUNCEMENT_DIR}/announcement_fr.wav') - text_fr = llm_translator.translator_de_es(test_de) + text_fr = llm_translator.translator_de_es(text_de) synthesize_resample_encode(text_fr, 'es_ES-sharvard-medium', f'{ANNOUNCEMENT_DIR}/announcement_fr.wav') # questions = [ diff --git a/test_content/test_content.py b/multilang_translator/test_content/test_content.py similarity index 100% rename from test_content/test_content.py rename to multilang_translator/test_content/test_content.py diff --git a/text_to_speech/piper_welcome.sh b/multilang_translator/text_to_speech/piper_welcome.sh similarity index 100% rename from text_to_speech/piper_welcome.sh rename to multilang_translator/text_to_speech/piper_welcome.sh diff --git a/text_to_speech/resample.py b/multilang_translator/text_to_speech/resample.py similarity index 100% rename from text_to_speech/resample.py rename to multilang_translator/text_to_speech/resample.py diff --git a/text_to_speech/text_to_speech.py b/multilang_translator/text_to_speech/text_to_speech.py similarity index 100% rename from text_to_speech/text_to_speech.py rename to multilang_translator/text_to_speech/text_to_speech.py diff --git a/text_to_speech/voices.json b/multilang_translator/text_to_speech/voices.json similarity index 100% rename from text_to_speech/voices.json rename to multilang_translator/text_to_speech/voices.json diff --git a/translator/__init__.py b/multilang_translator/translator/__init__.py similarity index 100% rename from translator/__init__.py rename to multilang_translator/translator/__init__.py diff --git a/translator/credentials.py b/multilang_translator/translator/credentials.py similarity index 100% rename from translator/credentials.py rename to multilang_translator/translator/credentials.py diff --git a/translator/llm_translator.py b/multilang_translator/translator/llm_translator.py similarity index 92% rename from translator/llm_translator.py rename to multilang_translator/translator/llm_translator.py index f400295..2ba4be0 100644 --- a/translator/llm_translator.py +++ b/multilang_translator/translator/llm_translator.py @@ -1,5 +1,7 @@ import requests import json +import logging as log +import time from . import credentials from . import syspromts @@ -13,7 +15,9 @@ def translate(model, query): 'model': model, 'messages': [{'role': 'user', 'content': query}], } + start = time.time() response = requests.post(url, headers=headers, json=payload) + log.info("Translating the text took %s s", round(time.time() - start, 2)) return response.json() diff --git a/translator/syspromts.py b/multilang_translator/translator/syspromts.py similarity index 100% rename from translator/syspromts.py rename to multilang_translator/translator/syspromts.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..9137bb5 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,12 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "multilang_translator" +version = '0.1' + +[tool.pytest.ini_options] +addopts = [ + "--import-mode=importlib", "-s", "-v" +] \ No newline at end of file diff --git a/readme.md b/readme.md index c79142c..eb24d73 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ sudo apt install liblc3-tools use python3.9 -pip install piper-tts soundfile librosa +pip install piper-tts soundfile librosa pyserial pytest # Piper update voices piper --update-voices -m en_US-lessac-medium diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_backend.py b/tests/test_backend.py new file mode 100644 index 0000000..e4f56db --- /dev/null +++ b/tests/test_backend.py @@ -0,0 +1,10 @@ +from multilang_translator.backend_controller.broadcaster_config import broadcaster_config +from multilang_translator.backend_controller.broadcaster_play_once import broadcaster_play_file + + +def test_config_broadcaster(): + broadcaster_config() + broadcaster_play_file(0, 'announcement_de.wav') + +def test_play_file(): + broadcaster_play_file(0, 'announcement_de.wav')