Просмотр исходного кода

video/webm;codecs=vp9,opus 处理兼容问题火狐浏览器

tangning 2 дней назад
Родитель
Сommit
98736ae84f
33 измененных файлов с 692 добавлено и 4 удалено
  1. 3 0
      src/util/simaqcore/index.d.ts
  2. 1 0
      src/util/simaqcore/index.d.ts.map
  3. 3 0
      src/util/simaqcore/index.js
  4. 1 0
      src/util/simaqcore/index.js.map
  5. 3 0
      src/util/simaqcore/lib/audioConstraints.d.ts
  6. 1 0
      src/util/simaqcore/lib/audioConstraints.d.ts.map
  7. 11 0
      src/util/simaqcore/lib/audioConstraints.js
  8. 1 0
      src/util/simaqcore/lib/audioConstraints.js.map
  9. 81 0
      src/util/simaqcore/lib/basicSimaqRecorder.d.ts
  10. 1 0
      src/util/simaqcore/lib/basicSimaqRecorder.d.ts.map
  11. 429 0
      src/util/simaqcore/lib/basicSimaqRecorder.js
  12. 1 0
      src/util/simaqcore/lib/basicSimaqRecorder.js.map
  13. 6 0
      src/util/simaqcore/lib/init.d.ts
  14. 1 0
      src/util/simaqcore/lib/init.d.ts.map
  15. 53 0
      src/util/simaqcore/lib/init.js
  16. 1 0
      src/util/simaqcore/lib/init.js.map
  17. 2 0
      src/util/simaqcore/lib/isSupport.d.ts
  18. 1 0
      src/util/simaqcore/lib/isSupport.d.ts.map
  19. 2 0
      src/util/simaqcore/lib/isSupport.js
  20. 1 0
      src/util/simaqcore/lib/isSupport.js.map
  21. 4 0
      src/util/simaqcore/lib/sdk.d.ts
  22. 1 0
      src/util/simaqcore/lib/sdk.d.ts.map
  23. 4 0
      src/util/simaqcore/lib/sdk.js
  24. 1 0
      src/util/simaqcore/lib/sdk.js.map
  25. 8 0
      src/util/simaqcore/lib/videoConstraints.d.ts
  26. 1 0
      src/util/simaqcore/lib/videoConstraints.d.ts.map
  27. 5 0
      src/util/simaqcore/lib/videoConstraints.js
  28. 1 0
      src/util/simaqcore/lib/videoConstraints.js.map
  29. 4 0
      src/util/simaqcore/lib/videoElement.d.ts
  30. 1 0
      src/util/simaqcore/lib/videoElement.d.ts.map
  31. 23 0
      src/util/simaqcore/lib/videoElement.js
  32. 1 0
      src/util/simaqcore/lib/videoElement.js.map
  33. 35 4
      src/view/newFireCase/newFireDetails/components/shot.vue

+ 3 - 0
src/util/simaqcore/index.d.ts

@@ -0,0 +1,3 @@
+export * from './lib/init';
+export { RecorderStatusType } from './lib/basicSimaqRecorder';
+//# sourceMappingURL=index.d.ts.map

+ 1 - 0
src/util/simaqcore/index.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}

+ 3 - 0
src/util/simaqcore/index.js

@@ -0,0 +1,3 @@
+export * from './lib/init';
+export { RecorderStatusType } from './lib/basicSimaqRecorder';
+//# sourceMappingURL=index.js.map

+ 1 - 0
src/util/simaqcore/index.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}

+ 3 - 0
src/util/simaqcore/lib/audioConstraints.d.ts

@@ -0,0 +1,3 @@
+import { BehaviorSubject } from 'rxjs';
+export declare const audioConstraints: BehaviorSubject<MediaTrackConstraints>;
+//# sourceMappingURL=audioConstraints.d.ts.map

+ 1 - 0
src/util/simaqcore/lib/audioConstraints.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"audioConstraints.d.ts","sourceRoot":"","sources":["../../src/lib/audioConstraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAEvC,eAAO,MAAM,gBAAgB,wCAQ3B,CAAC"}

