Transcriptions / app.py
Celsia's picture
Upload app.py
c800820 verified
Raw
History Blame Contribute Delete
3.78 kB
import whisper
import gradio as gr
from docx import Document
import time
import librosa
import soundfile as sf
from scipy.cluster.hierarchy import dendrogram, fcluster
from sklearn.preprocessing import StandardScaler
import numpy as np
import ssl
import urllib.request
# ไธดๆ—ถ็ฆ็”จ่ฏไนฆ้ชŒ่ฏ
context = ssl._create_unverified_context()
urllib.request.urlopen("https://huggingface.co", context=context)
# Load the Whisper model (choose a model based on performance/accuracy requirements)
model = whisper.load_model("base") # You can use "small", "medium", "large" for better accuracy
def extract_mfcc(audio_path, sr=None):
"""Extract MFCC features from audio file"""
y, sr = librosa.load(audio_path, sr=sr)
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
return mfccs.T # Transpose to get (time_steps, n_mfcc)
def perform_clustering(features):
"""Perform hierarchical clustering on MFCC features"""
scaler = StandardScaler()
scaled_features = scaler.fit_transform(features)
# Compute pairwise distances
distance_matrix = np.sqrt(((scaled_features - scaled_features[:, np.newaxis])**2).sum(axis=2))
# Perform hierarchical clustering
linkage = np.linalg.norm(distance_matrix[:, np.newaxis] - distance_matrix[np.newaxis, :], axis=2)
# Generate dendrogram and get flat clusters
clusters = fcluster(linkage, t=0.5, criterion='distance') # Threshold needs tuning
return clusters
def transcribe_and_generate_docx(audio_path, language):
# Step 1: Basic transcription with Whisper
audio_file = whisper.load_audio(audio_path)
language_code = 'en' if language == "English" else 'zh'
result = model.transcribe(audio_file, language=language_code)
transcribed_text = result["text"]
# Step 2: Extract MFCC features for clustering
mfcc_features = extract_mfcc(audio_path)
if len(mfcc_features) < 2:
return "output_transcription.docx", transcribed_text
# Step 3: Perform hierarchical clustering
try:
clusters = perform_clustering(mfcc_features)
except Exception as e:
log_message(f"Clustering error: {str(e)}")
raise RuntimeError("Failed to cluster speakers") from e
# Assign speaker labels
unique_speakers = list(np.unique(clusters))
speaker_map = {i+1: speaker for i, speaker in enumerate(unique_speakers)}
# Split transcription text by speaker clusters
time_segments = model.get_timestamps(audio_file)
speaker_texts = {}
for cluster_id, segment in zip(clusters, time_segments):
speaker_id = speaker_map[cluster_id]
start_time = segment['start']
end_time = segment['end']
# Find corresponding text็‰‡ๆฎต (approximation method)
current_text = []
for part in result["alternatives"][0]["transcript"].split(' '):
part_duration = len(part) * 0.03 # Approximate word duration
if start_time <= cumulative_time < end_time:
current_text.append(part)
cumulative_time += part_duration
speaker_texts[speaker_id] = ' '.join(current_text).strip()
# Create a docx document with speaker separation
doc = Document()
doc.add_heading("Speaker Transcription", level=1)
for speaker_id, text in speaker_texts.items():
doc.add_heading(f"Speaker {speaker_id}", level=2)
doc.add_paragraph(text)
# Save the document
output_filename = f"speaker_transcription_{os.path.basename(audio_path)}.docx"
doc.save(output_filename)
return output_filename, "\n\n".join([f"Speaker {i}: {text}" for i, text in speaker_texts.items()])
# ... [Keep Gradio interface code unchanged] ...
# Launch the interface
iface.launch()