Skip to content

Commit 9dd5ba5

Browse files
committed
Update transcribe_wav.py
1 parent f3fc409 commit 9dd5ba5

File tree

1 file changed

+180
-70
lines changed

1 file changed

+180
-70
lines changed

scripts/transcribe_wav.py

Lines changed: 180 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,41 @@
1-
# Trascrive automaticamente i file audio .wav in testo utilizzando il modello Whisper, salvando le trascrizioni e saltando quelle già esistenti.
1+
# Trascrive automaticamente i file audio .wav in testo utilizzando il modello Whisper,
2+
# salvando le trascrizioni e saltando quelle già esistenti.
23
import os
34
import subprocess
45
import sys
56
import importlib
7+
import time
8+
from datetime import datetime, timedelta
69

7-
def upgrade_pip_and_install_whisper():
10+
def upgrade_pip_and_install_packages():
811
"""
9-
Aggiorna pip e installa o reinstalla correttamente whisper.
12+
Aggiorna pip e installa o reinstalla correttamente whisper e tqdm.
1013
"""
1114
user_home = os.environ.get('USERPROFILE')
1215
python_path = os.path.join(user_home, "AppData", "Local", "Programs", "Python", "Python310", "python.exe")
1316

1417
if not os.path.exists(python_path):
1518
print(f"Errore: Python 3.10 non trovato in {python_path}.")
1619
sys.exit(1)
17-
20+
1821
print("Aggiornamento di pip in corso...")
1922
try:
2023
subprocess.check_call([python_path, "-m", "pip", "install", "--upgrade", "pip"])
2124
except subprocess.CalledProcessError as e:
2225
print(f"Errore durante l'aggiornamento di pip: {e}")
2326
sys.exit(1)
24-
27+
2528
print("Disinstallazione di vecchie versioni di whisper...")
2629
try:
2730
subprocess.check_call([python_path, "-m", "pip", "uninstall", "whisper", "-y"])
2831
except subprocess.CalledProcessError:
29-
# Ignora errori se whisper non è installato
3032
pass
31-
32-
print("Installazione di openai-whisper...")
33+
34+
print("Installazione di openai-whisper e tqdm...")
3335
try:
34-
subprocess.check_call([python_path, "-m", "pip", "install", "-U", "openai-whisper"])
36+
subprocess.check_call([python_path, "-m", "pip", "install", "-U", "openai-whisper", "tqdm"])
3537
except subprocess.CalledProcessError as e:
36-
print(f"Errore durante l'installazione di openai-whisper: {e}")
38+
print(f"Errore durante l'installazione: {e}")
3739
sys.exit(1)
3840