+ 11 - 0
src/util/simaqcore/lib/audioConstraints.js

@@ -0,0 +1,11 @@
+import { BehaviorSubject } from 'rxjs';
+export const audioConstraints = new BehaviorSubject({
+    autoGainControl: true,
+    echoCancellation: true,
+    noiseSuppression: true,
+    latency: 0,
+    channelCount: 2,
+    sampleRate: 44100,
+    suppressLocalAudioPlayback: false,
+});
+//# sourceMappingURL=audioConstraints.js.map

+ 1 - 0
src/util/simaqcore/lib/audioConstraints.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"audioConstraints.js","sourceRoot":"","sources":["../../src/lib/audioConstraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAEvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,eAAe,CAAwB;IACvE,eAAe,EAAE,IAAI;IACrB,gBAAgB,EAAE,IAAI;IACtB,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE,CAAC;IACV,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,KAAK;IACjB,0BAA0B,EAAE,KAAK;CACpC,CAAC,CAAC"}

+ 81 - 0
src/util/simaqcore/lib/basicSimaqRecorder.d.ts

@@ -0,0 +1,81 @@
+import { EventEmitter } from 'eventemitter3';
+export declare type ResolutionType = '1080p' | '2k' | '4k';
+export declare type PlatformType = 'web' | 'electron' | 'canvas';
+export interface PlatformConfigType {
+    chromeMediaSourceId?: string | null;
+    canvasId?: string;
+    minWidth?: number;
+    maxWidth?: number;
+    minHeight?: number;
+    maxHeight?: number;
+    frameRate?: number;
+    maxFrameRate?: number;
+    minFrameRate?: number;
+}
+export interface InitConfigType extends MediaStreamConstraints {
+    uploadUrl?: string;
+    resolution?: ResolutionType;
+    autoDownload?: boolean;
+    isElectron?: boolean;
+    platform?: PlatformType;
+    config?: PlatformConfigType;
+    debug?: boolean;
+    debugShowVideo?: boolean;
+    disabledAudio?: boolean;
+    systemAudio?: boolean;
+}
+export declare enum RecorderStatusType {
+    init = 0,
+    start = 1,
+    hold = 2,
+    end = 3
+}
+interface CustomMediaStreamConstraints extends MediaStreamConstraints {
+    selfBrowserSurface?: string;
+    systemAudio?: string;
+}
+export declare class BasicSimaqRecorder extends EventEmitter {
+    displayMediaStreamConstraints: CustomMediaStreamConstraints;
+    private isStartRecoding;
+    private stream;
+    private audioInput;
+    private mediaRecorder;
+    status: RecorderStatusType;
+    private recordChunks;
+    private autoDownload;
+    private passiveEnd;
+    private platform;
+    private uploadUrl;
+    private canvasId;
+    private platformConfig;
+    private chromeMediaSourceId;
+    private disabledAudio;
+    private systemAudio;
+    private debug;
+    private codecType;
+    private codecFileType;
+    constructor(arg: InitConfigType);
+    private sleep;
+    private get isElectron();
+    private get isWeb();
+    private get isCanvas();
+    private get canvasElement();
+    private set canvasElement(value);
+    private initParams;
+    private setSystemAudio;
+    startRecord(): Promise<void>;
+    private getDefaultMedia;
+    private getCanvasSteam;
+    private getEletronDisplayMedia;
+    private getDisplayMedia;
+    private getDeaultAudio;
+    private getEletronDeaultAudio;
+    holdRecord(): void;
+    endRecord(): Promise<Blob[]>;
+    private streamStop;
+    private createMediaRecoder;
+    private handleAutoDownload;
+    updateCanvas(canvas: HTMLCanvasElement): void;
+}
+export {};
+//# sourceMappingURL=basicSimaqRecorder.d.ts.map

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/util/simaqcore/lib/basicSimaqRecorder.d.ts.map


+ 429 - 0
src/util/simaqcore/lib/basicSimaqRecorder.js

