// recorder.js var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; const BLOB_TYPE = "video/webm"; class ScreenCastRecorder { /** True if the current browser likely supports screencasts. */ static isSupportedBrowser() { return (navigator.mediaDevices != null && navigator.mediaDevices.getUserMedia != null && navigator.mediaDevices.getDisplayMedia != null && MediaRecorder.isTypeSupported(BLOB_TYPE)); } constructor({ recordAudio, onErrorOrStop }) { this.recordAudio = recordAudio; this.onErrorOrStopCallback = onErrorOrStop; this.inputStream = null; this.recordedChunks = []; this.mediaRecorder = null; } /** * This asynchronous method will initialize the screen recording object asking * for permissions to the user which are needed to start recording. */ initialize() { return __awaiter(this, void 0, void 0, function* () { const desktopStream = yield navigator.mediaDevices.getDisplayMedia({ video: true, }); let tracks = desktopStream.getTracks(); if (this.recordAudio) { const voiceStream = yield navigator.mediaDevices.getUserMedia({ video: false, audio: true, }); tracks = tracks.concat(voiceStream.getAudioTracks()); } this.recordedChunks = []; this.inputStream = new MediaStream(tracks); this.mediaRecorder = new MediaRecorder(this.inputStream, { mimeType: BLOB_TYPE, }); this.mediaRecorder.ondataavailable = e => this.recordedChunks.push(e.data); }); } getState() { if (this.mediaRecorder) { return this.mediaRecorder.state; } return "inactive"; } /** * This method will start the screen recording if the user has granted permissions * and the mediaRecorder has been initialized * * @returns {boolean} */ start() { if (!this.mediaRecorder) { console.warn(`ScreenCastRecorder.start: mediaRecorder is null`); return false; } const logRecorderError = (e) => { console.warn(`mediaRecorder.start threw an error: ${e}`); }; this.mediaRecorder.onerror = (e) => { logRecorderError(e); this.onErrorOrStopCallback(); }; this.mediaRecorder.onstop = () => this.onErrorOrStopCallback(); try { this.mediaRecorder.start(); } catch (e) { logRecorderError(e); return false; } return true; } /** * This method will stop recording and then return the generated Blob * * @returns {(Promise|undefined)} * A Promise which will return the generated Blob * Undefined if the MediaRecorder could not initialize */ stop() { if (!this.mediaRecorder) { return undefined; } let resolver; const promise = new Promise(r => { resolver = r; }); this.mediaRecorder.onstop = () => resolver(); this.mediaRecorder.stop(); if (this.inputStream) { this.inputStream.getTracks().forEach(s => s.stop()); this.inputStream = null; } return promise.then(() => this.buildOutputBlob()); } buildOutputBlob() { return new Blob(this.recordedChunks, { type: BLOB_TYPE }); } }