Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -61,53 +61,58 @@ def transcribe_audio(audio_path):
|
|
61 |
# ------------------------
|
62 |
# Étape 5 : Validation des segments + découpe
|
63 |
# ------------------------
|
64 |
-
def
|
65 |
"""
|
66 |
-
|
67 |
-
|
68 |
-
3) On renvoie une liste de chemins pour écoute sur l'interface
|
69 |
"""
|
70 |
if not audio_path:
|
71 |
-
return [
|
72 |
|
73 |
-
#
|
|
|
|
|
|
|
|
|
74 |
if os.path.exists(TEMP_DIR):
|
75 |
shutil.rmtree(TEMP_DIR)
|
76 |
os.makedirs(TEMP_DIR, exist_ok=True)
|
77 |
|
78 |
-
# Charger l'audio complet pour la découpe
|
79 |
-
original_audio = AudioSegment.from_file(audio_path)
|
80 |
-
|
81 |
segment_paths = []
|
82 |
updated_metadata = []
|
83 |
|
|
|
|
|
|
|
84 |
for i, row in enumerate(table_data):
|
85 |
-
#
|
86 |
-
if len(row) < 4:
|
87 |
-
# S'il n'y a pas toutes les colonnes, on ignore
|
88 |
continue
|
89 |
|
90 |
-
segment_text
|
91 |
-
|
92 |
-
|
93 |
-
continue
|
94 |
|
95 |
-
#
|
96 |
-
if
|
97 |
-
|
98 |
|
99 |
-
#
|
100 |
-
start_ms = int(float(start_time) * 1000)
|
101 |
-
end_ms = int(float(end_time) * 1000)
|
102 |
-
extract = original_audio[start_ms:end_ms]
|
103 |
|
|
|
|
|
|
|
|
|
|
|
104 |
segment_filename = f"{Path(audio_path).stem}_{seg_id}.wav"
|
105 |
-
|
106 |
-
extract
|
|
|
107 |
|
108 |
-
|
|
|
109 |
|
110 |
-
# Stocker la méta (pour
|
111 |
updated_metadata.append({
|
112 |
"audio_file": segment_filename,
|
113 |
"text": segment_text,
|
@@ -116,11 +121,12 @@ def validate_segments(audio_path, table_data, metadata_state):
|
|
116 |
"id": seg_id
|
117 |
})
|
118 |
|
119 |
-
|
120 |
-
# (Dans Gradio, on renvoie la nouvelle valeur)
|
121 |
-
return segment_paths, updated_metadata
|
122 |
|
|
|
|
|
123 |
|
|
|
124 |
# ------------------------
|
125 |
# Étape 7 : Génération du ZIP (avec metadata.csv)
|
126 |
# ------------------------
|
@@ -235,13 +241,12 @@ with gr.Blocks(css="style.css") as demo:
|
|
235 |
outputs=[raw_transcription, table, audio_input], # On renvoie le path en 3e
|
236 |
)
|
237 |
|
238 |
-
# Étape 2 : Callback quand on valide les segments => on découpe
|
239 |
validate_button.click(
|
240 |
-
fn=
|
241 |
inputs=[audio_input, table, metadata_state],
|
242 |
outputs=[
|
243 |
-
audio_player_1, audio_player_2, audio_player_3, audio_player_4, audio_player_5,
|
244 |
-
metadata_state
|
245 |
]
|
246 |
)
|
247 |
|
|
|
61 |
# ------------------------
|
62 |
# Étape 5 : Validation des segments + découpe
|
63 |
# ------------------------
|
64 |
+
def validate_segments_with_timestamps(audio_path, table_data, metadata_state):
|
65 |
"""
|
66 |
+
Valide les segments définis par l'utilisateur et ajoute automatiquement
|
67 |
+
les timestamps (`start_time` et `end_time`) pour les lignes sans valeurs.
|
|
|
68 |
"""
|
69 |
if not audio_path:
|
70 |
+
return [None] * 20, metadata_state
|
71 |
|
72 |
+
# Charger l'audio complet
|
73 |
+
original_audio = AudioSegment.from_file(audio_path)
|
74 |
+
audio_duration = len(original_audio) / 1000 # Durée totale en secondes
|
75 |
+
|
76 |
+
# Nettoyer le dossier temporaire
|
77 |
if os.path.exists(TEMP_DIR):
|
78 |
shutil.rmtree(TEMP_DIR)
|
79 |
os.makedirs(TEMP_DIR, exist_ok=True)
|
80 |
|
|
|
|
|
|
|
81 |
segment_paths = []
|
82 |
updated_metadata = []
|
83 |
|
84 |
+
# Dernier temps utilisé (pour calculer les suivants)
|
85 |
+
last_end_time = 0.0
|
86 |
+
|
87 |
for i, row in enumerate(table_data):
|
88 |
+
# Vérifier si la ligne contient des données
|
89 |
+
if len(row) < 4 or not row[0]: # Texte vide
|
|
|
90 |
continue
|
91 |
|
92 |
+
segment_text = row[0] # Texte
|
93 |
+
start_time = row[1] if row[1] is not None else last_end_time
|
94 |
+
end_time = row[2] if row[2] is not None else min(audio_duration, start_time + 5) # Segment de 5s par défaut
|
|
|
95 |
|
96 |
+
# Ajuster `end_time` si nécessaire
|
97 |
+
if end_time <= start_time:
|
98 |
+
end_time = min(audio_duration, start_time + 5) # Minimum 5s
|
99 |
|
100 |
+
seg_id = row[3] if row[3] else f"seg_{i+1:02d}" # Générer ID si absent
|
|
|
|
|
|
|
101 |
|
102 |
+
# Convertir en millisecondes
|
103 |
+
start_ms = int(start_time * 1000)
|
104 |
+
end_ms = int(end_time * 1000)
|
105 |
+
|
106 |
+
# Découpe de l'audio
|
107 |
segment_filename = f"{Path(audio_path).stem}_{seg_id}.wav"
|
108 |
+
segment_path = os.path.join(TEMP_DIR, segment_filename)
|
109 |
+
extract = original_audio[start_ms:end_ms]
|
110 |
+
extract.export(segment_path, format="wav")
|
111 |
|
112 |
+
# Mise à jour des timestamps
|
113 |
+
last_end_time = end_time
|
114 |
|
115 |
+
# Stocker la méta (pour metadata_state)
|
116 |
updated_metadata.append({
|
117 |
"audio_file": segment_filename,
|
118 |
"text": segment_text,
|
|
|
121 |
"id": seg_id
|
122 |
})
|
123 |
|
124 |
+
segment_paths.append(segment_path)
|
|
|
|
|
125 |
|
126 |
+
# Remplir les 20 slots si moins de 20 segments
|
127 |
+
output_paths = segment_paths + [None] * (20 - len(segment_paths))
|
128 |
|
129 |
+
return output_paths, updated_metadata
|
130 |
# ------------------------
|
131 |
# Étape 7 : Génération du ZIP (avec metadata.csv)
|
132 |
# ------------------------
|
|
|
241 |
outputs=[raw_transcription, table, audio_input], # On renvoie le path en 3e
|
242 |
)
|
243 |
|
|
|
244 |
validate_button.click(
|
245 |
+
fn=validate_segments_with_timestamps,
|
246 |
inputs=[audio_input, table, metadata_state],
|
247 |
outputs=[
|
248 |
+
[audio_player_1, audio_player_2, audio_player_3, audio_player_4, audio_player_5],
|
249 |
+
metadata_state
|
250 |
]
|
251 |
)
|
252 |
|