@@ -0,0 +1,429 @@
+import { videoConstraints } from './videoConstraints';
+import { isSupport } from './isSupport';
+import { getVideo } from './videoElement';
+import { EventEmitter } from 'eventemitter3';
+export var RecorderStatusType;
+(function (RecorderStatusType) {
+    RecorderStatusType[RecorderStatusType["init"] = 0] = "init";
+    RecorderStatusType[RecorderStatusType["start"] = 1] = "start";
+    RecorderStatusType[RecorderStatusType["hold"] = 2] = "hold";
+    RecorderStatusType[RecorderStatusType["end"] = 3] = "end";
+})(RecorderStatusType || (RecorderStatusType = {}));
+function getSupportedMimeType() {
+      const firefoxMimeTypes = [
+        'video/webm;codecs=vp8,opus',
+        'video/webm'
+      ];
+      const defaultMimeTypes = [
+        'video/webm;codecs=vp9,opus',
+        'video/webm;codecs=vp8,opus',
+        'video/webm',
+        'video/mp4'
+      ];
+      const isFirefox = /firefox/i.test(navigator.userAgent);
+      const mimeTypes = isFirefox ? firefoxMimeTypes : defaultMimeTypes;
+
+      for (const type of mimeTypes) {
+        if (MediaRecorder && MediaRecorder.isTypeSupported(type)) {
+          return type;
+        }
+      }
+      return null;
+    }
+export class BasicSimaqRecorder extends EventEmitter {
+    // private codecH264Type = 'video/mp4;codecs=h264,opus';
+    constructor(arg) {
+        super();
+        this.displayMediaStreamConstraints = {
+            video: videoConstraints.getValue(),
+            // audio: audioConstraints.getValue(),
+            preferCurrentTab: true,
+            audio: false,
+            // selfBrowserSurface: 'exclude',
+            systemAudio: 'exclude',
+        };
+        this.isStartRecoding = false;
+        this.status = 0;
+        // public record = new BehaviorSubject<Blob>(null);
+        this.recordChunks = [];
+        this.autoDownload = false;
+        this.passiveEnd = false;
+        this.disabledAudio = false;
+        this.systemAudio = false;
+        this.debug = false;
+        this.codecType = getSupportedMimeType() || 'video/webm;codecs=vp9,opus';
+        this.codecFileType = 'video/webm';
+        this.sleep = (ms) => new Promise((r) => setTimeout(r, ms));
+        this.autoDownload = arg.autoDownload;
+        this.platform = arg.platform;
+        this.platformConfig = arg.config;
+        this.uploadUrl = arg.uploadUrl;
+        this.disabledAudio = arg.disabledAudio;
+        this.debug = arg.debug;
+        this.systemAudio = arg.systemAudio;
+        this.setSystemAudio();
+        this.initParams(arg);
+        videoConstraints.subscribe((value) => {
+            this.debug && console.log('subscribe', value);
+            this.displayMediaStreamConstraints.video = Object.assign({}, this.displayMediaStreamConstraints.video, value);
+        });
+        this.debug && console.log('arg', arg);
+    }
+    get isElectron() {
+        return this.platform === 'electron';
+    }
+    get isWeb() {
+        return this.platform === 'web';
+    }
+    get isCanvas() {
+        return this.platform === 'canvas';
+    }
+    get canvasElement() {
+        // return document.getElementById(this.canvasId);
+        return document.querySelector(this.canvasId);
+    }
+    set canvasElement(canvas) {
+        this.canvasElement = canvas;
+    }
+    initParams(arg) {
+        switch (arg.platform) {
+            case 'web':
+                if (arg.config.frameRate) {
+                    videoConstraints.value.frameRate = arg.config.frameRate;
+                }
+                break;
+            case 'electron':
+                this.chromeMediaSourceId = arg.config.chromeMediaSourceId;
+                break;
+            case 'canvas':
+                this.canvasId = arg.config.canvasId;
+                break;
+            default:
+                break;
+        }
+    }
+    setSystemAudio() {
+        if (this.systemAudio) {
+            this.displayMediaStreamConstraints.systemAudio = 'include';
+            this.displayMediaStreamConstraints.audio = true;
+        }
+        else {
+            this.displayMediaStreamConstraints.systemAudio = 'exclude';
+            this.displayMediaStreamConstraints.audio = false;
+        }
+    }
+    async startRecord() {
+        try {
+            if (!this.isStartRecoding) {
+                this.debug && console.log('开始录屏!', isSupport());
+                if (!isSupport()) {
+                    console.error('当前浏览器不支持录屏或不存在https环境');
+                    return;
+                }
+                // const media = this.isElectron
+                //     ? await this.getEletronDisplayMedia()
+                //     : await this.getDisplayMedia();
+                const media = await this.getDefaultMedia();
+                this.debug && console.log('media', media);
+                if (media) {
+                    this.emit('startRecord');
+                    this.isStartRecoding = true;
+                    this.status = RecorderStatusType.start;
+                    // console.log('media', media);
+                    const video = getVideo();
+                    if (video) {
+                        // console.log('video', video);
+                        video.srcObject = media;
+                        this.stream = media;
+                        await this.createMediaRecoder();
+                        this.mediaRecorder.start();
+                        this.stream.getVideoTracks()[0].onended = () => {
+                            this.debug && console.log('stop-share');
+                            this.endRecord();
+                        };
+                    }
+                }
+                else {
+                    this.streamStop();
+                    this.isStartRecoding = false;
+                    this.status = RecorderStatusType.end;
+                    this.emit('cancelRecord');
+                }
+            }
+        }
+        catch (error) {
+            console.error('startRecord::', error);
+        }
+    }
+    getDefaultMedia() {
+        return new Promise(async (resolve) => {
+            switch (this.platform) {
+                case 'web':
+                    return resolve(await this.getDisplayMedia());
+                case 'canvas':
+                    return resolve(await this.getCanvasSteam());
+                case 'electron':
+                    return resolve(await this.getEletronDisplayMedia());
+                default:
+                    return resolve(await this.getDisplayMedia());
+            }
+        });
+    }
+    getCanvasSteam() {
+        return new Promise(async (resolve) => {
+            try {
+                const audioInput = await this.getDeaultAudio();
+                if (audioInput) {
+                    this.audioInput = audioInput;
+                }
+                this.debug && console.log('audioInput', audioInput);
+                console.log('this.canvasElement', this.canvasElement);
+                let defaultFrame = 30;
+                if (typeof this.platformConfig.frameRate == 'number') {
+                    defaultFrame = this.platformConfig.frameRate;
+                }
+                const stream = this.canvasElement.captureStream(defaultFrame);
+                // debugger;
+                if (stream) {
+                    const videoTrack = stream.getVideoTracks()[0];
+                    if (videoTrack) {
+                        videoTrack.applyConstraints({
+                            advanced: [
+                                {
+                                    width: videoConstraints.value.width,
+                                    height: videoConstraints.value.height,
+                                    frameRate: videoConstraints.value.frameRate,
+                                },
+                            ],
+                        });
+                    }
+                    return resolve(stream);
+                }
+                return resolve(null);
+            }
+            catch (error) {
+                return resolve(null);
+            }
+        });
+    }
+    getEletronDisplayMedia() {
+        return new Promise(async (resolve) => {
+            try {
+                const audioInput = await this.getEletronDeaultAudio();
+                if (audioInput) {
+                    this.audioInput = audioInput;
+                }
+                console.log('eletron-audioInput', audioInput);
+                if (navigator.mediaDevices.getDisplayMedia) {
+                    const videoConfig = {
+                        mandatory: {
+                            chromeMediaSource: 'desktop',
+                            chromeMediaSourceId: this.chromeMediaSourceId,
+                            minWidth: this.platformConfig.minWidth || 1280,
+                            maxWidth: this.platformConfig.maxWidth || 3840,
+                            minHeight: this.platformConfig.minHeight || 720,
+                            maxHeight: this.platformConfig.maxHeight || 2160,
+                            maxFrameRate: this.platformConfig.maxFrameRate || 30,
+                            minFrameRate: this.platformConfig.minFrameRate || 30,
+                        },
+                    };
+                    this.debug && console.log('videoConfig', videoConfig);
+                    const res = await navigator.mediaDevices.getUserMedia({
+                        audio: false,
+                        video: videoConfig,
+                    });
+                    return resolve(res);
+                }
+                return resolve(null);
+            }
+            catch (error) {
+                return resolve(null);
+            }
+        });
+    }
+    getDisplayMedia() {
+        return new Promise(async (resolve) => {
+            try {
+                const audioInput = await this.getDeaultAudio();
+                if (audioInput) {
+                    this.audioInput = audioInput;
+                }
+                this.debug && console.log('audioInput', audioInput);
+                if (navigator.mediaDevices.getDisplayMedia) {
+                    if (this.debug) {
+                        console.log('displayMediaStreamConstraints', this.displayMediaStreamConstraints);
+                    }
+                    const res = await navigator.mediaDevices.getDisplayMedia(this.displayMediaStreamConstraints);
+                    return resolve(res);
+                }
+                return resolve(null);
+            }
+            catch (error) {
+                return resolve(null);
+            }
+        });
+    }
+    async getDeaultAudio() {
+        return new Promise(async (resolve) => {
+            try {
+                const audioConfig = {
+                    echoCancellation: true,
+                    autoGainControl: true,
+                    noiseSuppression: true,
+                    latency: 0,
+                };
+                console.log('audioConfig', audioConfig);
+                if (navigator.mediaDevices.getUserMedia) {
+                    const res = await navigator.mediaDevices.getUserMedia({
+                        audio: audioConfig,
+                        video: false,
+                    });
+                    return resolve(res);
+                }
+                return resolve(null);
+            }
+            catch (error) {
+                return resolve(null);
+            }
+        });
+    }
+    async getEletronDeaultAudio() {
+        return new Promise(async (resolve) => {
+            try {
+                if (navigator.mediaDevices.getUserMedia) {
+                    const res = await navigator.mediaDevices.getUserMedia({
+                        video: false,
+                        audio: { deviceId: 'default' },
+                    });
+                    return resolve(res);
+                }
+                return resolve(null);
+            }
+            catch (error) {
+                return resolve(null);
+            }
+        });
+    }
+    holdRecord() {
+        this.isStartRecoding = false;
+        this.status = RecorderStatusType.hold;
+        this.streamStop();
+    }
+    async endRecord() {
+        return new Promise(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 === null || blobs === void 0 ? void 0 : blobs.length) && this.handleAutoDownload(blobs);
+                }
+                this.emit('endRecord', blobs);
+                this.passiveEnd = false;
+                this.recordChunks = [];
+                resolve(blobs);
+            }
+            catch (error) {
+                this.emit('endRecord', null);
+                resolve([]);
+            }
+        });
+    }
+    // public async setMuteMode() {
+    // }
+    streamStop() {
+        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();
+        }
+    }
+    async createMediaRecoder() {
+        // let mergeSteam: MediaStream;
+        try {
+            let audioTrack, videoTrack;
+            if (this.audioInput) {
+                [videoTrack] = this.stream.getVideoTracks();
+                [audioTrack] = this.audioInput.getAudioTracks();
+                this.stream = new MediaStream([videoTrack, audioTrack]);
+            }
+            const globalAudioInstance = window.Howler;
+            if ((globalAudioInstance === null || globalAudioInstance === void 0 ? void 0 : globalAudioInstance.ctx) && !this.disabledAudio) {
+                const streamAudio = globalAudioInstance.ctx.createMediaStreamDestination();
+                globalAudioInstance.masterGain.connect(streamAudio);
+                console.log('streamDest', streamAudio);
+                window.streamAudio = streamAudio;
+                [videoTrack] = this.stream.getVideoTracks();
+                [audioTrack] = streamAudio.stream.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: this.codecType,
+                audioBitsPerSecond: videoConstraints.value.audioBitsPerSecond,
+                videoBitsPerSecond: videoConstraints.value.videoBitsPerSecond,
+            });
+            this.mediaRecorder = mediaRecorder;
+            // if (this.debug) {
+            window.__SIMAQ__ = mediaRecorder;
+            // }
+            this.mediaRecorder.ondataavailable = (event) => {
+                this.recordChunks.push(event.data);
+                this.emit('record', new Blob([event.data], {
+                    type: this.codecFileType,
+                }));
+            };
+            this.mediaRecorder.stop = () => {
+                // setTimeout(() => {
+                //     this.handleAutoDownload();
+                // }, 1000);
+            };
+            this.mediaRecorder.onerror = (event) => {
+                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);
+        }
+    }
+    handleAutoDownload(chunks) {
+        const downloadBlob = new Blob(chunks, {
+            type: this.codecFileType,
+        });
+        const url = URL.createObjectURL(downloadBlob);
+        const a = document.createElement('a');
+        document.body.appendChild(a);
+        a.style.display = 'none';
+        a.href = url;
+        const name = new Date().getTime();
+        a.download = `${name}.webm`;
+        a.click();
+        window.URL.revokeObjectURL(url);
+    }
+    updateCanvas(canvas) {
+        if (this.isCanvas) {
+            this.canvasElement = canvas;
+        }
+    }
+}
+//# sourceMappingURL=basicSimaqRecorder.js.map

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/util/simaqcore/lib/basicSimaqRecorder.js.map


