openvibers/openvibe.live Commits
Clip UX: processing indicator on the clip page; dedupe clip announces
Changes
@@@ -4904,7 +4904,7 @@ https://www.101soundboards.com/sounds/12345 150p 2</code></pre><!-- Scripts --><script src="/js/theme-engine.js?v=4"></script><script src="/live-notify.js?v=2" defer></script>--<script src="/js/app.js?v=119" defer></script>++<script src="/js/app.js?v=120" defer></script><script src="/js/stream-player.js?v=17" defer></script><script src="/js/chat-shared.js?v=3" defer></script><script src="/js/emotes.js?v=8" defer></script>@@@ -6760,6 +6760,27 @@ async function loadClipPlayer(clipId) {}const video = document.getElementById('clp-video');++ clearTimeout(window._clpProcessingPoll);++ { const _n = document.getElementById('clp-processing-note'); if (_n) _n.remove(); }++ if (!cl.file_path && (cl.status || 'processing') !== 'ready') {++ // Server is still cutting this clip — show progress instead of a black++ // player, and poll until it's ready.++ video.style.display = 'none';++ const container = document.getElementById('clp-container');++ if (container) {++ const note = document.createElement('div');++ note.id = 'clp-processing-note';++ note.style.cssText = 'display:flex;flex-direction:column;align-items:center;justify-content:center;height:300px;gap:12px;color:var(--text-muted,#999)';++ note.innerHTML = `++ <i class="fa-solid fa-scissors fa-bounce" style="font-size:2.5rem;color:var(--accent)"></i>++ <p style="font-size:1.05rem;font-weight:600">Clip is processing…</p>++ <p class="muted" style="font-size:0.85rem">The server is cutting your clip — this page will update automatically.</p>`;++ container.appendChild(note);++ }++ window._clpProcessingPoll = setTimeout(() => {++ if (window._clpClipId === cl.id) loadClipPlayer(cl.id);++ }, 3000);++ }if (cl.file_path) {const filename = cl.file_path.split('/').pop();// Handle video load errors (corrupt files, codec issues)@@@ -86,12 +86,20 @@ async function _sendOne(clipId) {}let _sweepTimer = null;++// Clips whose announce is currently being sent. A slow Media getClip() once let++// six 15s sweep ticks stack up on the same clip and announce it six times when++// Media finally answered — a clip stays claimed here until its send resolves.++const _inFlight = new Set();function startClipNotifySweeper() {if (_sweepTimer) return;_sweepTimer = setInterval(() => {try {const due = db.getDueClipNotifies(20) || [];-- for (const row of due) _sendOne(row.clip_id).catch(() => {});++ for (const row of due) {++ if (_inFlight.has(row.clip_id)) continue;++ _inFlight.add(row.clip_id);++ _sendOne(row.clip_id).catch(() => {}).finally(() => _inFlight.delete(row.clip_id));++ }} catch (e) { console.warn('[ClipNotify] sweep error:', e.message); }}, SWEEP_INTERVAL_MS);if (_sweepTimer.unref) _sweepTimer.unref();
@@ -4904,7 +4904,7 @@ https://www.101soundboards.com/sounds/12345 150p 2</code></pre>
@@ -4904,7 +4904,7 @@ https://www.101soundboards.com/sounds/12345 150p 2</code></pre>
<!-- Scripts -->
<!-- Scripts -->
<script src="/js/theme-engine.js?v=4"></script>
<script src="/js/theme-engine.js?v=4"></script>
<script src="/live-notify.js?v=2" defer></script>
<script src="/live-notify.js?v=2" defer></script>
-<script src="/js/app.js?v=119" defer></script>
+<script src="/js/app.js?v=120" defer></script>
<script src="/js/stream-player.js?v=17" defer></script>
<script src="/js/stream-player.js?v=17" defer></script>
<script src="/js/chat-shared.js?v=3" defer></script>
<script src="/js/chat-shared.js?v=3" defer></script>
<script src="/js/emotes.js?v=8" defer></script>
<script src="/js/emotes.js?v=8" defer></script>
@@ -6760,6 +6760,27 @@ async function loadClipPlayer(clipId) {
@@ -6760,6 +6760,27 @@ async function loadClipPlayer(clipId) {
}
}
const video = document.getElementById('clp-video');
const video = document.getElementById('clp-video');
+ clearTimeout(window._clpProcessingPoll);
+ { const _n = document.getElementById('clp-processing-note'); if (_n) _n.remove(); }
+ if (!cl.file_path && (cl.status || 'processing') !== 'ready') {
+ // Server is still cutting this clip — show progress instead of a black
+ // player, and poll until it's ready.
+ video.style.display = 'none';
+ const container = document.getElementById('clp-container');
+ if (container) {
+ const note = document.createElement('div');
+ note.id = 'clp-processing-note';
+ note.style.cssText = 'display:flex;flex-direction:column;align-items:center;justify-content:center;height:300px;gap:12px;color:var(--text-muted,#999)';
+ note.innerHTML = `
+ <i class="fa-solid fa-scissors fa-bounce" style="font-size:2.5rem;color:var(--accent)"></i>
+ <p style="font-size:1.05rem;font-weight:600">Clip is processing…</p>
+ <p class="muted" style="font-size:0.85rem">The server is cutting your clip — this page will update automatically.</p>`;
+ container.appendChild(note);
+ }
+ window._clpProcessingPoll = setTimeout(() => {
+ if (window._clpClipId === cl.id) loadClipPlayer(cl.id);
+ }, 3000);
+ }
if (cl.file_path) {
if (cl.file_path) {
const filename = cl.file_path.split('/').pop();
const filename = cl.file_path.split('/').pop();
// Handle video load errors (corrupt files, codec issues)
// Handle video load errors (corrupt files, codec issues)
@@ -86,12 +86,20 @@ async function _sendOne(clipId) {
@@ -86,12 +86,20 @@ async function _sendOne(clipId) {
}
}
let _sweepTimer = null;
let _sweepTimer = null;
+// Clips whose announce is currently being sent. A slow Media getClip() once let
+// six 15s sweep ticks stack up on the same clip and announce it six times when
+// Media finally answered — a clip stays claimed here until its send resolves.
+const _inFlight = new Set();
function startClipNotifySweeper() {
function startClipNotifySweeper() {
if (_sweepTimer) return;
if (_sweepTimer) return;
_sweepTimer = setInterval(() => {
_sweepTimer = setInterval(() => {
try {
try {
const due = db.getDueClipNotifies(20) || [];
const due = db.getDueClipNotifies(20) || [];
- for (const row of due) _sendOne(row.clip_id).catch(() => {});
+ for (const row of due) {
+ if (_inFlight.has(row.clip_id)) continue;
+ _inFlight.add(row.clip_id);
+ _sendOne(row.clip_id).catch(() => {}).finally(() => _inFlight.delete(row.clip_id));
+ }
} catch (e) { console.warn('[ClipNotify] sweep error:', e.message); }
} catch (e) { console.warn('[ClipNotify] sweep error:', e.message); }
}, SWEEP_INTERVAL_MS);
}, SWEEP_INTERVAL_MS);
if (_sweepTimer.unref) _sweepTimer.unref();
if (_sweepTimer.unref) _sweepTimer.unref();