drrobot9 commited on
Commit
6153b5e
·
verified ·
1 Parent(s): baffd5e

AI test version super initial commit

Browse files
Dockerfile ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /code
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY app/ ./app
9
+
10
+ WORKDIR /code/app
11
+
12
+ EXPOSE 7860
13
+
14
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
app/__pycache__/config.cpython-312.pyc ADDED
Binary file (866 Bytes). View file
 
app/__pycache__/main.cpython-312.pyc ADDED
Binary file (2.87 kB). View file
 
app/__pycache__/voice_languag_detector.cpython-312.pyc ADDED
Binary file (2.11 kB). View file
 
app/config.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dataclasses import dataclass, field
3
+ from typing import Dict
4
+
5
+
6
+
7
+
8
+ ELEVENLABS_API_KEY = "ELEVENLABS_API_KEY"
9
+
10
+ ELEVENLABS_BASE_URL = "https://api.elevenlabs.io/v1"
11
+
12
+
13
+ MODEL_ID = "eleven_v3"
14
+
15
+
16
+ VOICE_IDS = {
17
+ "ig": "QLniWkGYsJa91mXrxl3c", # Igbo
18
+ "yo": "x86DtpnPPuq2BpEiKPRy", # Yoruba
19
+ "ha": "65blg8G9v7ZRWectRxK8", # Hausa
20
+ "en": "65blg8G9v7ZRWectRxK8", # English
21
+ }
22
+
23
+ DEFAULT_LANGUAGE = "en"
24
+
25
+
26
+ CONFIDENCE_THRESHOLD = 0.5
27
+
28
+ FASTTEXT_REPO_ID = "facebook/fasttext-language-identification"
29
+ FASTTEXT_FILENAME = "model.bin"
30
+
31
+ LABEL_TO_VOICE = {
32
+ "ibo_Latn": "ig",
33
+ "yor_Latn": "yo",
34
+ "hau_Latn": "ha",
35
+ "eng_Latn": "en",
36
+ }
app/main.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ from fastapi import FastAPI, HTTPException
4
+ from fastapi.responses import Response
5
+ from pydantic import BaseModel
6
+
7
+ from app.config import (
8
+ ELEVENLABS_API_KEY,
9
+ ELEVENLABS_BASE_URL,
10
+ MODEL_ID,
11
+ VOICE_IDS,
12
+ DEFAULT_LANGUAGE,
13
+ )
14
+
15
+ from app.voice_languag_detector import detect_language
16
+
17
+ app = FastAPI(title="Africa TTS - Auto Language Voice Cloning")
18
+
19
+
20
+ class TTSRequest(BaseModel):
21
+ text: str
22
+ stability: float = 0.5
23
+ similarity_boost: float = 0.75
24
+
25
+
26
+ @app.get("/")
27
+ def root():
28
+ return {"status": "ok", "message": "Africa TTS API is running"}
29
+
30
+
31
+ @app.post("/tts")
32
+ def text_to_speech(request: TTSRequest):
33
+ if not request.text or not request.text.strip():
34
+ raise HTTPException(status_code=400, detail="Text cannot be empty")
35
+
36
+ if not ELEVENLABS_API_KEY:
37
+ raise HTTPException(status_code=500, detail="ELEVENLABS_API_KEY not set")
38
+
39
+ lang_code, confidence = detect_language(request.text)
40
+ voice_id = VOICE_IDS.get(lang_code, VOICE_IDS[DEFAULT_LANGUAGE])
41
+
42
+ url = f"{ELEVENLABS_BASE_URL}/text-to-speech/{voice_id}"
43
+
44
+ headers = {
45
+ "xi-api-key": ELEVENLABS_API_KEY,
46
+ "Content-Type": "application/json",
47
+ "Accept": "audio/mpeg",
48
+ }
49
+
50
+ payload = {
51
+ "text": request.text,
52
+ "model_id": MODEL_ID,
53
+ "voice_settings": {
54
+ "stability": request.stability,
55
+ "similarity_boost": request.similarity_boost,
56
+ },
57
+ }
58
+
59
+ response = requests.post(url, json=payload, headers=headers)
60
+
61
+ if response.status_code != 200:
62
+ raise HTTPException(
63
+ status_code=response.status_code,
64
+ detail=f"ElevenLabs API error: {response.text}",
65
+ )
66
+
67
+ return Response(
68
+ content = response.content,
69
+ media_type = "audio/mpeg",
70
+ headers = {
71
+ "X-Detected-Language": lang_code,
72
+ "X-Detection-confidence": str(round(confidence,4)),
73
+ "X-Voice-Id-Used": voice_id,
74
+ }
75
+ )
app/voice_languag_detector.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fasttext
2
+ from huggingface_hub import hf_hub_download
3
+
4
+ from app.config import (
5
+ FASTTEXT_REPO_ID,
6
+ FASTTEXT_FILENAME,
7
+ CONFIDENCE_THRESHOLD,
8
+ DEFAULT_LANGUAGE,
9
+ LABEL_TO_VOICE,
10
+ )
11
+
12
+ fasttext.FastText.eprint = lambda x: None # silence warnings
13
+
14
+
15
+ class LanguageDetector:
16
+ def __init__(self):
17
+ model_path = hf_hub_download(
18
+ repo_id=FASTTEXT_REPO_ID,
19
+ filename=FASTTEXT_FILENAME,
20
+ )
21
+ self.model = fasttext.load_model(model_path)
22
+
23
+ def detect(self, text: str):
24
+ clean_text = text.replace("\n", " ").strip()
25
+ if not clean_text:
26
+ return DEFAULT_LANGUAGE, 0.0
27
+
28
+ labels, confidences = self.model.predict(clean_text, k=1)
29
+ raw_label = labels[0].replace("__label__", "")
30
+ confidence = float(confidences[0])
31
+
32
+ lang_code = LABEL_TO_VOICE.get(raw_label)
33
+
34
+ if lang_code is not None and confidence >= CONFIDENCE_THRESHOLD:
35
+ return lang_code, confidence
36
+
37
+ return DEFAULT_LANGUAGE, confidence
38
+
39
+
40
+ detector = LanguageDetector()
41
+
42
+
43
+ def detect_language(text: str):
44
+ """Returns (lang_code, confidence)"""
45
+ return detector.detect(text)
classifier_model/voice_language_detector.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import urllib.request
3
+ import fasttext
4
+
5
+ from app.config import config
6
+
7
+
8
+
9
+ fasttext.FastText.eprint = lambda x: None
10
+
11
+
12
+ class LanguageDetector:
13
+ def __init__(self):
14
+ if not os.path.exists(FASTTEXT_MODEL_PATH):
15
+ print("Downloading fastText language ID model")
16
+ urllib.request.urlretrieve(FASTTEXT_MODEL_URL, FASTTEXT_MODEL_PATH)
17
+ self.model = fasttext.load_model(FASTTEXT_MODEL_PATH)
18
+
19
+ def detect(self, text: str):
20
+ clean_text = text.replace("\n", " ").strip()
21
+ if not clean_text:
22
+ return DEFAULT_LANGUAGE, 0.0
23
+
24
+ labels, confidences = self.model.predict(clean_text, k=1)
25
+ lang_code = labels[0].replace("__label__", "")
26
+ confidence = float(confidences[0])
27
+
28
+
29
+ if lang_code in VOICE_IDS and confidence >= CONFIDENCE_THRESHOLD:
30
+ return lang_code, confidence
31
+
32
+ return DEFAULT_LANGUAGE, confidence
33
+
34
+
35
+
36
+ detector = LanguageDetector()
37
+
38
+
39
+ def detect_language(text: str):
40
+ """Returns (lang_code, confidence)"""
41
+ return detector.detect(text)
lid.176.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7e69ec5451bc261cc7844e49e4792a85d7f09c06789ec800fc4a44aec362764e
3
+ size 131266198
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ requests
4
+ fasttext-wheel
5
+ pydantic
6
+ numpy<2