+ 6 - 0
src/util/simaqcore/lib/init.d.ts

@@ -0,0 +1,6 @@
+import { BasicSimaqRecorder, InitConfigType } from './basicSimaqRecorder';
+export declare class VideoRecorder extends BasicSimaqRecorder {
+    constructor(params: InitConfigType);
+    init(params: InitConfigType): void;
+}
+//# sourceMappingURL=init.d.ts.map

+ 1 - 0
src/util/simaqcore/lib/init.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/lib/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK1E,qBAAa,aAAc,SAAQ,kBAAkB;gBAKrC,MAAM,EAAE,cAAc;IAKlC,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;CAyCrC"}

+ 53 - 0
src/util/simaqcore/lib/init.js

@@ -0,0 +1,53 @@
+import { BasicSimaqRecorder } from './basicSimaqRecorder';
+import { createVideo } from './videoElement';
+// import { audioConstraints } from "./audioConstraints";
+import { videoConstraints } from './videoConstraints';
+export class VideoRecorder extends BasicSimaqRecorder {
+    // public displayMediaStreamConstraints: DisplayMediaStreamConstraints = {
+    //   video: videoConstraints.value,
+    //   audio: audioConstraints.value,
+    // };
+    constructor(params) {
+        super(params);
+        this.init(params);
+    }
+    init(params) {
+        document.addEventListener('DOMContentLoaded', createVideo.apply(this, [params.debugShowVideo]));
+        // if (params?.debug) {
+        //     const video = getVideo();
+        //     video.style.display = 'block';
+        // }
+        if (params === null || params === void 0 ? void 0 : params.resolution) {
+            switch (params.resolution) {
+                case '4k':
+                    videoConstraints.next({
+                        ...videoConstraints.value,
+                        width: 3840,
+                        height: 2160,
+                        audioBitsPerSecond: 128000,
+                        videoBitsPerSecond: 12000000, // 12m/s
+                    });
+                    break;
+                case '2k':
+                    videoConstraints.next({
+                        ...videoConstraints.value,
+                        width: 2560,
+                        height: 1440,
+                        audioBitsPerSecond: 128000,
+                        videoBitsPerSecond: 6500000, // 6.5m/s
+                    });
+                    break;
+                case '1080p':
+                    videoConstraints.next({
+                        ...videoConstraints.value,
+                        width: 1920,
+                        height: 1080,
+                        audioBitsPerSecond: 128000,
+                        videoBitsPerSecond: 2500000, // 2.5m/s
+                    });
+                    break;
+            }
+        }
+    }
+}
+//# sourceMappingURL=init.js.map

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/util/simaqcore/lib/init.js.map


