Add LibreTranslate module, add separate envs for it in Makefile

This commit is contained in:
2025-05-04 14:51:39 +02:00
parent 194fd2adea
commit 0b33dc19e7
3 changed files with 90 additions and 7 deletions

View File

@@ -3,9 +3,29 @@ default: run
include client/make.mk include client/make.mk
LIBRETRANSLATE_PYTHON_VERSION = 3.10.12
ifeq ($(shell command -v pyenv 2> /dev/null),)
HAS_PYENV = false
else
HAS_PYENV = true
endif
.PHONY: setup
setup: setup_pyenv setup_venvs
.PHONY: setup_pyenv
setup_pyenv:
ifeq ($(HAS_PYENV),true)
pyenv install -s $(LIBRETRANSLATE_PYTHON_VERSION)
endif
.PHONY: setup_venvs
setup_venvs: venv libretranslate_venv
.PHONY: run .PHONY: run
run: $(CLIENT_TARGETS) venv run: $(CLIENT_TARGETS) venv
source venv/bin/activate && python main.py . venv/bin/activate && python main.py
.PHONY: build .PHONY: build
build: $(CLIENT_TARGETS) build: $(CLIENT_TARGETS)
@@ -18,13 +38,26 @@ test: client_test
.PHONY: clean .PHONY: clean
clean: client_clean clean: client_clean
rm -rf __pycache__ rm -rf **pycache**
rm -rf venv rm -rf venv
rm -rf libretranslate_venv
rm -f pythagoras.tar.xz rm -f pythagoras.tar.xz
venv: venv:
python -m venv venv python -m venv venv
source venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt . venv/bin/activate && pip install --upgrade pip && pip install -r requirements.txt
libretranslate_venv:
ifeq ($(HAS_PYENV),true)
PYENV_VERSION=$(LIBRETRANSLATE_PYTHON_VERSION) pyenv exec python -m venv libretranslate_venv
else
@exit 1
endif
. libretranslate_venv/bin/activate && pip install --upgrade pip && pip install -r libretranslate_requirements.txt
.PHONY: start_libretranslate
start_libretranslate: libretranslate_venv
. libretranslate_venv/bin/activate && libretranslate --port 5000 --load-only en,cs
pythagoras.tar.xz: main.py $(CLIENT_TARGETS) pythagoras.tar.xz: main.py $(CLIENT_TARGETS)
tar --transform='s|^|pythagoras/|' -Jcvf $@ $^ tar --transform='s|^|pythagoras/|' -Jcvf $@ $^

View File

@@ -0,0 +1,3 @@
libretranslate
torch==2.2.0

55
main.py
View File

@@ -26,6 +26,7 @@ logger = logging.getLogger("pythagoras")
app = FastAPI(title="Pythagoras", description="A proxy service handling HTTP and WebSocket connections") app = FastAPI(title="Pythagoras", description="A proxy service handling HTTP and WebSocket connections")
app.state.auto_polling = False app.state.auto_polling = False
app.state.polling_rate = 5 app.state.polling_rate = 5
app.state.enable_libretranslate = True
# Define the media directory # Define the media directory
MEDIA_DIR = Path("./media") MEDIA_DIR = Path("./media")
@@ -115,6 +116,11 @@ async def control_endpoint(request: Request):
app.state.auto_polling = new_state app.state.auto_polling = new_state
logger.info(f"Polling command issued, changing auto-polling to {new_state}") logger.info(f"Polling command issued, changing auto-polling to {new_state}")
elif data['command'] == "setlibretranslate" and 'state' in data:
new_state = data['state']
app.state.auto_polling = new_state
logger.info(f"LibreTranslate command issued, changing state to {new_state}")
elif data['command'] == "autopollingrate" and 'rate' in data: elif data['command'] == "autopollingrate" and 'rate' in data:
new_rate = data['rate'] new_rate = data['rate']
app.state.polling_rate = new_rate app.state.polling_rate = new_rate
@@ -184,12 +190,16 @@ async def get_media(file_path: str):
async def process_subtitles(request: Request, sub_type: str): async def process_subtitles(request: Request, sub_type: str):
try: try:
text_content = await request.body() text_content = await request.body()
subtitle_text = text_content.decode("utf-8") en_subtitle_text = text_content.decode("utf-8")
logger.info(f"Received subtitle text: {subtitle_text}, request type: {sub_type}") logger.info(f"Received subtitle text: {en_subtitle_text}, request type: {sub_type}")
if manager.active_connections: if manager.active_connections:
await manager.broadcast_binary({"type": f"subtitle_{sub_type}", "text": subtitle_text}) await manager.broadcast_binary({"type": f"subtitle_en_{sub_type}", "text": en_subtitle_text})
if app.state.enable_libretranslate and sub_type == "submit_sentence":
cs_subtitle_text = await translate_to_cs_libre(en_subtitle_text)
await manager.broadcast_binary({"type": f"subtitle_cs_{sub_type}", "text": cs_subtitle_text})
return JSONResponse( return JSONResponse(
status_code=200, status_code=200,
content={"status": "success", "message": "Subtitle text received"} content={"status": "success", "message": "Subtitle text received"}
@@ -201,6 +211,43 @@ async def process_subtitles(request: Request, sub_type: str):
content={"status": "error", "message": f"Failed to process request."} content={"status": "error", "message": f"Failed to process request."}
) )
async def translate_to_cs_libre(text: str):
"""
Translates the provided text from English to Czech using LibreTranslate.
"""
if not text:
return text
try:
url = "http://localhost:5000/translate"
payload = {
"q": text,
"source": "en",
"target": "cs",
"format": "text"
}
timeout = httpx.Timeout(10.0)
async with httpx.AsyncClient(timeout=timeout) as client:
response = await client.post(url, json=payload)
if response.status_code == 200:
result = response.json()
translated_text = result.get("translatedText", text)
logger.info(f"Successfully translated text to Czech")
return translated_text
else:
logger.error(f"Translation API error: {response.status_code}, {response.text}")
return text
except Exception as e:
logger.error(f"Translation error: {str(e)}")
return text
async def fetch_selected_message(): async def fetch_selected_message():
""" """
Fetches a selected message from the specified endpoint. Fetches a selected message from the specified endpoint.