|
@@ -2,8 +2,8 @@ import { audioConstraints } from './audioConstraints';
|
|
|
import { videoConstraints } from './videoConstraints';
|
|
|
import { isSupport } from './isSupport';
|
|
|
import { getVideo } from './videoElement';
|
|
|
-// import { BehaviorSubject } from 'rxjs';
|
|
|
import { EventEmitter } from 'eventemitter3';
|
|
|
+
|
|
|
export type ResolutionType = '1080p' | '2k' | '4k';
|
|
|
export interface InitConfigType extends DisplayMediaStreamConstraints {
|
|
|
uploadUrl: '';
|
|
@@ -11,6 +11,12 @@ export interface InitConfigType extends DisplayMediaStreamConstraints {
|
|
|
autoDownload?: boolean;
|
|
|
debug?: boolean;
|
|
|
}
|
|
|
+export enum RecorderStatusType {
|
|
|
+ init = 0,
|
|
|
+ start = 1,
|
|
|
+ hold = 2,
|
|
|
+ end = 3,
|
|
|
+}
|
|
|
export class BasicSimaqRecorder extends EventEmitter {
|
|
|
displayMediaStreamConstraints: DisplayMediaStreamConstraints = {
|
|
|
video: videoConstraints.getValue(),
|
|
@@ -20,9 +26,11 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
private stream: MediaStream;
|
|
|
private audioInput: MediaStream;
|
|
|
private mediaRecorder: MediaRecorder;
|
|
|
+ public status: RecorderStatusType = 0;
|
|
|
// public record = new BehaviorSubject<Blob>(null);
|
|
|
private recordChunks: Blob[] = [];
|
|
|
private autoDownload = false;
|
|
|
+ private passiveEnd = false;
|
|
|
|
|
|
constructor(arg: InitConfigType) {
|
|
|
super();
|
|
@@ -32,6 +40,7 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
console.log('subscribe', value);
|
|
|
});
|
|
|
}
|
|
|
+ private sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
|
|
public async startRecord(): Promise<void> {
|
|
|
if (!this.isStartRecoding) {
|
|
@@ -40,10 +49,13 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
console.error('当前浏览器不支持录屏或不存在https环境');
|
|
|
return;
|
|
|
}
|
|
|
- this.isStartRecoding = true;
|
|
|
+
|
|
|
const media = await this.getDisplayMedia();
|
|
|
+ console.log('media', media);
|
|
|
if (media) {
|
|
|
this.emit('startRecord');
|
|
|
+ this.isStartRecoding = true;
|
|
|
+ this.status = RecorderStatusType.start;
|
|
|
// console.log('media', media);
|
|
|
const video: HTMLVideoElement = getVideo();
|
|
|
if (video) {
|
|
@@ -57,6 +69,8 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
this.endRecord();
|
|
|
};
|
|
|
}
|
|
|
+ } else {
|
|
|
+ this.endRecord();
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -99,15 +113,40 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- public endRecord(): void {
|
|
|
+ public holdRecord(): void {
|
|
|
this.isStartRecoding = false;
|
|
|
+ this.status = RecorderStatusType.hold;
|
|
|
this.streamStop();
|
|
|
- this.emit('endRecord');
|
|
|
+ }
|
|
|
+
|
|
|
+ public async endRecord(): Promise<Blob[]> {
|
|
|
+ return new Promise<Blob[]>(async (resolve) => {
|
|
|
+ try {
|
|
|
+ this.streamStop();
|
|
|
+ await this.sleep(1000);
|
|
|
+ this.isStartRecoding = false;
|
|
|
+ this.status = RecorderStatusType.end;
|
|
|
+ const blobs = this.recordChunks.slice();
|
|
|
+ console.log('last-dump', blobs);
|
|
|
+ if (this.autoDownload) {
|
|
|
+ blobs?.length && this.handleAutoDownload(blobs);
|
|
|
+ }
|
|
|
+ this.emit('endRecord', blobs);
|
|
|
+ this.passiveEnd = false;
|
|
|
+ this.recordChunks = [];
|
|
|
+ resolve(blobs);
|
|
|
+ } catch (error) {
|
|
|
+ resolve([]);
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
private streamStop(): void {
|
|
|
if (this.stream) {
|
|
|
this.stream.getTracks().forEach((track) => track.stop());
|
|
|
}
|
|
|
+ if (this.audioInput) {
|
|
|
+ this.audioInput.getTracks().forEach((track) => track.stop());
|
|
|
+ }
|
|
|
if (this.mediaRecorder) {
|
|
|
this.mediaRecorder.stop();
|
|
|
}
|
|
@@ -129,7 +168,6 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
});
|
|
|
this.mediaRecorder = mediaRecorder;
|
|
|
this.mediaRecorder.ondataavailable = (event) => {
|
|
|
- // console.log('ondataavailable', event.data);
|
|
|
this.recordChunks.push(event.data);
|
|
|
this.emit(
|
|
|
'record',
|
|
@@ -139,29 +177,24 @@ export class BasicSimaqRecorder extends EventEmitter {
|
|
|
);
|
|
|
};
|
|
|
this.mediaRecorder.stop = () => {
|
|
|
- setTimeout(() => {
|
|
|
- this.handleAutoDownload();
|
|
|
- this.recordChunks = [];
|
|
|
- // this.record.next(null);
|
|
|
- }, 1000);
|
|
|
+ // setTimeout(() => {
|
|
|
+ // this.handleAutoDownload();
|
|
|
+ // }, 1000);
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- private handleAutoDownload(): void {
|
|
|
- if (this.autoDownload) {
|
|
|
- // console.log('recordChunks', this.recordChunks);
|
|
|
- const downloadBlob = new Blob(this.recordChunks, {
|
|
|
- type: 'video/mp4; codecs=h264',
|
|
|
- });
|
|
|
- const url = URL.createObjectURL(downloadBlob);
|
|
|
- const a: HTMLAnchorElement = document.createElement('a');
|
|
|
- document.body.appendChild(a);
|
|
|
- a.style.display = 'none';
|
|
|
- a.href = url;
|
|
|
- a.download = 'test.mp4';
|
|
|
- a.click();
|
|
|
- window.URL.revokeObjectURL(url);
|
|
|
- }
|
|
|
+ private handleAutoDownload(chunks: Blob[]): void {
|
|
|
+ const downloadBlob = new Blob(chunks, {
|
|
|
+ type: 'video/mp4; codecs=h264',
|
|
|
+ });
|
|
|
+ const url = URL.createObjectURL(downloadBlob);
|
|
|
+ const a: HTMLAnchorElement = document.createElement('a');
|
|
|
+ document.body.appendChild(a);
|
|
|
+ a.style.display = 'none';
|
|
|
+ a.href = url;
|
|
|
+ a.download = 'test.mp4';
|
|
|
+ a.click();
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
}
|
|
|
|
|
|
private uploadToServer(): void { }
|