+ 2 - 0
src/util/simaqcore/lib/isSupport.d.ts

@@ -0,0 +1,2 @@
+export declare const isSupport: () => boolean;
+//# sourceMappingURL=isSupport.d.ts.map

+ 1 - 0
src/util/simaqcore/lib/isSupport.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"isSupport.d.ts","sourceRoot":"","sources":["../../src/lib/isSupport.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS,eACkD,CAAC"}

+ 2 - 0
src/util/simaqcore/lib/isSupport.js

@@ -0,0 +1,2 @@
+export const isSupport = () => !!navigator.mediaDevices && !!navigator.mediaDevices.getDisplayMedia;
+//# sourceMappingURL=isSupport.js.map

+ 1 - 0
src/util/simaqcore/lib/isSupport.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"isSupport.js","sourceRoot":"","sources":["../../src/lib/isSupport.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,EAAE,CAC1B,CAAC,CAAC,SAAS,CAAC,YAAY,IAAI,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,eAAe,CAAC"}

+ 4 - 0
src/util/simaqcore/lib/sdk.d.ts

@@ -0,0 +1,4 @@
+export declare class SDK {
+    constructor();
+}
+//# sourceMappingURL=sdk.d.ts.map

+ 1 - 0
src/util/simaqcore/lib/sdk.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/lib/sdk.ts"],"names":[],"mappings":"AAAA,qBAAa,GAAG;;CAEf"}

