Spaces:
Running on Zero
Running on Zero
Add special_type to JSON/API responses and hide animate button for transitions
Browse files- Pipeline JSON output now includes special_type field for special segments
(Amin, Takbir, Tahmeed, Basmala, etc.) with empty ref_from/ref_to
- Session API forwards special_type to clients
- Animate button hidden for transition segments (no word spans for MFA)
while Basmala/Isti'adha retain it
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- src/api/session_api.py +5 -2
- src/pipeline.py +6 -2
- src/ui/segments.py +5 -2
src/api/session_api.py
CHANGED
|
@@ -171,7 +171,7 @@ def _format_response(audio_id, json_output):
|
|
| 171 |
"""Convert pipeline json_output to the documented API response schema."""
|
| 172 |
segments = []
|
| 173 |
for seg in json_output.get("segments", []):
|
| 174 |
-
|
| 175 |
"segment": seg["segment"],
|
| 176 |
"time_from": seg["time_from"],
|
| 177 |
"time_to": seg["time_to"],
|
|
@@ -181,7 +181,10 @@ def _format_response(audio_id, json_output):
|
|
| 181 |
"confidence": seg["confidence"],
|
| 182 |
"has_missing_words": seg.get("has_missing_words", False),
|
| 183 |
"error": seg["error"],
|
| 184 |
-
}
|
|
|
|
|
|
|
|
|
|
| 185 |
resp = {"audio_id": audio_id, "segments": segments}
|
| 186 |
warning = _gpu_fallback_warning()
|
| 187 |
if warning:
|
|
|
|
| 171 |
"""Convert pipeline json_output to the documented API response schema."""
|
| 172 |
segments = []
|
| 173 |
for seg in json_output.get("segments", []):
|
| 174 |
+
entry = {
|
| 175 |
"segment": seg["segment"],
|
| 176 |
"time_from": seg["time_from"],
|
| 177 |
"time_to": seg["time_to"],
|
|
|
|
| 181 |
"confidence": seg["confidence"],
|
| 182 |
"has_missing_words": seg.get("has_missing_words", False),
|
| 183 |
"error": seg["error"],
|
| 184 |
+
}
|
| 185 |
+
if seg.get("special_type"):
|
| 186 |
+
entry["special_type"] = seg["special_type"]
|
| 187 |
+
segments.append(entry)
|
| 188 |
resp = {"audio_id": audio_id, "segments": segments}
|
| 189 |
warning = _gpu_fallback_warning()
|
| 190 |
if warning:
|
src/pipeline.py
CHANGED
|
@@ -482,18 +482,22 @@ def _run_post_vad_pipeline(
|
|
| 482 |
return parts[0], parts[1] if len(parts) > 1 else parts[0]
|
| 483 |
return matched_ref, matched_ref
|
| 484 |
|
|
|
|
|
|
|
| 485 |
segments_list = []
|
| 486 |
for i, seg in enumerate(segments):
|
|
|
|
| 487 |
segment_data = {
|
| 488 |
"segment": i + 1,
|
| 489 |
"time_from": round(seg.start_time, 3),
|
| 490 |
"time_to": round(seg.end_time, 3),
|
| 491 |
-
"ref_from": parse_ref(seg.matched_ref)[0],
|
| 492 |
-
"ref_to": parse_ref(seg.matched_ref)[1],
|
| 493 |
"matched_text": seg.matched_text or "",
|
| 494 |
"confidence": round(seg.match_score, 3),
|
| 495 |
"has_missing_words": seg.has_missing_words,
|
| 496 |
"potentially_undersegmented": seg.potentially_undersegmented,
|
|
|
|
| 497 |
"error": seg.error
|
| 498 |
}
|
| 499 |
segments_list.append(segment_data)
|
|
|
|
| 482 |
return parts[0], parts[1] if len(parts) > 1 else parts[0]
|
| 483 |
return matched_ref, matched_ref
|
| 484 |
|
| 485 |
+
from src.alignment.special_segments import ALL_SPECIAL_REFS
|
| 486 |
+
|
| 487 |
segments_list = []
|
| 488 |
for i, seg in enumerate(segments):
|
| 489 |
+
is_special = seg.matched_ref in ALL_SPECIAL_REFS
|
| 490 |
segment_data = {
|
| 491 |
"segment": i + 1,
|
| 492 |
"time_from": round(seg.start_time, 3),
|
| 493 |
"time_to": round(seg.end_time, 3),
|
| 494 |
+
"ref_from": "" if is_special else parse_ref(seg.matched_ref)[0],
|
| 495 |
+
"ref_to": "" if is_special else parse_ref(seg.matched_ref)[1],
|
| 496 |
"matched_text": seg.matched_text or "",
|
| 497 |
"confidence": round(seg.match_score, 3),
|
| 498 |
"has_missing_words": seg.has_missing_words,
|
| 499 |
"potentially_undersegmented": seg.potentially_undersegmented,
|
| 500 |
+
"special_type": seg.matched_ref if is_special else None,
|
| 501 |
"error": seg.error
|
| 502 |
}
|
| 503 |
segments_list.append(segment_data)
|
src/ui/segments.py
CHANGED
|
@@ -276,9 +276,12 @@ def render_segment_card(seg: SegmentInfo, idx: int, audio_int16: np.ndarray = No
|
|
| 276 |
audio_html = ""
|
| 277 |
if audio_int16 is not None and sample_rate > 0 and segment_dir is not None:
|
| 278 |
audio_src = encode_segment_audio(audio_int16, sample_rate, seg.start_time, seg.end_time, segment_dir, idx, inline=audio_inline)
|
| 279 |
-
# Add animate button only if segment has
|
|
|
|
|
|
|
| 280 |
animate_btn = ""
|
| 281 |
-
|
|
|
|
| 282 |
animate_btn = f'<button class="animate-btn" data-segment="{idx}" disabled>Animate</button>'
|
| 283 |
audio_html = f'''
|
| 284 |
<div class="segment-audio">
|
|
|
|
| 276 |
audio_html = ""
|
| 277 |
if audio_int16 is not None and sample_rate > 0 and segment_dir is not None:
|
| 278 |
audio_src = encode_segment_audio(audio_int16, sample_rate, seg.start_time, seg.end_time, segment_dir, idx, inline=audio_inline)
|
| 279 |
+
# Add animate button only if segment has a Quran verse ref (word spans for animation).
|
| 280 |
+
# Basmala/Isti'adha get animate because they have indexed word spans for MFA.
|
| 281 |
+
# Transition segments (Amin, Takbir, Tahmeed) don't.
|
| 282 |
animate_btn = ""
|
| 283 |
+
_ANIMATABLE_SPECIALS = {"Basmala", "Isti'adha", "Isti'adha+Basmala"}
|
| 284 |
+
if seg.matched_ref and (seg.matched_ref not in ALL_SPECIAL_REFS or seg.matched_ref in _ANIMATABLE_SPECIALS):
|
| 285 |
animate_btn = f'<button class="animate-btn" data-segment="{idx}" disabled>Animate</button>'
|
| 286 |
audio_html = f'''
|
| 287 |
<div class="segment-audio">
|