Ved Gupta commited on
Commit
022e710
·
1 Parent(s): 8f082c1

Updated v3

Browse files
app/api/endpoints/transcribe.py CHANGED
@@ -1,11 +1,17 @@
1
  from typing import Annotated, List, Union
2
 
3
  from fastapi import APIRouter, File, UploadFile, Request, Header, HTTPException
 
4
  from pydantic import BaseModel
5
 
6
- from app.utils.utils import save_audio_file, transcribeFile
 
 
 
 
7
 
8
  router = APIRouter()
 
9
 
10
 
11
  class Transcription(BaseModel):
@@ -15,16 +21,24 @@ class Transcription(BaseModel):
15
 
16
  @router.post("/", response_model=Transcription)
17
  async def post_audio(
 
18
  request: Request,
19
  file: UploadFile = File(...),
20
  Authentication: Annotated[Union[str, None], Header()] = None,
21
  ):
22
- print(f"Authorization header: {Authentication}")
23
-
24
  try:
25
- """Receive audio file and save it to disk. and then transcribe the audio file"""
26
  file_path = save_audio_file(file)
27
- data = transcribeFile(file_path)
 
 
 
 
28
  return Transcription(filename=file.filename, text=data)
29
  except Exception as e:
30
  raise HTTPException(status_code=400, detail=e.__str__())
 
 
 
 
 
 
1
  from typing import Annotated, List, Union
2
 
3
  from fastapi import APIRouter, File, UploadFile, Request, Header, HTTPException
4
+ from fastapi.background import BackgroundTasks
5
  from pydantic import BaseModel
6
 
7
+ from app.core.database import SessionLocal
8
+
9
+ from app.utils.utils import save_audio_file, transcribe_file, get_audio_duration
10
+ from app.core.models import AuthTokenController, TranscribeController
11
+
12
 
13
  router = APIRouter()
14
+ database = SessionLocal()
15
 
16
 
17
  class Transcription(BaseModel):
 
21
 
22
  @router.post("/", response_model=Transcription)
23
  async def post_audio(
24
+ background_tasks: BackgroundTasks,
25
  request: Request,
26
  file: UploadFile = File(...),
27
  Authentication: Annotated[Union[str, None], Header()] = None,
28
  ):
 
 
29
  try:
30
+ userId = AuthTokenController(database).get_userid_from_token(Authentication)
31
  file_path = save_audio_file(file)
32
+ [data, output_audio_path] = transcribe_file(file_path)
33
+ background_tasks.add_task(
34
+ create_transcribe_record, database, userId, data, output_audio_path
35
+ )
36
+
37
  return Transcription(filename=file.filename, text=data)
38
  except Exception as e:
39
  raise HTTPException(status_code=400, detail=e.__str__())
40
+
41
+
42
+ def create_transcribe_record(database, userId, data, file_path):
43
+ duration = get_audio_duration(file_path)
44
+ TranscribeController(database).create(user_id=userId, text=data, duration=duration)
app/core/models/AuthToken.py CHANGED
@@ -1,4 +1,3 @@
1
- from datetime import datetime, timedelta
2
  import uuid
3
  import random
4
  import string
@@ -7,6 +6,8 @@ from app.core.config import settings
7
 
8
  from sqlalchemy.dialects.postgresql import UUID
9
  from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
 
 
10
  from sqlalchemy.sql import func
11
 
12
  from app.core.database import Base
@@ -19,10 +20,35 @@ class AuthToken(Base):
19
  token = Column(String, unique=True, index=True)
20
  user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
21
  created_at = Column(DateTime(timezone=True), server_default=func.now())
 
 
 
 
 
 
22
 
23
- def __init__(self, user_id: UUID):
 
 
 
 
 
 
 
 
 
 
 
 
24
  self.user_id = user_id
25
  self.token = self.create_token()
 
 
 
 
 
 
 
26
 
27
  def create_token(self):
28
  token = self.generate_bearer_token()
 
 
1
  import uuid
2
  import random
3
  import string
 
6
 
7
  from sqlalchemy.dialects.postgresql import UUID
8
  from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
9
+ from sqlalchemy.orm import relationship
10
+
11
  from sqlalchemy.sql import func
12
 
13
  from app.core.database import Base
 
20
  token = Column(String, unique=True, index=True)
21
  user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
22
  created_at = Column(DateTime(timezone=True), server_default=func.now())
23
+ user = relationship("UserInDB", back_populates="auth_tokens")
24
+
25
+ def __init__(self, user_id: UUID, token: str):
26
+ self.user_id = user_id
27
+ self.token = token
28
+
29
 
