File size: 3,822 Bytes
164d23a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
"""
Module for transcribing audio files using Whisper.
Optimized for CPU with whisper-tiny model.
"""

import os
import logging
from typing import Optional

try:
    import torch
    from transformers import WhisperProcessor, WhisperForConditionalGeneration
    import librosa
except ImportError as e:
    print(f"Import error: {e}")
    torch = None
    WhisperProcessor = None
    WhisperForConditionalGeneration = None
    librosa = None

# Configurazione logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Variabili globali per il modello (caricato una sola volta)
_model = None
_processor = None


def load_whisper_model():
    """Load Whisper tiny model optimized for CPU."""
    global _model, _processor
    
    if _model is None or _processor is None:
        try:
            logger.info("Loading Whisper tiny model...")
            
            # Load processor and model
            _processor = WhisperProcessor.from_pretrained("openai/whisper-tiny")
            _model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-tiny")
            
            # Configure for CPU
            _model.eval()
            if torch.cuda.is_available():
                _model = _model.to("cuda")
            else:
                _model = _model.to("cpu")
            
            logger.info("Whisper model loaded successfully")
            
        except Exception as e:
            logger.error(f"Error loading Whisper model: {str(e)}")
            raise
    
    return _model, _processor


def transcribe_audio(file_path: str, language: str = "en") -> Optional[str]:
    """
    Transcribe an audio file using Whisper.
    
    Args:
        file_path (str): Path to audio file
        language (str): Language of audio content (default: "en" for English)
        
    Returns:
        Optional[str]: Text transcription or None if error
    """
    if not os.path.exists(file_path):
        logger.error(f"Audio file not found: {file_path}")
        return None
    
    if librosa is None:
        logger.error("librosa not installed. Install with: pip install librosa")
        return None
    
    try:
        # Load the model
        model, processor = load_whisper_model()
        
        # Load and preprocess audio
        logger.info(f"Loading audio file: {file_path}")
        audio_array, sample_rate = librosa.load(file_path, sr=16000)
        
        # Preprocess audio
        inputs = processor(audio_array, sampling_rate=sample_rate, return_tensors="pt")
        
        # Move to appropriate device
        device = next(model.parameters()).device
        inputs = {k: v.to(device) for k, v in inputs.items()}
        
        # Generate transcription
        logger.info("Generating transcription...")
        with torch.no_grad():
            predicted_ids = model.generate(
                inputs["input_features"],
                max_length=448,
                num_beams=1,
                do_sample=False,
                language=language
            )
        
        # Decode the result
        transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)[0]
        
        logger.info("Transcription completed successfully")
        return transcription.strip()
        
    except Exception as e:
        logger.error(f"Error during transcription of {file_path}: {str(e)}")
        return None


def get_supported_audio_extensions() -> list:
    """Return supported audio extensions."""
    return ['.mp3', '.wav', '.m4a', '.flac', '.ogg']


def is_audio_file(file_path: str) -> bool:
    """Check if a file is a supported audio file."""
    if not file_path:
        return False
    
    file_extension = os.path.splitext(file_path)[1].lower()
    return file_extension in get_supported_audio_extensions()