3941
def ensure_python_3_10():
@@ -42,53 +44,83 @@ def ensure_python_3_10():
4244
"""
4345
if sys.version_info[0] != 3 or sys.version_info[1] != 10:
4446
print("Forzando l'esecuzione con Python 3.10...")
45-
46-
# Recupera il percorso della home directory reale
4747
user_home = os.environ.get('USERPROFILE')
48-
49-
# Costruisci il percorso di Python 3.10 dinamicamente
5048
python_path = os.path.join(user_home, "AppData", "Local", "Programs", "Python", "Python310", "python.exe")
51-
49+
5250
if not os.path.exists(python_path):
5351
print(f"Errore: Python 3.10 non trovato in {python_path}. Verifica che Python 3.10 sia installato correttamente.")
5452
sys.exit(1)
55-
56-
# Verifica se python3.10 è disponibile
53+
5754
try:
5855
subprocess.check_call([python_path, "--version"])
5956
except subprocess.CalledProcessError:
6057
print("Errore: Python 3.10 non trovato o non configurato correttamente.")
6158
sys.exit(1)
62-
63-
# Esegui lo script con Python 3.10
59+
6460
subprocess.check_call([python_path, os.path.abspath(__file__)] + sys.argv[1:])
65-
sys.exit() # Termina il processo attuale, in modo che non venga eseguito altro codice
61+
sys.exit()
6662

67-
def import_whisper():
63+
def import_required_modules():
6864
"""
69-
Importa il modulo whisper in modo sicuro.
65+
Importa i moduli necessari in modo sicuro.
7066
"""
7167
try:
7268
import whisper
73-
return whisper
74-
except ImportError:
75-
print("Modulo whisper non trovato. Installazione in corso...")
76-
upgrade_pip_and_install_whisper()
77-
# Riprova ad importare dopo l'installazione
69+
from tqdm import tqdm
70+
return whisper, tqdm
71+
except ImportError as e:
72+
print(f"Moduli non trovati: {e}. Installazione in corso...")
73+
upgrade_pip_and_install_packages()
74+
7875
try:
7976
import whisper
80-
return whisper
77+
from tqdm import tqdm
78+
return whisper, tqdm
8179
except ImportError as e:
82-
print(f"Impossibile importare whisper anche dopo l'installazione: {e}")
80+
print(f"Impossibile importare i moduli anche dopo l'installazione: {e}")
8381
sys.exit(1)
8482

85-
def transcribe_podcast(file_path, model_name='medium', language='it'):
83+
def get_audio_duration(file_path):
84+
"""
85+
Stima la durata del file audio in secondi (approssimativa).
86+
Questa è una stima basata sulla dimensione del file.
87+
La stima è volutamente pessimistica per dare un ETA più lungo del reale.
88+
"""
89+
try:
90+
file_size = os.path.getsize(file_path)
91+
# Stima pessimistica: ~0.5MB per minuto di audio WAV (peggiorata del 50%)
92+
# Questo significa che stimiamo file più lunghi di quello che sono realmente
93+
estimated_duration = file_size / (1024 * 1024) * 120 # 120 invece di 60
94+
return max(estimated_duration, 60) # Minimo 60 secondi invece di 30
95+
except:
96+
return 600 # Default 10 minuti invece di 5 se non riusciamo a stimare
97+
98+
def transcribe_podcast_with_progress(file_path, model_name='medium', language='it'):
8699
"""
87-
Trascrive un file audio in formato .wav utilizzando il modello Whisper.
100+
Trascrive un file audio con barra di progresso simulata.
88101
"""
89-
whisper = import_whisper()
102+
whisper, tqdm = import_required_modules()
103+
104+
print(f"Caricamento del modello {model_name}...")
90105
model = whisper.load_model(model_name)
91-
result = model.transcribe(file_path, language=language)
106+
107+
# Stima della durata per il progresso (pessimistica)
108+
estimated_duration = get_audio_duration(file_path)
109+
estimated_time = estimated_duration * 0.2 # Raddoppiato: da 0.1 a 0.2 per essere più pessimisti
110+
111+
print(f"Trascrizione in corso...")
112+
start_time = time.time()
113+
114+
# Barra di progresso simulata durante la trascrizione
115+
with tqdm(total=100, desc="Progresso", unit="%", ncols=80) as pbar:
116+
# Avvia la trascrizione in un thread separato (simulato con aggiornamenti)
117+
result = model.transcribe(file_path, language=language)
118+
119+
# Simula il progresso (Whisper non fornisce callback di progresso nativi)
120+
elapsed = time.time() - start_time
121+
pbar.update(100)
122+
pbar.set_postfix({"Tempo": f"{elapsed:.1f}s"})
123+
92124
return result['text']
93125

94126
def save_transcription(transcription, output_path):
@@ -98,53 +130,131 @@ def save_transcription(transcription, output_path):
98130
with open(output_path, 'w', encoding='utf-8') as f:
99131
f.write(transcription)
100132

101-
def main(podcast_dir):
133+
def count_wav_files(podcast_dir):
134+
"""
135+
Conta il numero totale di file .wav da elaborare.
136+
"""
137+
count = 0
102138
for root, dirs, files in os.walk(podcast_dir):
103139
for file_name in files:
104-
file_path = os.path.join(root, file_name)
105-
base_name, ext = os.path.splitext(file_name)
106-
107-
# Supportati formati audio (solo .wav ora)
108-
if ext.lower() == '.wav':
109-
output_file_name = base_name + '.txt'
110-
output_path = os.path.join(root, output_file_name)
140+
if file_name.lower().endswith('.wav'):
141+
base_name = os.path.splitext(file_name)[0]
142+
output_path = os.path.join(root, base_name + '.txt')
143+
if not (os.path.exists(output_path) and os.path.getsize(output_path) > 1):
144+
count += 1
145+
return count
111146

112-
# Verifica se la trascrizione esiste già
113-
if os.path.exists(output_path) and os.path.getsize(output_path) > 1:
114-
print(f'Saltato {file_name}, il file di trascrizione esiste già.')
115-
continue
147+
def format_time(seconds):
148+
"""
149+
Formatta i secondi in formato HH:MM:SS.
150+
"""
151+
return str(timedelta(seconds=int(seconds)))
116152

117-
try:
118-
print(f'Trascrizione in corso per {file_name}...')
119-
transcription = transcribe_podcast(file_path)
120-
save_transcription(transcription, output_path)
121-
print(f'Trascrizione completata per {file_name}, salvata in {output_path}')
122-
except Exception as e:
123-
print(f'Errore durante la trascrizione di {file_name}: {e}')
153+
def main(podcast_dir):
154+
"""
155+
Funzione principale con barra di progresso e ETA.
156+
"""
157+
# Importa i moduli necessari
158+
whisper, tqdm = import_required_modules()
159+
160+
# Conta i file da elaborare
161+
total_files = count_wav_files(podcast_dir)
162+
163+
if total_files == 0:
164+
print("Nessun file .wav da elaborare trovato.")
165+
return
166+
167+
print(f"\nTrovati {total_files} file da trascrivere.")
168+
169+
processed_files = 0
170+
start_time = time.time()
171+
172+
# Barra di progresso principale per tutti i file
173+
with tqdm(total=total_files, desc="File elaborati", unit="file", ncols=100) as main_pbar:
174+
for root, dirs, files in os.walk(podcast_dir):
175+
for file_name in files:
176+
file_path = os.path.join(root, file_name)
177+
base_name, ext = os.path.splitext(file_name)
178+
179+
if ext.lower() == '.wav':
180+
output_file_name = base_name + '.txt'
181+
output_path = os.path.join(root, output_file_name)
182+
183+
# Verifica se la trascrizione esiste già
184+
if os.path.exists(output_path) and os.path.getsize(output_path) > 1:
185+
continue
186+
187+
try:
188+
file_start_time = time.time()
189+
190+
# Aggiorna la descrizione con il file corrente
191+
main_pbar.set_description(f"Elaborando: {file_name[:30]}...")
192+
193+
transcription = transcribe_podcast_with_progress(file_path)
194+
save_transcription(transcription, output_path)
195+
196+
processed_files += 1
197+
elapsed_total = time.time() - start_time
198+
file_elapsed = time.time() - file_start_time
199+
200+
# Calcola ETA
201+
if processed_files > 0:
202+
avg_time_per_file = elapsed_total / processed_files
203+
remaining_files = total_files - processed_files
204+
eta_seconds = avg_time_per_file * remaining_files
205+
eta_formatted = format_time(eta_seconds)
206+
else:
207+
eta_formatted = "Calcolando..."
208+
209+
# Aggiorna la barra di progresso
210+
main_pbar.update(1)
211+
main_pbar.set_postfix({
212+
"File": f"{file_elapsed:.1f}s",
213+
"ETA": eta_formatted,
214+
"Totale": format_time(elapsed_total)
215+
})
216+
217+
print(f"\n✓ Completato: {file_name}")
218+
print(f" Salvato in: {output_path}")
219+
print(f" Tempo impiegato: {file_elapsed:.1f} secondi")
220+
221+
except Exception as e:
222+
print(f"\n✗ Errore durante la trascrizione di {file_name}: {e}")
223+
main_pbar.update(1)
224+
225+
total_elapsed = time.time() - start_time
226+
print(f"\n🎉 Trascrizione completata!")
227+
print(f"File elaborati: {processed_files}/{total_files}")
228+
print(f"Tempo totale: {format_time(total_elapsed)}")
229+
if processed_files > 0:
230+
print(f"Tempo medio per file: {total_elapsed/processed_files:.1f} secondi")
124231

125232
if __name__ == "__main__":
126233
# Verifica che Python 3.10 sia utilizzato
127234
ensure_python_3_10()
128235

129-
# Aggiorna pip e installa correttamente whisper
130-
upgrade_pip_and_install_whisper()
131-
132-
podcast_dir = input("Inserisci il percorso della cartella contenente i podcast: ").strip()
133-
if os.path.isdir(podcast_dir):
134-
main(podcast_dir)
135-
print("Trascrizione completata.")
136-
else:
137-
print("Il percorso inserito non è valido. Per favore riprova.")
236+
# Aggiorna pip e installa correttamente whisper e tqdm
237+
upgrade_pip_and_install_packages()
238+
239+
while True:
240+
podcast_dir = input("\nInserisci il percorso della cartella contenente i podcast: ").strip()
241+
242+
if os.path.isdir(podcast_dir):
243+
print(f"\nIniziando l'elaborazione della cartella: {podcast_dir}")
244+
main(podcast_dir)
245+
else:
246+
print("Il percorso inserito non è valido. Per favore riprova.")
247+
continue
248+
138249
while True:
139-
scelta = input("\nUtilizza di nuovo lo script digitando 1 o premi 0 per ritornare a main.py: ").strip()
250+
scelta = input("\nUtilizza di nuovo lo script digitando 1 o premi 0 per uscire: ").strip()
140251
if scelta == '1':
141-
podcast_dir = input("Inserisci il percorso della cartella contenente i podcast: ").strip()
142-
if os.path.isdir(podcast_dir):
143-
main(podcast_dir)
144-
print("Trascrizione completata.")
145-
else:
146-
print("Il percorso inserito non è valido. Per favore riprova.")
147-
elif scelta == '0':
148252
break
253+
elif scelta == '0':
254+
print("Arrivederci!")
255+
sys.exit(0)
149256
else:
150-
print("Scelta non valida. Inserire 1 o 0.")
257+
print("Scelta non valida. Inserire 1 o 0.")
258+
259+
if scelta == '0':
260+
break

0 commit comments

Comments
 (0)