+ 4 - 0
src/util/simaqcore/lib/sdk.js

@@ -0,0 +1,4 @@
+export class SDK {
+    constructor() { }
+}
+//# sourceMappingURL=sdk.js.map

+ 1 - 0
src/util/simaqcore/lib/sdk.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../../src/lib/sdk.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,GAAG;IACZ,gBAAe,CAAC;CACnB"}

+ 8 - 0
src/util/simaqcore/lib/videoConstraints.d.ts

@@ -0,0 +1,8 @@
+import { BehaviorSubject } from 'rxjs';
+interface CustomMediaTrackConstraints extends MediaTrackConstraints {
+    audioBitsPerSecond?: number;
+    videoBitsPerSecond?: number;
+}
+export declare const videoConstraints: BehaviorSubject<CustomMediaTrackConstraints>;
+export {};
+//# sourceMappingURL=videoConstraints.d.ts.map

+ 1 - 0
src/util/simaqcore/lib/videoConstraints.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"videoConstraints.d.ts","sourceRoot":"","sources":["../../src/lib/videoConstraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAEvC,UAAU,2BAA4B,SAAQ,qBAAqB;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,eAAO,MAAM,gBAAgB,8CAGvB,CAAC"}

+ 5 - 0
src/util/simaqcore/lib/videoConstraints.js