30
+ class AuthTokenController:
31
+ AuthToken = AuthToken
32
+
33
+ def __init__(self, database):
34
+ self.db = database
35
+
36
+ def get_userid_from_token(self, token) -> str:
37
+ user = self.db.query(AuthToken).filter(AuthToken.token == token).first()
38
+ if not user:
39
+ raise Exception("Invalid Token!")
40
+ return user.user_id
41
+
42
+ def create(self, user_id: UUID):
43
  self.user_id = user_id
44
  self.token = self.create_token()
45
+ self.auth_token = AuthToken(self.user_id, self.token)
46
+ self.db.add(self.auth_token)
47
+ self.db.commit()
48
+ self.db.refresh(self.auth_token)
49
+
50
+ def get_token(self):
51
+ return self.auth_token.token
52
 
53
  def create_token(self):
54
  token = self.generate_bearer_token()
app/core/models/Transcribe.py CHANGED
@@ -4,7 +4,7 @@ import uuid
4
  from app.core.config import settings
5
 
6
  from sqlalchemy.dialects.postgresql import UUID
7
- from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
8
  from sqlalchemy.orm import Mapped, mapped_column, relationship
9
  from sqlalchemy.sql import func
10
 
@@ -16,6 +16,30 @@ class TranscibeInDB(Base):
16
 
17
  id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
18
  text = Column(String)
 
19
  user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
20
  user = relationship("UserInDB", back_populates="transcribes")
21
  created_at = Column(DateTime(timezone=True), server_default=func.now())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from app.core.config import settings
5
 
6
  from sqlalchemy.dialects.postgresql import UUID
7
+ from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime, Integer
8
  from sqlalchemy.orm import Mapped, mapped_column, relationship
9
  from sqlalchemy.sql import func
10
 
 
16
 
17
  id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
18
  text = Column(String)
19
+ audio_duration = Column(Integer)
20
  user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
21
  user = relationship("UserInDB", back_populates="transcribes")
22
  created_at = Column(DateTime(timezone=True), server_default=func.now())
23
+
24
+ def __init__(self, user_id, text, audio_duration):
25
+ self.text = text
26
+ self.audio_duration = audio_duration
27
+ self.user_id = user_id
28
+
29
+
30
+ class TranscribeController:
31
+ TranscibeInDB = TranscibeInDB
32
+
33
+ def __init__(self, database):
34
+ self.db = database
35
+
36
+ def create(self, user_id: UUID, text: str, duration: int):
37
+ self.user_id = user_id
38
+ self.text = text
39
+ self.audio_duration = duration
40
+ self.transcribe_data = TranscibeInDB(
41
+ user_id=self.user_id, text=self.text, audio_duration=self.audio_duration
42
+ )
43
+ self.db.add(self.transcribe_data)
44
+ self.db.commit()
45
+ self.db.refresh(self.transcribe_data)
app/core/models/User.py CHANGED
@@ -1,6 +1,5 @@
1
  import uuid
2
 
3
-
4
  from app.core.config import settings
5
 
6
  from sqlalchemy.dialects.postgresql import UUID
@@ -12,6 +11,8 @@ from app.core.database import Base
12
 
13
  from app.core.security import get_password_hash, verify_password
14
 
 
 
15
 
16
  class UserInDB(Base):
17
  __tablename__ = "users"
@@ -22,6 +23,7 @@ class UserInDB(Base):
22
  hashed_password = Column(String)
23
  is_active = Column(Boolean, default=True)
24
  transcribes = relationship("TranscibeInDB", back_populates="user")
 
25
  created_at = Column(DateTime(timezone=True), server_default=func.now())
26
 
27
  def __init__(self, username: str, email: str, hashed_password: str):
@@ -44,7 +46,7 @@ class UserController:
44
  def __init__(self, database):
45
  self.db = database
46
 
47
- def create(self, username: str, email: str, password: str):
48
  isUserExists: Boolean = self.CheckUserIsExistsByEmailAndUsername(
49
  email, username
50
  )
@@ -65,6 +67,10 @@ class UserController:
65
  self.db.refresh(self.db_user)
66
  self.user = self.db_user.data()
67
 
 
 
 
 
68
  def CheckUserIsExistsByEmailAndUsername(self, email: str, username: str):
