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

Method startVideoStream

app/src/utils/tauriStreamCapture.ts:463–658  ·  view source on GitHub ↗

* Start video-only capture stream. * Independent from audio - use startAudioStream separately if you also need audio. * Works on both desktop and iOS.

(targetId?: string)

Source from the content-addressed store, hash-verified

461 * Works on both desktop and iOS.
462 */
463 async startVideoStream(targetId?: string): Promise<VideoStreamResult> {
464 if (!isTauri()) {
465 throw new Error('Screen capture only available in Tauri');
466 }
467
468 Logger.info("TAURI_STREAM", `Starting video-only capture stream`);
469
470 // Desktop: Show selector and wait for target selection (unless a target is provided
471 // explicitly or was pre-seated via setPreselectedTarget). iOS: ReplayKit picker later.
472 let selectedTargetId: string | undefined = targetId ?? this.preselectedTargetId ?? undefined;
473 this.preselectedTargetId = null; // consume once, regardless of platform
474 if (isDesktop() && !selectedTargetId) {
475 const selected = await this.waitForTargetSelection();
476 if (!selected) {
477 throw new Error('Screen capture cancelled by user');
478 }
479 selectedTargetId = selected;
480 }
481
482 Logger.info("TAURI_STREAM", `Starting video capture with target: ${selectedTargetId || 'iOS broadcast'}`);
483
484 // Clean canvas (for AI/recording/preview). The PiP canvas only exists on mobile,
485 // where the status/timer overlay is baked into a separate stream. On desktop the
486 // overlay never draws (it's mobile-only), so a PiP canvas would be a pixel-identical
487 // copy of clean — a wasted per-frame drawImage plus a second canvas.captureStream()
488 // read-back. So on desktop we skip it and reuse the clean stream for the with-pip slot.
489 const usePip = !isDesktop();
490
491 const canvasClean = document.createElement('canvas');
492 canvasClean.width = 1920;
493 canvasClean.height = 1080;
494 const ctxClean = canvasClean.getContext('2d');
495 if (!ctxClean) {
496 throw new Error('Failed to create canvas context');
497 }
498
499 const canvasPip = usePip ? document.createElement('canvas') : null;
500 const ctxPip = canvasPip ? canvasPip.getContext('2d') : null;
501 if (canvasPip) {
502 canvasPip.width = 1920;
503 canvasPip.height = 1080;
504 if (!ctxPip) {
505 throw new Error('Failed to create PiP canvas context');
506 }
507 }
508
509 const cleanStream = canvasClean.captureStream(30);
510 const pipStream = canvasPip ? canvasPip.captureStream(30) : cleanStream;
511
512 let canvasSizeInitialized = false;
513 let frameCount = 0;
514 let isActive = true;
515
516 const frameChannel = new Channel<FrameData>();
517
518 // Coalescing decode pump: we only ever hold the NEWEST undecoded frame and decode
519 // one at a time. If frames arrive faster than we can decode+draw, the intermediate
520 // ones are dropped instead of queuing — so latency stays at ~one frame no matter how

Callers 1

Calls 9

pushCaptureConfigMethod · 0.95
getLatestBase64FrameMethod · 0.95
isTauriFunction · 0.90
isDesktopFunction · 0.90
infoMethod · 0.80
warnMethod · 0.80
debugMethod · 0.45
stopMethod · 0.45

Tested by

no test coverage detected