Add LibreTranslate module, add separate envs for it in Makefile
This commit is contained in:
39
Makefile
39
Makefile
@@ -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 $@ $^
|
||||||
|
3
libretranslate_requirements.txt
Normal file
3
libretranslate_requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
libretranslate
|
||||||
|
torch==2.2.0
|
||||||
|
|
55
main.py
55
main.py
@@ -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.
|
||||||
|
Reference in New Issue
Block a user