Skip to content

Commit

Permalink
start cleanning
Browse files Browse the repository at this point in the history
  • Loading branch information
guillaume-chervet committed Oct 31, 2024
1 parent 77148de commit 7dbdf83
Show file tree
Hide file tree
Showing 6 changed files with 8 additions and 140 deletions.
10 changes: 5 additions & 5 deletions deploy/kubernetes/api-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ spec:
value: "production"
resources:
limits:
memory: "2000Mi"
cpu: "1000m"
memory: "240Mi"
cpu: "200m"
requests:
ephemeral-storage: "1000Mi"
memory: "2000Mi"
cpu: "1000m"
ephemeral-storage: "100Mi"
memory: "240Mi"
cpu: "200m"
30 changes: 0 additions & 30 deletions production/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
# Première étape : Construire l'environnement avec les dépendances nécessaires
FROM python:3.11-slim AS build

# Mettre à jour les paquets et installer les dépendances requises
RUN apt-get update && \
apt-get install -y --no-install-recommends \
wget \
curl \
ca-certificates \
gnupg \
lsb-release \
software-properties-common

# Ajouter le dépôt LLVM pour obtenir la version la plus récente
RUN echo "deb http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm main" > /etc/apt/sources.list.d/llvm.list && \
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
apt-get update && \
apt-get install -y llvm

# Installer Poetry
ENV POETRY_VERSION=1.8.4
RUN pip install "poetry==${POETRY_VERSION}"
Expand All @@ -30,26 +14,12 @@ COPY . /app
# Installer les dépendances sans les dev packages
RUN poetry config virtualenvs.create false && poetry install --no-root --only main

# Stocker les chemins des binaires dans des fichiers temporaires
RUN which llvm-config > /llvm_path

# Deuxième étape : Construire l'image finale allégée
FROM python:3.11-slim

# Créer l'utilisateur non-root
RUN useradd -ms /bin/bash appuser

# Copier les chemins des binaires stockés dans des fichiers temporaires
COPY --from=build /llvm_path /tmp/

# Charger les chemins des binaires depuis les fichiers temporaires en utilisant RUN pour définir les variables d’environnement
RUN export LLVM_PATH=$(cat /tmp/llvm_path)

COPY $LLVM_PATH /usr/local/bin/llvm-config

# Install ffmpeg
RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg

# Copier les packages Python installés
COPY --from=build /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages

Expand Down
95 changes: 1 addition & 94 deletions production/api/app/main.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import asyncio
import json
import uuid

from fastapi import FastAPI, UploadFile, File, Form, Request
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
import whisper
import ffmpeg
import io
import torchaudio
from pydantic import BaseModel

app = FastAPI()
Expand All @@ -26,102 +21,14 @@
allow_headers=["*"],
)

# Charger le modèle Whisper
model = whisper.load_model("small")

# Stocker les messages SSE par client
clients = {}

# Créer une file d'attente pour les tâches de transcription
transcription_queue = asyncio.Queue()

class Transcript(BaseModel):
message:str
chunk_index: int
client_id:str

@app.post("/audio")
async def receive_audio_chunk(
audio_chunk: UploadFile = File(...),
chunk_index: int = Form(...),
client_id: str = Form(...)
):
if client_id not in clients:
clients[client_id] = {
"sse_messages": []
}

content = await audio_chunk.read()

# Placer le chunk dans la file d'attente de transcription
await transcription_queue.put((client_id, content, chunk_index))

return {"status": "Chunk received"}


async def transcription_worker():
while True:
client_id, content, chunk_index = await transcription_queue.get()
await transcribe_audio(client_id, content, chunk_index)
transcription_queue.task_done()
await asyncio.sleep(0.1)


@app.on_event("startup")
async def startup_event():
# Démarrer le worker de transcription en arrière-plan
asyncio.create_task(transcription_worker())


async def transcribe_audio(client_id, chunk_data, chunk_index):
try:
# Convertir le chunk en WAV
input_stream = io.BytesIO(chunk_data)
input_data = input_stream.read()

loop = asyncio.get_event_loop()
# Exécuter ffmpeg avec les paramètres appropriés dans un exécuteur
out, err = await loop.run_in_executor(None, lambda: (
ffmpeg
.input('pipe:0')
.output('pipe:1', format='wav', acodec='pcm_s16le', ac=1, ar='16k')
.run(input=input_data, capture_stdout=True, capture_stderr=True, overwrite_output=True)
))

# Placer les données de sortie dans un flux BytesIO
output_stream = io.BytesIO(out)
output_stream.seek(0)

# Lire les données audio à partir du flux BytesIO
waveform, sample_rate = torchaudio.load(output_stream)

# Si nécessaire, rééchantillonner à 16000 Hz
if sample_rate != 16000:
resampler = torchaudio.transforms.Resample(orig_freq=sample_rate, new_freq=16000)
waveform = resampler(waveform)

# Convertir le tenseur en tableau NumPy
audio_data = waveform.numpy().flatten()

# Transcrire l'audio dans un exécuteur
result = await loop.run_in_executor(None, lambda: model.transcribe(audio_data, fp16=False, language="fr"))

# Envoyer la transcription via SSE en incluant chunk_index
data = {
"transcript": result['text'],
"chunk_index": chunk_index
}
message = f"data: {json.dumps(data)}\n\n"
print(f"Transcription: {message}")
await send_sse_message(client_id, message)

except Exception as e:
print(f"Erreur lors de la transcription : {e}")
# Impression de la stacktrace complète
import traceback
traceback.print_exc()


async def send_sse_message(client_id, message):
if client_id in clients:
clients[client_id]["sse_messages"].append(message)
Expand Down Expand Up @@ -177,7 +84,7 @@ async def receive_transcript(transcript: Transcript):
return {"status": "Transcript received"}


@app.post("/audio-queue")
@app.post("/audio")
async def receive_audio_chunk(
audio_chunk: UploadFile = File(...),
chunk_index: int = Form(...),
Expand Down
9 changes: 0 additions & 9 deletions production/api/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,7 @@ python = "^3.11"
fastapi = "^0.115.3"
uvicorn = "^0.32.0"
starlette = "^0.41.0"
torch = "^2.5.0"
ffmpeg-python = "^0.2.0"
aiofiles = "^24.1.0"
llvmlite = "0.43.0"
numba = "0.60.0"
openai-whisper = "^20240930"
python-multipart = "^0.0.12"
soundfile = "^0.12.1"
librosa = "^0.10.2.post1"
torchaudio = "^2.5.0"
redis = "^5.2.0"
httpx = "^0.27.2"
msgpack = "^1.1.0"
Expand Down
2 changes: 1 addition & 1 deletion production/webapp/src/AudioRecorder.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class AudioRecorder {
this.onError = options.onError || function() {};
this.silenceDelay = options.silenceDelay || 200;
this.speechThreshold = options.speechThreshold || 10;
this.silenceThreshold = options.silenceThreshold || 2;
this.silenceThreshold = options.silenceThreshold || 4;

// Nouvelle propriété pour contrôler la détection de la parole
this.isDetectingSpeech = false;
Expand Down
2 changes: 1 addition & 1 deletion production/webapp/src/AudioRecorderComponent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const sendAudioChunk= (baseUrl) => (chunk, clientId, chunkIndex) => {
formData.append('chunk_index', chunkIndex);
formData.append('client_id', clientId);

fetch(`${baseUrl}/audio-queue`, {
fetch(`${baseUrl}/audio`, {
method: 'POST',
body: formData,
})
Expand Down

0 comments on commit 7dbdf83

Please sign in to comment.