Spaces:
Sleeping
Sleeping
ALLARD Marc-Antoine
commited on
Commit
Β·
de1009f
1
Parent(s):
c19c343
Fix transcription auto-save and segmentation form reset
Browse files
app.py
CHANGED
@@ -96,7 +96,7 @@ def create_waveform_html(audio_data, segments=None):
|
|
96 |
<div id="waveform" style="height: 200px; border: 1px solid #ddd;"></div>
|
97 |
<div style="margin-top: 10px;">
|
98 |
<button id="play-pause" style="margin-right: 5px; padding: 8px 15px; background: #00cc44; color: white; border: none; border-radius: 3px; cursor: pointer;">
|
99 |
-
|
100 |
</button>
|
101 |
<button id="add-region" style="margin-right: 5px; padding: 8px 15px; background: #0066cc; color: white; border: none; border-radius: 3px; cursor: pointer;">
|
102 |
β Add Region
|
@@ -128,7 +128,9 @@ def create_waveform_html(audio_data, segments=None):
|
|
128 |
responsive: true,
|
129 |
plugins: [
|
130 |
WaveSurfer.regions.create({{
|
131 |
-
dragSelection:
|
|
|
|
|
132 |
color: 'rgba(255, 75, 75, 0.3)'
|
133 |
}})
|
134 |
]
|
@@ -161,6 +163,40 @@ def create_waveform_html(audio_data, segments=None):
|
|
161 |
updateRegionsList();
|
162 |
}});
|
163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
// Add region function
|
165 |
function addRegion(start, end, speaker_id) {{
|
166 |
// Get or assign color for this speaker
|
@@ -205,7 +241,7 @@ def create_waveform_html(audio_data, segments=None):
|
|
205 |
</div>
|
206 |
<button onclick="removeRegion('${{region.id}}')"
|
207 |
style="background: #cc0000; color: white; border: none; border-radius: 3px; padding: 5px 8px; cursor: pointer;">
|
208 |
-
|
209 |
</button>
|
210 |
</div>
|
211 |
`;
|
@@ -430,49 +466,55 @@ def show_transcription_page():
|
|
430 |
audio_html = create_audio_player_html(st.session_state.audio_file)
|
431 |
st.components.v1.html(audio_html, height=120)
|
432 |
|
433 |
-
# Transcription area
|
434 |
st.subheader("Transcript")
|
|
|
|
|
|
|
|
|
|
|
435 |
transcript = st.text_area(
|
436 |
"Write your transcription here:",
|
437 |
value=st.session_state.transcript,
|
438 |
height=300,
|
439 |
-
help="Check the guidelines below to help you transcribe accurately."
|
|
|
|
|
440 |
)
|
441 |
-
st.session_state.transcript = transcript
|
442 |
|
443 |
# Guidelines reminder
|
444 |
with st.expander("π Transcription Guidelines"):
|
445 |
st.markdown("""
|
446 |
**Key Guidelines:**
|
447 |
-
- Transcribe
|
448 |
-
- Use standard punctuation and capitalization (tip: Get punctuation from natural pauses in dialogue)
|
449 |
-
- Write numbers
|
450 |
-
- Ignore unclear speech or marked as [unclear] or [inaudible]
|
451 |
-
- For multi-speaker: transcribe all audible speech without identifying speakers
|
452 |
""")
|
453 |
|
454 |
# Action buttons
|
455 |
col1, col2, col3 = st.columns(3)
|
456 |
|
457 |
with col1:
|
458 |
-
if transcript.strip():
|
459 |
-
download_link = get_download_link(transcript, "transcript.txt", "πΎ Download Transcript")
|
460 |
st.markdown(download_link, unsafe_allow_html=True)
|
461 |
else:
|
462 |
st.button("πΎ Download Transcript", disabled=True)
|
463 |
|
464 |
with col2:
|
465 |
-
if st.session_state.annotation_type == "multi_speaker" and transcript.strip():
|
466 |
if st.button("π― Continue to Segmentation β"):
|
467 |
st.session_state.current_page = "segmentation"
|
468 |
st.rerun()
|
469 |
|
470 |
with col3:
|
471 |
-
if st.session_state.annotation_type == "single_speaker" and transcript.strip():
|
472 |
if st.button("β
Finish Annotation"):
|
473 |
st.balloons()
|
474 |
st.success("π Single speaker annotation completed!")
|
475 |
-
download_link = get_download_link(transcript, "transcript.txt", "π₯ Download Final Transcript")
|
476 |
st.markdown(download_link, unsafe_allow_html=True)
|
477 |
|
478 |
def show_segmentation_page():
|
@@ -491,7 +533,7 @@ def show_segmentation_page():
|
|
491 |
|
492 |
# Manual segment addition
|
493 |
st.subheader("Manual Segment Addition")
|
494 |
-
st.info("After having segmented the wav using our wav surfer, you can manually add segments here. Don't hesitate to replay and pause
|
495 |
col1, col2, col3, col4 = st.columns(4)
|
496 |
|
497 |
with col1:
|
@@ -632,3 +674,4 @@ def create_speaker_transcript(segments):
|
|
632 |
|
633 |
if __name__ == "__main__":
|
634 |
main()
|
|
|
|
96 |
<div id="waveform" style="height: 200px; border: 1px solid #ddd;"></div>
|
97 |
<div style="margin-top: 10px;">
|
98 |
<button id="play-pause" style="margin-right: 5px; padding: 8px 15px; background: #00cc44; color: white; border: none; border-radius: 3px; cursor: pointer;">
|
99 |
+
βΆοΈ Play/Pause
|
100 |
</button>
|
101 |
<button id="add-region" style="margin-right: 5px; padding: 8px 15px; background: #0066cc; color: white; border: none; border-radius: 3px; cursor: pointer;">
|
102 |
β Add Region
|
|
|
128 |
responsive: true,
|
129 |
plugins: [
|
130 |
WaveSurfer.regions.create({{
|
131 |
+
dragSelection: {{
|
132 |
+
slop: 5
|
133 |
+
}},
|
134 |
color: 'rgba(255, 75, 75, 0.3)'
|
135 |
}})
|
136 |
]
|
|
|
163 |
updateRegionsList();
|
164 |
}});
|
165 |
|
166 |
+
// Handle region creation via drag selection
|
167 |
+
wavesurfer.on('region-created', function(region) {{
|
168 |
+
// Check if this is a new region (not from loading existing segments)
|
169 |
+
const existingRegion = regions.find(r => r.id === region.id);
|
170 |
+
if (!existingRegion) {{
|
171 |
+
// Prompt for speaker ID
|
172 |
+
const speakerId = prompt("Enter speaker ID (e.g., SPK001):", "SPK" + (Object.keys(speakerColors).length + 1).toString().padStart(3, '0'));
|
173 |
+
|
174 |
+
if (speakerId) {{
|
175 |
+
// Get or assign color for this speaker
|
176 |
+
if (!speakerColors[speakerId]) {{
|
177 |
+
speakerColors[speakerId] = getColorForSpeaker(speakerId);
|
178 |
+
}}
|
179 |
+
|
180 |
+
// Update region color
|
181 |
+
region.color = speakerColors[speakerId];
|
182 |
+
region.updateRender();
|
183 |
+
|
184 |
+
// Add to regions array
|
185 |
+
regions.push({{
|
186 |
+
id: region.id,
|
187 |
+
start: region.start,
|
188 |
+
end: region.end,
|
189 |
+
speaker_id: speakerId
|
190 |
+
}});
|
191 |
+
|
192 |
+
updateRegionsList();
|
193 |
+
}} else {{
|
194 |
+
// If user cancels, remove the region
|
195 |
+
region.remove();
|
196 |
+
}}
|
197 |
+
}}
|
198 |
+
}});
|
199 |
+
|
200 |
// Add region function
|
201 |
function addRegion(start, end, speaker_id) {{
|
202 |
// Get or assign color for this speaker
|
|
|
241 |
</div>
|
242 |
<button onclick="removeRegion('${{region.id}}')"
|
243 |
style="background: #cc0000; color: white; border: none; border-radius: 3px; padding: 5px 8px; cursor: pointer;">
|
244 |
+
β
|
245 |
</button>
|
246 |
</div>
|
247 |
`;
|
|
|
466 |
audio_html = create_audio_player_html(st.session_state.audio_file)
|
467 |
st.components.v1.html(audio_html, height=120)
|
468 |
|
469 |
+
# Transcription area with callback for auto-saving
|
470 |
st.subheader("Transcript")
|
471 |
+
|
472 |
+
def update_transcript():
|
473 |
+
"""Callback function to update transcript in session state"""
|
474 |
+
st.session_state.transcript = st.session_state.transcript_input
|
475 |
+
|
476 |
transcript = st.text_area(
|
477 |
"Write your transcription here:",
|
478 |
value=st.session_state.transcript,
|
479 |
height=300,
|
480 |
+
help="Check the guidelines below to help you transcribe accurately.",
|
481 |
+
key="transcript_input",
|
482 |
+
on_change=update_transcript
|
483 |
)
|
|
|
484 |
|
485 |
# Guidelines reminder
|
486 |
with st.expander("π Transcription Guidelines"):
|
487 |
st.markdown("""
|
488 |
**Key Guidelines:**
|
489 |
+
- Transcribe EXACTLY what is said. No shortening or paraphrasing. (e.g saying "I do like" and "I'd like" are different)
|
490 |
+
- Use standard punctuation and capitalization (tip: Get punctuation from natural pauses in dialogue).
|
491 |
+
- Write numbers as digits.
|
492 |
+
- Ignore unclear speech or marked as [unclear] or [inaudible].
|
493 |
+
- For multi-speaker: transcribe all audible speech without identifying speakers.
|
494 |
""")
|
495 |
|
496 |
# Action buttons
|
497 |
col1, col2, col3 = st.columns(3)
|
498 |
|
499 |
with col1:
|
500 |
+
if st.session_state.transcript.strip():
|
501 |
+
download_link = get_download_link(st.session_state.transcript, "transcript.txt", "πΎ Download Transcript")
|
502 |
st.markdown(download_link, unsafe_allow_html=True)
|
503 |
else:
|
504 |
st.button("πΎ Download Transcript", disabled=True)
|
505 |
|
506 |
with col2:
|
507 |
+
if st.session_state.annotation_type == "multi_speaker" and st.session_state.transcript.strip():
|
508 |
if st.button("π― Continue to Segmentation β"):
|
509 |
st.session_state.current_page = "segmentation"
|
510 |
st.rerun()
|
511 |
|
512 |
with col3:
|
513 |
+
if st.session_state.annotation_type == "single_speaker" and st.session_state.transcript.strip():
|
514 |
if st.button("β
Finish Annotation"):
|
515 |
st.balloons()
|
516 |
st.success("π Single speaker annotation completed!")
|
517 |
+
download_link = get_download_link(st.session_state.transcript, "transcript.txt", "π₯ Download Final Transcript")
|
518 |
st.markdown(download_link, unsafe_allow_html=True)
|
519 |
|
520 |
def show_segmentation_page():
|
|
|
533 |
|
534 |
# Manual segment addition
|
535 |
st.subheader("Manual Segment Addition")
|
536 |
+
st.info("After having segmented the wav using our wav surfer, you can manually add segments here. Don't hesitate to replay and pause.")
|
537 |
col1, col2, col3, col4 = st.columns(4)
|
538 |
|
539 |
with col1:
|
|
|
674 |
|
675 |
if __name__ == "__main__":
|
676 |
main()
|
677 |
+
|