123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- import { Tools } from "./tools.js";
- /**
- * This can help with recording videos from BabylonJS.
- * This is based on the available WebRTC functionalities of the browser.
- *
- * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/renderToVideo
- */
- export class VideoRecorder {
- /**
- * Returns whether or not the VideoRecorder is available in your browser.
- * @param engine Defines the Babylon Engine.
- * @param canvas Defines the canvas to record. If not provided, the engine canvas will be used.
- * @returns true if supported otherwise false.
- */
- static IsSupported(engine, canvas) {
- const targetCanvas = canvas ?? engine.getRenderingCanvas();
- return !!targetCanvas && typeof targetCanvas.captureStream === "function";
- }
- /**
- * True when a recording is already in progress.
- */
- get isRecording() {
- return !!this._canvas && this._canvas.isRecording;
- }
- /**
- * Create a new VideoCapture object which can help converting what you see in Babylon to a video file.
- * @param engine Defines the BabylonJS Engine you wish to record.
- * @param options Defines options that can be used to customize the capture.
- */
- constructor(engine, options = {}) {
- if (!VideoRecorder.IsSupported(engine, options.canvas)) {
- // eslint-disable-next-line no-throw-literal
- throw "Your browser does not support recording so far.";
- }
- const canvas = options.canvas ?? engine.getRenderingCanvas();
- if (!canvas) {
- // eslint-disable-next-line no-throw-literal
- throw "The babylon engine must have a canvas to be recorded";
- }
- this._canvas = canvas;
- this._canvas.isRecording = false;
- this._options = {
- ...VideoRecorder._DefaultOptions,
- ...options,
- };
- const stream = this._canvas.captureStream(this._options.fps);
- if (this._options.audioTracks) {
- for (const track of this._options.audioTracks) {
- stream.addTrack(track);
- }
- }
- this._mediaRecorder = new MediaRecorder(stream, { mimeType: this._options.mimeType });
- this._mediaRecorder.ondataavailable = (evt) => this._handleDataAvailable(evt);
- this._mediaRecorder.onerror = (evt) => this._handleError(evt);
- this._mediaRecorder.onstop = () => this._handleStop();
- }
- /**
- * Stops the current recording before the default capture timeout passed in the startRecording function.
- */
- stopRecording() {
- if (!this._canvas || !this._mediaRecorder) {
- return;
- }
- if (!this.isRecording) {
- return;
- }
- this._canvas.isRecording = false;
- this._mediaRecorder.stop();
- }
- /**
- * Starts recording the canvas for a max duration specified in parameters.
- * @param fileName Defines the name of the file to be downloaded when the recording stop.
- * If null no automatic download will start and you can rely on the promise to get the data back.
- * @param maxDuration Defines the maximum recording time in seconds.
- * It defaults to 7 seconds. A value of zero will not stop automatically, you would need to call stopRecording manually.
- * @returns A promise callback at the end of the recording with the video data in Blob.
- */
- startRecording(fileName = "babylonjs.webm", maxDuration = 7) {
- if (!this._canvas || !this._mediaRecorder) {
- // eslint-disable-next-line no-throw-literal
- throw "Recorder has already been disposed";
- }
- if (this.isRecording) {
- // eslint-disable-next-line no-throw-literal
- throw "Recording already in progress";
- }
- if (maxDuration > 0) {
- setTimeout(() => {
- this.stopRecording();
- }, maxDuration * 1000);
- }
- this._fileName = fileName;
- this._recordedChunks = [];
- this._resolve = null;
- this._reject = null;
- this._canvas.isRecording = true;
- this._mediaRecorder.start(this._options.recordChunckSize);
- return new Promise((resolve, reject) => {
- this._resolve = resolve;
- this._reject = reject;
- });
- }
- /**
- * Releases internal resources used during the recording.
- */
- dispose() {
- this._canvas = null;
- this._mediaRecorder = null;
- this._recordedChunks = [];
- this._fileName = null;
- this._resolve = null;
- this._reject = null;
- }
- _handleDataAvailable(event) {
- if (event.data.size > 0) {
- this._recordedChunks.push(event.data);
- }
- }
- _handleError(event) {
- this.stopRecording();
- if (this._reject) {
- this._reject(event.error);
- }
- else {
- throw new event.error();
- }
- }
- _handleStop() {
- this.stopRecording();
- const superBuffer = new Blob(this._recordedChunks);
- if (this._resolve) {
- this._resolve(superBuffer);
- }
- window.URL.createObjectURL(superBuffer);
- if (this._fileName) {
- Tools.Download(superBuffer, this._fileName);
- }
- }
- }
- VideoRecorder._DefaultOptions = {
- mimeType: "video/webm",
- fps: 25,
- recordChunckSize: 3000,
- };
- //# sourceMappingURL=videoRecorder.js.map
|