MCPcopy Create free account
hub / github.com/Roy3838/Observer / createPersistentVideoElement

Method createPersistentVideoElement

app/src/utils/streamManager.ts:350–396  ·  view source on GitHub ↗

* Create a persistent video element that stays attached to a stream. * Waits for the video to be fully ready (first frame rendered) before resolving. * This eliminates race conditions on frame capture, especially on iOS.

(stream: MediaStream, timeoutMs: number = 5000)

Source from the content-addressed store, hash-verified

348 * This eliminates race conditions on frame capture, especially on iOS.
349 */
350 private async createPersistentVideoElement(stream: MediaStream, timeoutMs: number = 5000): Promise<HTMLVideoElement> {
351 const video = document.createElement('video');
352 video.srcObject = stream;
353 video.muted = true;
354 video.playsInline = true;
355
356 // Wait for video to be ready with first frame
357 await new Promise<void>((resolve, reject) => {
358 const timeout = setTimeout(() => {
359 Logger.warn("StreamManager", "Video element ready timeout - proceeding anyway");
360 resolve();
361 }, timeoutMs);
362
363 const checkReady = () => {
364 // readyState >= 2 (HAVE_CURRENT_DATA) means we have at least one frame
365 if (video.readyState >= 2 && video.videoWidth > 0) {
366 clearTimeout(timeout);
367 resolve();
368 return true;
369 }
370 return false;
371 };
372
373 // Check if already ready
374 if (checkReady()) return;
375
376 // Listen for loadeddata event (fires when first frame is available)
377 video.addEventListener('loadeddata', () => {
378 if (checkReady()) return;
379 }, { once: true });
380
381 // Also listen for canplay as fallback
382 video.addEventListener('canplay', () => {
383 if (checkReady()) return;
384 }, { once: true });
385
386 // Start playing
387 video.play().catch(e => {
388 Logger.warn("StreamManager", `Video play failed: ${e}`);
389 clearTimeout(timeout);
390 reject(e);
391 });
392 });
393
394 Logger.debug("StreamManager", `Video element ready: readyState=${video.readyState}, ${video.videoWidth}x${video.videoHeight}`);
395 return video;
396 }
397
398 /**
399 * Capture a frame from a video stream. Returns base64 PNG or null.

Callers 1

acquireMasterStreamMethod · 0.95

Calls 2

warnMethod · 0.80
debugMethod · 0.45

Tested by

no test coverage detected