MCPcopy Create free account
hub / github.com/FastLED/FastLED / initializeWorkerVideoRecorder

Function initializeWorkerVideoRecorder

src/platforms/wasm/compiler/index.ts:1302–1458  ·  view source on GitHub ↗

* Initializes main-thread video recording with worker frame transfer * Worker captures frames as ImageBitmap and sends to main thread * Main thread draws to mirror canvas and uses MediaRecorder (where it's available) * @param {HTMLElement} recordButton - The record button element

(recordButton)

Source from the content-addressed store, hash-verified

1300 * @param {HTMLElement} recordButton - The record button element
1301 */
1302function initializeWorkerVideoRecorder(recordButton) {
1303 console.log('Initializing video recorder for worker mode');
1304
1305 // Check MediaRecorder support
1306 if (typeof MediaRecorder === 'undefined') {
1307 console.warn('MediaRecorder API not supported, video recording disabled');
1308 recordButton.style.display = 'none';
1309 return;
1310 }
1311
1312 // Make record button visible
1313 recordButton.classList.add('visible');
1314 console.log('Record button made visible');
1315
1316 // Try direct capture from the main canvas. After transferControlToOffscreen(),
1317 // the OffscreenCanvas content auto-syncs to the original HTMLCanvasElement.
1318 // captureStream() can capture this displayed content directly, eliminating the
1319 // expensive ImageBitmap→postMessage→mirror canvas pipeline.
1320 const mainCanvas = document.getElementById('myCanvas');
1321 let useDirectCapture = false;
1322
1323 if (mainCanvas) {
1324 try {
1325 const testStream = /** @type {HTMLCanvasElement} */ (mainCanvas).captureStream(0);
1326 if (testStream && testStream.getVideoTracks().length > 0) {
1327 testStream.getTracks().forEach((t) => t.stop());
1328 useDirectCapture = true;
1329 console.log('Direct canvas capture supported - using optimized recording pipeline (no ImageBitmap transfer)');
1330 }
1331 } catch (e) {
1332 console.log('Direct canvas capture not supported, falling back to mirror canvas:', e.message);
1333 }
1334 }
1335
1336 if (!useDirectCapture) {
1337 // Fall back to mirror canvas approach (worker sends ImageBitmap frames)
1338 setupWorkerFrameListener();
1339 }
1340
1341 let isRecording = false;
1342
1343 /**
1344 * Updates record button UI state
1345 * @param {boolean} recording - Whether currently recording
1346 */
1347 function updateRecordButtonUI(recording) {
1348 isRecording = recording;
1349
1350 if (recording) {
1351 recordButton.classList.add('recording');
1352 const recordIcon = /** @type {HTMLElement|null} */ (recordButton.querySelector('.record-icon'));
1353 const stopIcon = /** @type {HTMLElement|null} */ (recordButton.querySelector('.stop-icon'));
1354 if (recordIcon) recordIcon.style.display = 'none';
1355 if (stopIcon) stopIcon.style.display = 'block';
1356 } else {
1357 recordButton.classList.remove('recording');
1358 const recordIcon = /** @type {HTMLElement|null} */ (recordButton.querySelector('.record-icon'));
1359 const stopIcon = /** @type {HTMLElement|null} */ (recordButton.querySelector('.stop-icon'));

Callers 2

initializeVideoRecorderFunction · 0.85
tryInitializeFunction · 0.85

Calls 11

setupWorkerFrameListenerFunction · 0.85
forEachMethod · 0.80
logMethod · 0.45
addMethod · 0.45
stopMethod · 0.45
addEventListenerMethod · 0.45
errorMethod · 0.45
startRecordingMethod · 0.45
stopRecordingMethod · 0.45
removeMethod · 0.45

Tested by

no test coverage detected