VoiceToWrite / diarization.py
Seicas's picture
Update diarization.py
f631cbd verified
from pyannote.audio import Pipeline
from typing import List, Dict, Any
import torch
import os
from config import settings
# HF_TOKEN hardcoded assignment removed for security
_diarization_pipeline = None
def get_diarization_pipeline():
"""Diarization pipeline singleton with fallback"""
global _diarization_pipeline
if not os.getenv("HF_TOKEN"):
print("Warning: HF_TOKEN not set! Diarization will be disabled.")
return None
if _diarization_pipeline is None:
try:
device = "cuda" if torch.cuda.is_available() else "cpu"
_diarization_pipeline = Pipeline.from_pretrained(
settings.DIARIZATION_MODEL,
use_auth_token=os.environ.get("HF_TOKEN"),
device=device
)
except Exception as e:
print(f"Error loading diarization pipeline: {e}")
return None
return _diarization_pipeline
def rename_speakers_for_pediatrics(segments: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
"""
Konuşmacıları pediatri bağlamına göre yeniden isimlendirir
"""
# Konuşmacıları basit bir şekilde yeniden isimlendiriyoruz
# Gerçek bir uygulamada ses özellikleri analizi ile daha sofistike olabilir
renamed_segments = []
speaker_mapping = {}
for segment in segments:
speaker = segment["speaker"]
if speaker not in speaker_mapping:
# İlk konuşmacıyı bölüm başkanı olarak kabul ediyoruz
if len(speaker_mapping) == 0:
speaker_mapping[speaker] = "Bölüm_Başkanı"
# İkinci konuşmacıyı hekim olarak kabul ediyoruz
elif len(speaker_mapping) == 1:
speaker_mapping[speaker] = "Hekim"
# Üçüncü konuşmacıyı asistan olarak kabul ediyoruz
elif len(speaker_mapping) == 2:
speaker_mapping[speaker] = "Asistan"
# Diğer konuşmacılar
else:
speaker_mapping[speaker] = f"Konuşmacı_{len(speaker_mapping) + 1}"
# Segment kopyası oluştur ve konuşmacı ismini güncelle
new_segment = segment.copy()
new_segment["speaker"] = speaker_mapping[speaker]
renamed_segments.append(new_segment)
return renamed_segments
def diarize_audio(audio_path: str) -> List[Dict[str, Any]]:
"""Diarize audio with fallback to single speaker"""
try:
pipeline = get_diarization_pipeline()
if pipeline is None:
# Fallback: Return single speaker for entire duration
return [{"speaker": "Speaker 1", "start": 0.0, "end": float("inf")}]
diarization = pipeline(audio_path)
segments = []
for turn, _, speaker in diarization.itertracks(yield_label=True):
if turn.duration >= settings.MIN_SPEAKER_DURATION:
segments.append({
"speaker": f"Speaker {speaker.split('_')[-1]}",
"start": turn.start,
"end": turn.end
})
return segments
except Exception as e:
print(f"Diarization error: {e}")
# Fallback: Return single speaker
return [{"speaker": "Speaker 1", "start": 0.0, "end": float("inf")}]
def diarize_segments(audio_file: str, is_pediatrics: bool = True) -> List[Dict[str, Any]]:
"""
Ses dosyasındaki konuşmacıları ayırt eder
Args:
audio_file: Ses dosyasının yolu
Returns:
Konuşmacı segmentleri listesi
[
{"speaker": "speaker_0", "start": 0.5, "end": 2.3, "text": "..."},
{"speaker": "speaker_1", "start": 2.4, "end": 5.1, "text": "..."},
...
]
"""
# Pipeline'ı al
pipeline = get_diarization_pipeline()
# Diyarizasyon gerçekleştir
diarization = pipeline(audio_file)
# Sonuçları formatlayalım
results = []
for turn, _, speaker in diarization.itertracks(yield_label=True):
segment = {
"speaker": speaker,
"start": turn.start,
"end": turn.end,
"text": "" # Bu alanı transcribe işlemi sonrası dolduracağız
}
results.append(segment)
# Pediatri bağlamı için konuşmacı isimlerini güncelle
if is_pediatrics:
results = rename_speakers_for_pediatrics(results)
return results