AkomptaBackend / api /assemblyai_service.py
rinogeek's picture
Initial commit of backend code to Hugging Face Space
385a349
import os
import time
import requests
from pathlib import Path
from django.conf import settings
class AssemblyAIService:
def __init__(self):
# Try to load from environment first
self.api_key = os.environ.get("ASSEMBLYAI_API_KEY")
# If not in environment, try loading from .env file directly
if not self.api_key:
env_path = Path(__file__).resolve().parent.parent / '.env'
if env_path.exists():
with open(env_path, 'r') as f:
for line in f:
line = line.strip()
if line.startswith('ASSEMBLYAI_API_KEY='):
self.api_key = line.split('=', 1)[1].strip()
break
if not self.api_key:
print("Warning: ASSEMBLYAI_API_KEY not found.")
self.headers = {
"Authorization": self.api_key,
"Content-Type": "application/json"
}
self.upload_url = "https://api.assemblyai.com/v2/upload"
self.transcript_url = "https://api.assemblyai.com/v2/transcript"
def upload_file(self, audio_file):
"""Upload audio file to AssemblyAI"""
if not self.api_key:
return None
try:
# AssemblyAI expects the raw file content in the body
audio_file.seek(0)
response = requests.post(
self.upload_url,
headers={"Authorization": self.api_key},
data=audio_file.read()
)
if response.status_code != 200:
print(f"AssemblyAI Upload Error: {response.status_code} - {response.text}")
response.raise_for_status()
return response.json()["upload_url"]
except Exception as e:
print(f"Error uploading to AssemblyAI: {e}")
return None
def transcribe(self, audio_file, language=None):
"""
Transcribe audio file using AssemblyAI REST API.
"""
if not self.api_key:
return None
try:
# 1. Upload
upload_url = self.upload_file(audio_file)
if not upload_url:
return None
# Start transcription with required speech model
lang_to_use = language.lower()[:2] if language else "fr"
payload = {
"audio_url": upload_url,
"language_code": lang_to_use,
"speech_models": ["universal-3-pro"] # Matches the error suggestion
}
response = requests.post(self.transcript_url, json=payload, headers=self.headers)
if response.status_code != 200 and response.status_code != 201:
print(f"AssemblyAI error response: {response.text}")
response.raise_for_status()
transcript_id = response.json()["id"]
# 3. Polling for results
polling_url = f"{self.transcript_url}/{transcript_id}"
max_attempts = 30
attempts = 0
while attempts < max_attempts:
polling_response = requests.get(polling_url, headers=self.headers)
polling_response.raise_for_status()
data = polling_response.json()
if data["status"] == "completed":
return data["text"]
elif data["status"] == "error":
print(f"AssemblyAI transcription error: {data.get('error')}")
return None
attempts += 1
time.sleep(1) # Poll every second
print("AssemblyAI transcription timed out.")
return None
except Exception as e:
print(f"Error calling AssemblyAI STT: {e}")
return None