69
  db_user = (
70
  self.db.query(UserInDB)
 
1
  import uuid
2
 
 
3
  from app.core.config import settings
4
 
5
  from sqlalchemy.dialects.postgresql import UUID
 
11
 
12
  from app.core.security import get_password_hash, verify_password
13
 
14
+ from app.core.models import AuthTokenController
15
+
16
 
17
  class UserInDB(Base):
18
  __tablename__ = "users"
 
23
  hashed_password = Column(String)
24
  is_active = Column(Boolean, default=True)
25
  transcribes = relationship("TranscibeInDB", back_populates="user")
26
+ auth_tokens = relationship("AuthToken", back_populates="user")
27
  created_at = Column(DateTime(timezone=True), server_default=func.now())
28
 
29
  def __init__(self, username: str, email: str, hashed_password: str):
 
46
  def __init__(self, database):
47
  self.db = database
48
 
49
+ def create(self, username: str, email: str, password: str, init_token: bool = True):
50
  isUserExists: Boolean = self.CheckUserIsExistsByEmailAndUsername(
51
  email, username
52
  )
 
67
  self.db.refresh(self.db_user)
68
  self.user = self.db_user.data()
69
 
70
+ if init_token == False:
71
+ return
72
+ AuthTokenController(self.db).create(self.db_user.id)
73
+
74
  def CheckUserIsExistsByEmailAndUsername(self, email: str, username: str):
75
  db_user = (
76
  self.db.query(UserInDB)
app/core/models/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
- from .AuthToken import AuthToken
2
  from .User import UserInDB
3
- from .Transcribe import TranscibeInDB
4
 
5
  from app.core.database import Base, engine
6
 
 
1
+ from .AuthToken import AuthToken, AuthTokenController
2
  from .User import UserInDB
3
+ from .Transcribe import TranscibeInDB, TranscribeController
4
 
5
  from app.core.database import Base, engine
6
 
app/utils/utils.py CHANGED
@@ -2,6 +2,7 @@ import json
2
  import subprocess
3
  import uuid
4
  import logging
 
5
 
6
 
7
  def get_all_routes(app):
@@ -33,18 +34,20 @@ def print_routes(app):
33
  print("\n")
34
 
35
 
36
- def transcribeFile(path: str = None, model="ggml-model-whisper-tiny.en-q5_1.bin"):
37
- """./binary/whisper -m models/ggml-tiny.en.bin -f Rev.mp3 -nt --output-text out1.txt"""
38
  try:
39
  if path is None:
40
  raise Exception("No path provided")
41
- outputFilePath: str = f"transcribe/{uuid.uuid4()}.txt"
42
- command: str = f"./binary/whisper -m models/{model} -f {path} -nt --output-text {outputFilePath}"
 
 
43
  execute_command(command)
44
  f = open(outputFilePath, "r")
45
  data = f.read()
46
  f.close()
47
- return data
48
  except Exception as e:
49
  logging.error(e)
50
  raise Exception(e.__str__())
@@ -66,3 +69,22 @@ def save_audio_file(file=None):
66
  with open(path, "wb") as f:
67
  f.write(file.file.read())
68
  return path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import subprocess
3
  import uuid
4
  import logging
5
+ import wave
6
 
7
 
8
  def get_all_routes(app):
 
34
  print("\n")
35
 
36
 
37
+ def transcribe_file(path: str = None, model="ggml-model-whisper-tiny.en-q5_1.bin"):
38
+ """./binary/whisper -m models/ggml-tiny.en.bin -f Rev.mp3 out.wav -nt --output-text out1.txt"""
39
  try:
40
  if path is None:
41
  raise Exception("No path provided")
42
+ rand = uuid.uuid4()
43
+ outputFilePath: str = f"transcribe/{rand}.txt"
44
+ output_audio_path: str = f"audio/{rand}.wav"
45
+ command: str = f"./binary/whisper -m models/{model} -f {path} {output_audio_path} -nt --output-text {outputFilePath}"
46
  execute_command(command)
47
  f = open(outputFilePath, "r")
48
  data = f.read()
49
  f.close()
50
+ return [data, output_audio_path]
51
  except Exception as e:
52
  logging.error(e)
53
  raise Exception(e.__str__())
 
69
  with open(path, "wb") as f:
70
  f.write(file.file.read())
71
  return path
72
+
73
+
74
+ def get_audio_duration(audio_file):
75
+ """Gets the duration of the audio file in seconds.
76
+
77
+ Args:
78
+ audio_file: The path to the audio file.
79
+
80
+ Returns:
81
+ The duration of the audio file in seconds.
82
+ """
83
+
84
+ with wave.open(audio_file, "rb") as f:
85
+ frames = f.getnframes()
86
+ sample_rate = f.getframerate()
87
+ duration = frames / sample_rate
88
+ rounded_duration = int(round(duration, 0))
89
+
90
+ return rounded_duration
binary/whisper CHANGED
Binary files a/binary/whisper and b/binary/whisper differ