zeyadcode commited on
Commit
61a559c
·
verified ·
1 Parent(s): b7d3fbf

Sync from GitHub via hub-sync

Browse files
Files changed (4) hide show
  1. app.py +59 -4
  2. config/settings.py +0 -6
  3. index.py +0 -63
  4. requirements.txt +60 -63
app.py CHANGED
@@ -1,8 +1,63 @@
1
- from fastapi import FastAPI
 
 
 
 
 
 
 
 
2
 
 
3
  app = FastAPI()
4
 
 
5
  @app.get("/")
6
- async def root():
7
- return {"message": "Hello World"}
8
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io
2
+ import numpy as np
3
+ from scipy.io import wavfile
4
+ import librosa
5
+ from fastapi import Depends, FastAPI, File, UploadFile, HTTPException
6
+ from utils.audio_cleaning import denoise_audio, normalize_audio
7
+ from config.settings import Settings, get_settings
8
+ from config import constants
9
+ from groq import Groq
10
 
11
+ groq_client = Groq(api_key=get_settings().groq_secret_key)
12
  app = FastAPI()
13
 
14
+
15
  @app.get("/")
16
+ def root():
17
+ return {"status": "ok"}
18
+
19
+
20
+ @app.post("/transcribe")
21
+ async def process_and_transcribe(file: UploadFile = File(...)):
22
+ audio_bytes = await file.read()
23
+ print(f"File size: {len(audio_bytes)} bytes")
24
+ if len(audio_bytes) == 0:
25
+ raise HTTPException(400, "Empty file")
26
+
27
+ buffer = io.BytesIO(audio_bytes)
28
+ waveform, sr = librosa.load(buffer, sr=None)
29
+
30
+ cleaned_audio = denoise_audio(waveform, sr)
31
+ cleaned_audio = normalize_audio(cleaned_audio)
32
+
33
+ # prepare audio to be sent
34
+ audio_np = cleaned_audio.detach().cpu().numpy().squeeze()
35
+ audio_np = librosa.resample(audio_np, orig_sr=sr, target_sr=constants.GROQ_TARGET_SR)
36
+ audio_int16 = (audio_np * 32767).astype(np.int16)
37
+
38
+ export_buffer = io.BytesIO()
39
+ wavfile.write(export_buffer, constants.GROQ_TARGET_SR, audio_int16)
40
+ export_buffer.seek(0)
41
+
42
+ try:
43
+ transcription = groq_client.audio.transcriptions.create(
44
+ file=(file.filename, export_buffer.read()),
45
+ model=constants.GROQ_MODEL_NAME,
46
+ response_format="json",
47
+ language="en",
48
+ )
49
+ return {
50
+ "transcript": transcription.text,
51
+ "filename": file.filename,
52
+ "duration_seconds": round(len(waveform) / sr, 2),
53
+ }
54
+
55
+ except Exception as e:
56
+ print(f"Groq API Error: {e}")
57
+ raise HTTPException(500, f"Transcription failed: {str(e)}")
58
+
59
+
60
+ if __name__ == "__main__":
61
+ import uvicorn
62
+
63
+ uvicorn.run("index:app", host="127.0.0.1", port=8000, reload=True)
config/settings.py CHANGED
@@ -4,13 +4,7 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
4
 
5
  class Settings(BaseSettings):
6
  # Pydantic automatically finds CLERK_SECRET_KEY in your .env.local
7
- clerk_secret_key: str
8
- gemini_api_key: str
9
  groq_secret_key: str
10
- next_public_clerk_publishable_key: str
11
- smtp_password: str
12
- smtp_user: str
13
- vercel_oidc_token: str
14
 
15
  model_config = SettingsConfigDict(env_file=".env.local", env_file_encoding="utf-8")
16
 
 
4
 
5
  class Settings(BaseSettings):
6
  # Pydantic automatically finds CLERK_SECRET_KEY in your .env.local
 
 
7
  groq_secret_key: str
 
 
 
 
8
 
9
  model_config = SettingsConfigDict(env_file=".env.local", env_file_encoding="utf-8")
10
 
