{"record":{"id":"6b06315469767dae","repo":"hcengineering/platform","slug":"no-video-tracks-found","errorCode":null,"errorMessage":"No video tracks found","messagePattern":"No video tracks found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/recorder-resources/src/utils.ts","lineNumber":120,"sourceCode":"      await new Promise((resolve) => {\n        const video = document.createElement('video')\n        video.srcObject = stream\n        video.onloadedmetadata = () => {\n          maxWidth = video.videoWidth\n          maxHeight = video.videoHeight\n          video.remove()\n          resolve(null)\n        }\n        video.play().catch(() => {\n          // Ignore play errors, just resolve\n          video.remove()\n          resolve(null)\n        })\n      })\n    }\n\n    if (maxWidth === 0 || maxHeight === 0) {\n      throw new Error('No video tracks found')\n    }\n\n    return { width: maxWidth, height: maxHeight }\n  }\n\n  throw new Error('No video tracks found')\n}\n\nexport function whenStreamEnded (stream: MediaStream, callback: () => void): void {\n  const tracks = stream.getTracks()\n\n  const cleanup = (): void => {\n    callback()\n\n    for (const track of tracks) {\n      track.onended = null\n    }\n  }","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/plugins/recorder-resources/src/utils.ts#L102-L138","documentation":"`getVideoDimensions(stream)` resolves video width/height from the stream's video track settings. When the settings report zero width or height, it falls back to loading the stream into a temporary `<video>` element and reading `videoWidth`/`videoHeight`. If that fallback still yields zero dimensions, it throws 'No video tracks found'. Despite the message, the real problem here is that video track settings and metadata loading both produced no usable dimensions — the stream has video tracks but they carry no resolvable size (e.g. track ended or settings unavailable).","triggerScenarios":"Passing a stream whose video tracks exist but report `width`/`height` of 0 or undefined AND whose `<video>` metadata load yields 0 (e.g. tracks already ended/muted, or the video element failed to load metadata before resolving); calling on a stream after its tracks were stopped.","commonSituations":"Firefox tracks missing width/height in `getSettings()` combined with `video.play()` being blocked or metadata not loaded; measuring a canvas/screen stream after the share was cancelled; capturing dimensions from a stale stream stored before a device switch.","solutions":["Ensure the stream has live, enabled video tracks before calling: check `track.readyState === 'live'`.","Call `getVideoDimensions` soon after the stream is obtained, before any track could end.","Await any stream setup (e.g. `video.play()` promises) in the surrounding code so metadata is ready.","Wrap the call in try/catch and fall back to a default resolution (e.g. 1280x720) for layout purposes.","On Firefox specifically, retry the metadata load once with a user-gesture-driven play if autoplay was blocked."],"exampleFix":"// before\nconst { width, height } = await getVideoDimensions(oldStream)\n\n// after\nconst tracks = oldStream.getVideoTracks().filter(t => t.readyState === 'live')\nif (tracks.length === 0) return { width: 1280, height: 720 }\nconst { width, height } = await getVideoDimensions(new MediaStream(tracks)).catch(() => ({ width: 1280, height: 720 }))","handlingStrategy":"fallback","validationCode":"const liveVideoTracks = stream.getVideoTracks().filter(t => t.readyState === 'live')\nif (liveVideoTracks.length === 0) return { width: 1280, height: 720 }","typeGuard":"function hasLiveVideoTrack(stream: MediaStream): boolean {\n  return stream.getVideoTracks().some(t => t.readyState === 'live')\n}","tryCatchPattern":"let dims\ntry {\n  dims = await getVideoDimensions(stream)\n} catch (err) {\n  if (err instanceof Error && err.message === 'No video tracks found') {\n    dims = { width: 1280, height: 720 } // layout fallback\n  } else throw err\n}","preventionTips":["Measure dimensions immediately after stream acquisition, before tracks can end.","Filter for `readyState === 'live'` video tracks first.","On Firefox, expect missing settings dimensions and rely on the metadata-load path; ensure `video.play()` isn't blocked by autoplay policy.","Always define sensible default dimensions for UI layout as a fallback."],"tags":["mediastream","webrtc","video-dimensions","browser-compatibility"],"backgroundTag":"no-video-tracks","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}