@@ -0,0 +1,5 @@
+import { BehaviorSubject } from 'rxjs';
+export const videoConstraints = new BehaviorSubject({
+    frameRate: 30,
+});
+//# sourceMappingURL=videoConstraints.js.map

+ 1 - 0
src/util/simaqcore/lib/videoConstraints.js.map

@@ -0,0 +1 @@
+{"version":3,"file":"videoConstraints.js","sourceRoot":"","sources":["../../src/lib/videoConstraints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AAOvC,MAAM,CAAC,MAAM,gBAAgB,GACzB,IAAI,eAAe,CAA8B;IAC7C,SAAS,EAAE,EAAE;CAChB,CAAC,CAAC"}

+ 4 - 0
src/util/simaqcore/lib/videoElement.d.ts

@@ -0,0 +1,4 @@
+export declare function createVideo(show: boolean): void;
+export declare function getVideo(): HTMLVideoElement;
+export declare function removeVideo(): void;
+//# sourceMappingURL=videoElement.d.ts.map

+ 1 - 0
src/util/simaqcore/lib/videoElement.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"videoElement.d.ts","sourceRoot":"","sources":["../../src/lib/videoElement.ts"],"names":[],"mappings":"AAAA,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAa/C;AAED,wBAAgB,QAAQ,IAAI,gBAAgB,CAK3C;AAED,wBAAgB,WAAW,IAAI,IAAI,CAKlC"}