index.py DELETED
@@ -1,63 +0,0 @@
1
- import io
2
- import numpy as np
3
- from scipy.io import wavfile
4
- import librosa
5
- from fastapi import Depends, FastAPI, File, UploadFile, HTTPException
6
- from api.utils.audio_cleaning import denoise_audio, normalize_audio
7
- from api.config.settings import Settings, get_settings
8
- from api.config import constants
9
- from groq import Groq
10
-
11
- groq_client = Groq(api_key=get_settings().groq_secret_key)
12
- app = FastAPI()
13
-
14
-
15
- @app.get("/")
16
- def root():
17
- return {"status": "ok"}
18
-
19
-
20
- @app.post("/api/transcribe")
21
- async def process_and_transcribe(file: UploadFile = File(...)):
22
- audio_bytes = await file.read()
23
- print(f"File size: {len(audio_bytes)} bytes")
24
- if len(audio_bytes) == 0:
25
- raise HTTPException(400, "Empty file")
26
-
27
- buffer = io.BytesIO(audio_bytes)
28
- waveform, sr = librosa.load(buffer, sr=None)
29
-
30
- cleaned_audio = denoise_audio(waveform, sr)
31
- cleaned_audio = normalize_audio(cleaned_audio)
32
-
33
- # prepare audio to be sent
34
- audio_np = cleaned_audio.detach().cpu().numpy().squeeze()
35
- audio_np = librosa.resample(audio_np, orig_sr=sr, target_sr=constants.GROQ_TARGET_SR)
36
- audio_int16 = (audio_np * 32767).astype(np.int16)
37
-
38
- export_buffer = io.BytesIO()
39
- wavfile.write(export_buffer, constants.GROQ_TARGET_SR, audio_int16)
40
- export_buffer.seek(0)
41
-
42
- try:
43
- transcription = groq_client.audio.transcriptions.create(
44
- file=(file.filename, export_buffer.read()),
45
- model=constants.GROQ_MODEL_NAME,
46
- response_format="json",
47
- language="en",
48
- )
49
- return {
50
- "transcript": transcription.text,
51
- "filename": file.filename,
52
- "duration_seconds": round(len(waveform) / sr, 2),
53
- }
54
-
55
- except Exception as e:
56
- print(f"Groq API Error: {e}")
57
- raise HTTPException(500, f"Transcription failed: {str(e)}")
58
-
59
-
60
- if __name__ == "__main__":
61
- import uvicorn
62
-
63
- uvicorn.run("index:app", host="127.0.0.1", port=8000, reload=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,63 +1,60 @@
1
- # annotated-doc==0.0.4
2
- # annotated-types==0.7.0
3
- # anyio==4.13.0
4
- # appdirs==1.4.4
5
- # audioread==3.1.0
6
- # certifi==2026.4.22
7
- # cffi==2.0.0
8
- # charset-normalizer==3.4.7
9
- # click==8.3.3
10
- # DeepFilterLib==0.5.6
11
- # DeepFilterNet==0.5.6
12
- # distro==1.9.0
13
- # fastapi==0.136.1
14
- # filelock==3.29.0
15
- # fsspec==2026.4.0
16
- # git-filter-repo==2.47.0
17
- # groq==1.2.0
18
- # h11==0.16.0
19
- # httpcore==1.0.9
20
- # httpx==0.28.1
21
- # idna==3.15
22
- # intel-openmp==2021.4.0
23
- # Jinja2==3.1.6
24
- # joblib==1.5.3
25
- # lazy-loader==0.5
26
- # librosa==0.11.0
27
- # llvmlite==0.47.0
28
- # loguru==0.7.3
29
- # MarkupSafe==3.0.3
30
- # mkl==2021.4.0
31
- # mpmath==1.3.0
32
- # msgpack==1.1.2
33
- # networkx==3.4.2
34
- # numba==0.65.1
35
- # numpy==1.26.4
36
- # packaging==23.2
37
- # pillow==12.2.0
38
- # pooch==1.9.0
39
- # pycparser==3.0
40
- # pydantic==2.13.4
41
- # pydantic-settings==2.14.1
42
- # pydantic_core==2.46.4
43
- # python-dotenv==1.2.2
44
- # python-multipart==0.0.28
45
- # requests==2.34.2
46
- # scikit-learn==1.7.2
47
- # scipy==1.15.3
48
- # sniffio==1.3.1
49
- # soundfile==0.13.1
50
- # soxr==1.1.0
51
- # starlette==1.0.0
52
- # sympy==1.14.0
53
- # tbb==2021.13.1
54
- # threadpoolctl==3.6.0
55
- # torch==2.3.0
56
- # torchaudio==2.3.0
57
- # torchvision==0.18.0
58
- # typing-inspection==0.4.2
59
- # urllib3==2.7.0
60
- # uvicorn==0.47.0
61
-
62
- uvicorn
63
- fastapi
 
1
+ annotated-doc==0.0.4
2
+ annotated-types==0.7.0
3
+ anyio==4.13.0
4
+ appdirs==1.4.4
5
+ audioread==3.1.0
6
+ certifi==2026.4.22
7
+ cffi==2.0.0
8
+ charset-normalizer==3.4.7
9
+ click==8.3.3
10
+ DeepFilterLib==0.5.6
11
+ DeepFilterNet==0.5.6
12
+ distro==1.9.0
13
+ fastapi==0.136.1
14
+ filelock==3.29.0
15
+ fsspec==2026.4.0
16
+ git-filter-repo==2.47.0
17
+ groq==1.2.0
18
+ h11==0.16.0
19
+ httpcore==1.0.9
20
+ httpx==0.28.1
21
+ idna==3.15
22
+ intel-openmp==2021.4.0
23
+ Jinja2==3.1.6
24
+ joblib==1.5.3
25
+ lazy-loader==0.5
26
+ librosa==0.11.0
27
+ llvmlite==0.47.0
28
+ loguru==0.7.3
29
+ MarkupSafe==3.0.3
30
+ mkl==2021.4.0
31
+ mpmath==1.3.0
32
+ msgpack==1.1.2
33
+ networkx==3.4.2
34
+ numba==0.65.1
35
+ numpy==1.26.4
36
+ packaging==23.2
37
+ pillow==12.2.0
38
+ pooch==1.9.0
39
+ pycparser==3.0
40
+ pydantic==2.13.4
41
+ pydantic-settings==2.14.1
42
+ pydantic_core==2.46.4
43
+ python-dotenv==1.2.2
44
+ python-multipart==0.0.28
45
+ requests==2.34.2
46
+ scikit-learn==1.7.2
47
+ scipy==1.15.3
48
+ sniffio==1.3.1
49
+ soundfile==0.13.1
50
+ soxr==1.1.0
51
+ starlette==1.0.0
52
+ sympy==1.14.0
53
+ tbb==2021.13.1
54
+ threadpoolctl==3.6.0
55
+ torch==2.3.0
56
+ torchaudio==2.3.0
57
+ torchvision==0.18.0
58
+ typing-inspection==0.4.2
59
+ urllib3==2.7.0
60
+ uvicorn==0.47.0