|
|
|
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 { |
|
|
|
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; |
|
} |
|
|
|
|
|
|
|
|
|
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"; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
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; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 }); |
|
} |
|
} |