+ 23 - 0
src/util/simaqcore/lib/videoElement.js

@@ -0,0 +1,23 @@
+export function createVideo(show) {
+    const videoElement = document.createElement('video');
+    videoElement.id = 'simaq-video';
+    videoElement.setAttribute('autoplay', 'true');
+    videoElement.setAttribute('mute', 'true');
+    videoElement.style.width = '600px';
+    videoElement.style.height = '400px';
+    videoElement.style.position = 'fixed';
+    videoElement.style.top = '0px';
+    videoElement.style.right = '0px';
+    videoElement.style.zIndex = '1000';
+    videoElement.style.display = show ? 'block' : 'none';
+    document.body.appendChild(videoElement);
+}
+export function getVideo() {
+    const videoElement = document.getElementById('simaq-video');
+    return videoElement;
+}
+export function removeVideo() {
+    const videoElement = document.getElementById('simaq-video');
+    document.body.removeChild(videoElement);
+}
+//# sourceMappingURL=videoElement.js.map

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
src/util/simaqcore/lib/videoElement.js.map


+ 35 - 4
src/view/newFireCase/newFireDetails/components/shot.vue

@@ -47,7 +47,7 @@ import {
 } from "vue";
 import Toolbar from "./Toolbar.vue";
 import { ElMessage } from "element-plus";
-import { VideoRecorder } from "simaqcore";
+import { VideoRecorder } from "@/util/simaqcore";
 import { getVideoCover } from "@/util/video-cover";
 import { getRecordFragmentBlobs, appEl, getResource } from "@/store/system";
 
@@ -61,14 +61,40 @@ const emit = defineEmits<{
   'deleteRecord': [value: any],
   'playVideo': [value: any],
 }>()
-
+const isFirefox = /firefox/i.test(navigator.userAgent);
+
+function getSupportedMimeType() {
+      const firefoxMimeTypes = [
+        'video/webm;codecs=vp8,opus',
+        'video/webm'
+      ];
+      const defaultMimeTypes = [
+        'video/webm;codecs=vp9,opus',
+        'video/webm;codecs=vp8,opus',
+        'video/webm',
+        'video/mp4'
+      ];
+      const mimeTypes = isFirefox ? firefoxMimeTypes : defaultMimeTypes;
+
+      for (const type of mimeTypes) {
+        if (MediaRecorder && MediaRecorder.isTypeSupported(type)) {
+          return type;
+        }
+      }
+      return null;
+    }
 const config: any = {
   uploadUrl: "",
   resolution: "4k",
   debug: false,
 };
 const MetaType = 'video';
-const videoRecorder = new VideoRecorder(config);
+
+const videoRecorder = new VideoRecorder(config,{
+        mimeType:getSupportedMimeType(),
+        audioBitsPerSecond: 128000,
+        videoBitsPerSecond: 2500000
+      });
 let showBottomBar = ref(false);
 const MAX_SIZE = 2 * 1024 * 1024 * 1024;
 const MAX_TIME = 30 * 60 * 1000;
@@ -77,7 +103,12 @@ const previewVisible = ref(false);
 const countdown = ref(0);
 let interval: NodeJS.Timer;
 let recordIng = ref(false);
-const start = () => {
+  const start = () => {
+  // 3. 检测兼容的编码格式
+  const mimeType = getSupportedMimeType();
+  if (!mimeType) {
+    throw new Error('当前设备不支持任何视频录制格式');
+  }
   if (size.value > MAX_SIZE || pauseTime.value < 2000) {
     return ElMessage.warning("已超出限制大小无法继续录制,可保存后继续录制!");
   }