gemercheung 2 年之前
父节点
当前提交
ca3557e51f
共有 6 个文件被更改,包括 647 次插入621 次删除
  1. 2 1
      packages/core/package.json
  2. 93 49
      packages/core/src/lib/basicSimaqRecorder.ts
  3. 1 0
      play/package.json
  4. 二进制
      play/public/gs-16b-2c-44100hz.wav
  5. 11 1
      play/src/App.vue
  6. 540 570
      pnpm-lock.yaml

+ 2 - 1
packages/core/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@simaq/core",
-  "version": "1.1.3",
+  "version": "1.1.4",
   "main": "dist/index",
   "types": "dist/index",
   "files": [
@@ -22,6 +22,7 @@
     "rxjs": "~7.5.7"
   },
   "devDependencies": {
+    "@types/howler": "^2.2.7",
     "rimraf": "~3.0.2",
     "typescript": "~4.7.4"
   }

+ 93 - 49
packages/core/src/lib/basicSimaqRecorder.ts

@@ -20,7 +20,7 @@ export interface PlatformConfigType {
     minFrameRate?: number;
 }
 
-export interface InitConfigType extends DisplayMediaStreamConstraints {
+export interface InitConfigType extends MediaStreamConstraints {
     uploadUrl?: string;
     resolution?: ResolutionType;
     autoDownload?: boolean;
@@ -28,6 +28,7 @@ export interface InitConfigType extends DisplayMediaStreamConstraints {
     platform?: PlatformType;
     config?: PlatformConfigType;
     debug?: boolean;
+    disbaledAudio?: boolean;
 }
 export enum RecorderStatusType {
     init = 0,
@@ -36,11 +37,19 @@ export enum RecorderStatusType {
     end = 3,
 }
 
+interface CustomMediaStreamConstraints extends MediaStreamConstraints {
+    selfBrowserSurface?: string,
+    systemAudio?: string,
+}
 export class BasicSimaqRecorder extends EventEmitter {
-    displayMediaStreamConstraints: DisplayMediaStreamConstraints = {
+    displayMediaStreamConstraints: CustomMediaStreamConstraints = {
         video: videoConstraints.getValue(),
         // audio: audioConstraints.getValue(),
+        preferCurrentTab: true,
         audio: false,
+        // selfBrowserSurface: 'exclude',
+        systemAudio: 'exclude'
+
     };
     private isStartRecoding = false;
     private stream: MediaStream;
@@ -56,18 +65,22 @@ export class BasicSimaqRecorder extends EventEmitter {
     private canvasId: string;
     private platformConfig: PlatformConfigType;
     private chromeMediaSourceId: string | null;
-
+    private disbaledAudio = false;
+    private debug = false;
     constructor(arg: InitConfigType) {
         super();
-        console.log('arg', arg);
+
         this.autoDownload = arg.autoDownload;
         this.platform = arg.platform;
         this.platformConfig = arg.config;
         this.uploadUrl = arg.uploadUrl;
+        this.disbaledAudio = arg.disbaledAudio;
+        this.debug = arg.debug;
         this.initParams(arg);
         videoConstraints.subscribe((value) => {
-            console.log('subscribe', value);
+            this.debug && console.log('subscribe', value);
         });
+        this.debug && console.log('arg', arg);
     }
     private sleep = (ms) => new Promise((r) => setTimeout(r, ms));
 
@@ -107,7 +120,7 @@ export class BasicSimaqRecorder extends EventEmitter {
     public async startRecord(): Promise<void> {
         try {
             if (!this.isStartRecoding) {
-                console.log('开始录屏!', isSupport());
+                this.debug && console.log('开始录屏!', isSupport());
                 if (!isSupport()) {
                     console.error('当前浏览器不支持录屏或不存在https环境');
                     return;
@@ -119,7 +132,7 @@ export class BasicSimaqRecorder extends EventEmitter {
 
                 const media = await this.getDefaultMedia();
 
-                console.log('media', media);
+                this.debug && console.log('media', media);
                 if (media) {
                     this.emit('startRecord');
                     this.isStartRecoding = true;
@@ -133,7 +146,7 @@ export class BasicSimaqRecorder extends EventEmitter {
                         await this.createMediaRecoder();
                         this.mediaRecorder.start();
                         this.stream.getVideoTracks()[0].onended = () => {
-                            console.log('stop-share');
+                            this.debug && console.log('stop-share');
                             this.endRecord();
                         };
                     }
@@ -170,8 +183,7 @@ export class BasicSimaqRecorder extends EventEmitter {
                 if (audioInput) {
                     this.audioInput = audioInput;
                 }
-                console.log('audioInput', audioInput);
-                console.log('this.canvasElement', this.canvasElement);
+                this.debug && console.log('audioInput', audioInput);
                 const stream = this.canvasElement.captureStream(30);
                 if (stream) {
                     return resolve(stream);
@@ -206,7 +218,7 @@ export class BasicSimaqRecorder extends EventEmitter {
                                 this.platformConfig.minFrameRate || 30,
                         },
                     };
-                    console.log('videoConfig', videoConfig);
+                    this.debug && console.log('videoConfig', videoConfig);
                     const res = await navigator.mediaDevices.getUserMedia({
                         audio: false,
                         video: videoConfig,
@@ -227,9 +239,9 @@ export class BasicSimaqRecorder extends EventEmitter {
                 if (audioInput) {
                     this.audioInput = audioInput;
                 }
-                console.log('audioInput', audioInput);
+                this.debug && console.log('audioInput', audioInput);
                 if (navigator.mediaDevices.getDisplayMedia) {
-                    console.log(
+                    this.debug && console.log(
                         'displayMediaStreamConstraints',
                         this.displayMediaStreamConstraints,
                     );
@@ -313,6 +325,11 @@ export class BasicSimaqRecorder extends EventEmitter {
             }
         });
     }
+
+    public async setMuteMode() {
+
+    }
+
     private streamStop(): void {
         if (this.stream) {
             this.stream.getTracks().forEach((track) => track.stop());
@@ -327,44 +344,71 @@ export class BasicSimaqRecorder extends EventEmitter {
 
     private async createMediaRecoder() {
         // let mergeSteam: MediaStream;
-        let audioTrack: MediaStreamTrack, videoTrack: MediaStreamTrack;
-        if (this.audioInput) {
-            [videoTrack] = this.stream.getVideoTracks();
-            [audioTrack] = this.audioInput.getAudioTracks();
-            this.stream = new MediaStream([videoTrack, audioTrack]);
-        }
-        const globalAudioInstance = (window as any).Howler;
-        if (globalAudioInstance?.ctx) {
-            const streamDest =
-                globalAudioInstance.ctx.createMediaStreamDestination();
-            globalAudioInstance.masterGain.connect(streamDest);
-            console.log('streamDest', streamDest);
-            [videoTrack] = this.stream.getVideoTracks();
-            [audioTrack] = (streamDest.stream as MediaStream).getAudioTracks();
-            console.log('audioTrack', audioTrack);
-            this.stream = new MediaStream([videoTrack, audioTrack]);
+        try {
+            let audioTrack: MediaStreamTrack, videoTrack: MediaStreamTrack;
+            if (this.audioInput) {
+                [videoTrack] = this.stream.getVideoTracks();
+                [audioTrack] = this.audioInput.getAudioTracks();
+                this.stream = new MediaStream([videoTrack, audioTrack]);
+            }
+            const globalAudioInstance = (window as any).Howler;
+            if (globalAudioInstance?.ctx && !this.disbaledAudio) {
+                const streamAudio =
+                    globalAudioInstance.ctx.createMediaStreamDestination();
+                globalAudioInstance.masterGain.connect(streamAudio);
+                console.log('streamDest', streamAudio);
+                (window as any).streamAudio = streamAudio;
+                [videoTrack] = this.stream.getVideoTracks();
+                [audioTrack] = (streamAudio.stream as MediaStream).getAudioTracks();
+                console.log('audioTrack', audioTrack);
+                audioTrack.onended = (event) => {
+                    console.log('audioTrack-end', event);
+                    this.mediaRecorder.stop();
+                };
+                this.stream = new MediaStream([videoTrack, audioTrack]);
+            }
+
+            const mediaRecorder = new MediaRecorder(this.stream, {
+                mimeType: 'video/webm;codecs=vp9',
+                audioBitsPerSecond: videoConstraints.value.audioBitsPerSecond,
+                videoBitsPerSecond: videoConstraints.value.videoBitsPerSecond,
+            });
+            this.mediaRecorder = mediaRecorder;
+            // if (this.debug) {
+            (window as any).__SIMAQ__ = mediaRecorder;
+            // }
+
+            this.mediaRecorder.ondataavailable = (event) => {
+                this.recordChunks.push(event.data);
+                this.emit(
+                    'record',
+                    new Blob([event.data], {
+                        type: 'video/webm; codecs=webm',
+                    }),
+                );
+            };
+            this.mediaRecorder.stop = () => {
+                // setTimeout(() => {
+                //     this.handleAutoDownload();
+                // }, 1000);
+            };
+            this.mediaRecorder.onerror = (event: ErrorEvent) => {
+                console.error(`onerror stream: ${event.error.name},`, event);
+            };
+            this.mediaRecorder.onstop = (event) => {
+                console.warn(`onstop stream:`, event);
+            };
+            this.mediaRecorder.onpause = (event) => {
+                console.warn(`onpause stream: `, event);
+            };
+            this.mediaRecorder.onresume = (event) => {
+                console.warn(`onresume stream: `, event);
+            };
+
+        } catch (error) {
+            console.error('error', error)
         }
 
-        const mediaRecorder = new MediaRecorder(this.stream, {
-            mimeType: 'video/webm;codecs=vp9',
-            audioBitsPerSecond: videoConstraints.value.audioBitsPerSecond,
-            videoBitsPerSecond: videoConstraints.value.videoBitsPerSecond,
-        });
-        this.mediaRecorder = mediaRecorder;
-        this.mediaRecorder.ondataavailable = (event) => {
-            this.recordChunks.push(event.data);
-            this.emit(
-                'record',
-                new Blob([event.data], {
-                    type: 'video/webm; codecs=webm',
-                }),
-            );
-        };
-        this.mediaRecorder.stop = () => {
-            // setTimeout(() => {
-            //     this.handleAutoDownload();
-            // }, 1000);
-        };
     }
 
     private handleAutoDownload(chunks: Blob[]): void {

+ 1 - 0
play/package.json

@@ -16,6 +16,7 @@
     },
     "devDependencies": {
         "@vitejs/plugin-vue": "^3.1.2",
+        "@types/howler": "^2.2.7",
         "typescript": "^4.8.4",
         "vite": "^3.1.7",
         "vite-plugin-mkcert": "^1.10.1",

二进制
play/public/gs-16b-2c-44100hz.wav


+ 11 - 1
play/src/App.vue

@@ -10,21 +10,31 @@ import { Howler, Howl } from 'howler';
 console.log('howler', Howler, Howl);
 let sound = new Howl({
     html5: false,
-    src: ['2825345580.mp3', '2825345580.mp3'],
+    src: ['gs-16b-2c-44100hz.wav'],
 });
 const videoRecorder = new VideoRecorder({
     // uploadUrl: '',
     resolution: '4k',
     autoDownload: false,
     platform: 'web',
+    disbaledAudio: false,
     // config: {
     //     canvasId: '.goldplay__screen--canvas',
     // },
     debug: false,
 });
 console.log('videoRecorder', videoRecorder);
+sound.on('end', () => {
+    console.log('sound end');
+    // Howler.masterGain.disconnect((window as any).streamAudio);
+});
+
 videoRecorder.on('startRecord', () => {
     sound.play();
+    console.log('ctx', (window as any).Howler.ctx);
+    (window as any).Howler.ctx.onstatechange = () => {
+        console.log('onstatechange', (window as any).Howler.ctx.state);
+    };
     //开始录屏event
 });
 videoRecorder.on('record', (data: Blob) => {

文件差异内容过多而无法显示
+ 540 - 570
pnpm-lock.yaml