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

Method createPersistentVideoElement

app/src/utils/streamManager.ts:328–374  ·  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

326 * This eliminates race conditions on frame capture, especially on iOS.
327 */
328 private async createPersistentVideoElement(stream: MediaStream, timeoutMs: number = 5000): Promise<HTMLVideoElement> {
329 const video = document.createElement('video');
330 video.srcObject = stream;
331 video.muted = true;
332 video.playsInline = true;
333
334 // Wait for video to be ready with first frame
335 await new Promise<void>((resolve, reject) => {
336 const timeout = setTimeout(() => {
337 Logger.warn("StreamManager", "Video element ready timeout - proceeding anyway");
338 resolve();
339 }, timeoutMs);
340
341 const checkReady = () => {
342 // readyState >= 2 (HAVE_CURRENT_DATA) means we have at least one frame
343 if (video.readyState >= 2 && video.videoWidth > 0) {
344 clearTimeout(timeout);
345 resolve();
346 return true;
347 }
348 return false;
349 };
350
351 // Check if already ready
352 if (checkReady()) return;
353
354 // Listen for loadeddata event (fires when first frame is available)
355 video.addEventListener('loadeddata', () => {
356 if (checkReady()) return;
357 }, { once: true });
358
359 // Also listen for canplay as fallback
360 video.addEventListener('canplay', () => {
361 if (checkReady()) return;
362 }, { once: true });
363
364 // Start playing
365 video.play().catch(e => {
366 Logger.warn("StreamManager", `Video play failed: ${e}`);
367 clearTimeout(timeout);
368 reject(e);
369 });
370 });
371
372 Logger.debug("StreamManager", `Video element ready: readyState=${video.readyState}, ${video.videoWidth}x${video.videoHeight}`);
373 return video;
374 }
375
376 /**
377 * 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