Spaces:
Running on Zero
Running on Zero
Commit ·
0378fbe
1
Parent(s): c97fd8e
fix: draw and hit-test segments by unique region to prevent overlap highlight bleed
Browse filesSegment color blocks and click targets were drawn using each segment's full
[start, end] span. Since windows overlap (e.g. seg0=0-8s, seg1=6-14s), this
caused adjacent segment colors to visually bleed into each other, and clicking
in an overlap zone would ambiguously match multiple segments.
Fix: each segment now owns only [start, nextSeg.start) visually and for click
detection, with the final segment owning [start, end]. This means exactly one
colored block is highlighted during regen and clicks always target precisely
the visible segment the user clicked on.
app.py
CHANGED
|
@@ -1123,8 +1123,14 @@ def _build_regen_pending_html(segments: list, regen_seg_idx: int, slot_id: str,
|
|
| 1123 |
|
| 1124 |
seg_divs = ""
|
| 1125 |
for i, seg in enumerate(segments):
|
| 1126 |
-
|
| 1127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1128 |
color = active_color if i == regen_seg_idx else seg_colors[i % len(seg_colors)]
|
| 1129 |
extra = "border:2px solid #ffb300;animation:wf_pulse 0.8s ease-in-out infinite alternate;" if i == regen_seg_idx else ""
|
| 1130 |
seg_divs += (
|
|
@@ -1262,10 +1268,14 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
|
|
| 1262 |
ctx.fillRect(0, 0, W, H);
|
| 1263 |
|
| 1264 |
segments.forEach(function(seg, idx) {{
|
|
|
|
|
|
|
| 1265 |
const x1 = (seg[0] / duration) * W;
|
| 1266 |
-
const
|
|
|
|
|
|
|
| 1267 |
ctx.fillStyle = segColors[idx % segColors.length];
|
| 1268 |
-
ctx.fillRect(x1, 0,
|
| 1269 |
ctx.fillStyle = 'rgba(255,255,255,0.6)';
|
| 1270 |
ctx.font = '10px sans-serif';
|
| 1271 |
ctx.fillText('Seg '+(idx+1), x1+3, 12);
|
|
@@ -1300,8 +1310,13 @@ def _build_waveform_html(audio_path: str, segments: list, slot_id: str,
|
|
| 1300 |
const r=cv.getBoundingClientRect();
|
| 1301 |
const xRel=(e.clientX-r.left)/r.width;
|
| 1302 |
const tClick=xRel*duration;
|
|
|
|
|
|
|
| 1303 |
let hit=-1;
|
| 1304 |
-
segments.forEach(function(seg,idx){{
|
|
|
|
|
|
|
|
|
|
| 1305 |
console.log('[wf click] tClick='+tClick.toFixed(2)+' hit='+hit+' audioDuration='+audioDuration+' segments='+JSON.stringify(segments));
|
| 1306 |
if (hit>=0) showPopup(hit, e.clientX, e.clientY);
|
| 1307 |
else hidePopup();
|
|
|
|
| 1123 |
|
| 1124 |
seg_divs = ""
|
| 1125 |
for i, seg in enumerate(segments):
|
| 1126 |
+
# Draw only the non-overlapping (unique) portion of each segment so that
|
| 1127 |
+
# overlapping windows don't visually bleed into adjacent segments.
|
| 1128 |
+
# Each segment owns the region from its own start up to the next segment's
|
| 1129 |
+
# start (or its own end for the final segment).
|
| 1130 |
+
seg_start = seg[0]
|
| 1131 |
+
seg_end = segments[i + 1][0] if i + 1 < len(segments) else seg[1]
|
| 1132 |
+
left_pct = seg_start / duration * 100
|
| 1133 |
+
width_pct = (seg_end - seg_start) / duration * 100
|
| 1134 |
color = active_color if i == regen_seg_idx else seg_colors[i % len(seg_colors)]
|
| 1135 |
extra = "border:2px solid #ffb300;animation:wf_pulse 0.8s ease-in-out infinite alternate;" if i == regen_seg_idx else ""
|
| 1136 |
seg_divs += (
|
|
|
|
| 1268 |
ctx.fillRect(0, 0, W, H);
|
| 1269 |
|
| 1270 |
segments.forEach(function(seg, idx) {{
|
| 1271 |
+
// Draw only each segment's unique (non-overlapping) region:
|
| 1272 |
+
// from its start up to the next segment's start, or its own end if last.
|
| 1273 |
const x1 = (seg[0] / duration) * W;
|
| 1274 |
+
const xEnd = idx + 1 < segments.length
|
| 1275 |
+
? (segments[idx + 1][0] / duration) * W
|
| 1276 |
+
: (seg[1] / duration) * W;
|
| 1277 |
ctx.fillStyle = segColors[idx % segColors.length];
|
| 1278 |
+
ctx.fillRect(x1, 0, xEnd - x1, H);
|
| 1279 |
ctx.fillStyle = 'rgba(255,255,255,0.6)';
|
| 1280 |
ctx.font = '10px sans-serif';
|
| 1281 |
ctx.fillText('Seg '+(idx+1), x1+3, 12);
|
|
|
|
| 1310 |
const r=cv.getBoundingClientRect();
|
| 1311 |
const xRel=(e.clientX-r.left)/r.width;
|
| 1312 |
const tClick=xRel*duration;
|
| 1313 |
+
// Pick the segment whose unique (non-overlapping) region contains the click.
|
| 1314 |
+
// Each segment owns [seg[0], nextSeg[0]) visually; last segment owns [seg[0], seg[1]].
|
| 1315 |
let hit=-1;
|
| 1316 |
+
segments.forEach(function(seg,idx){{
|
| 1317 |
+
const uniqueEnd = idx + 1 < segments.length ? segments[idx+1][0] : seg[1];
|
| 1318 |
+
if (tClick >= seg[0] && tClick < uniqueEnd) hit = idx;
|
| 1319 |
+
}});
|
| 1320 |
console.log('[wf click] tClick='+tClick.toFixed(2)+' hit='+hit+' audioDuration='+audioDuration+' segments='+JSON.stringify(segments));
|
| 1321 |
if (hit>=0) showPopup(hit, e.clientX, e.clientY);
|
| 1322 |
else hidePopup();
|