瀏覽代碼

feat: 缓存摄像头

shuisheng 2 年之前
父節點
當前提交
54eb582fc8
共有 6 個文件被更改,包括 78 次插入10 次删除
  1. 1 1
      .vscode/settings.json
  2. 1 1
      public/index.html
  3. 1 1
      src/hooks/use-push.ts
  4. 13 3
      src/main.scss
  5. 1 0
      src/store/app/index.ts
  6. 61 4
      src/views/push/index.vue

+ 1 - 1
.vscode/settings.json

@@ -43,5 +43,5 @@
     "vue"
   ],
   "typescript.tsdk": "node_modules/typescript/lib",
-  "vue.codeActions.savingTimeLimit": 1000
+  "vue.codeActions.savingTimeLimit": 2000
 }

+ 1 - 1
public/index.html

@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+<!doctype html>
 <html lang="">
   <head>
     <meta charset="utf-8" />

+ 1 - 1
src/hooks/use-push.ts

@@ -49,7 +49,7 @@ export function usePush() {
 
   watch(
     () => appStore.allTrack,
-    (newTrack, oldTrack) => {
+    (newTrack) => {
       console.log('appStore.allTrack变了');
       const mixedStream = new MediaStream();
       newTrack.forEach((item) => {

+ 13 - 3
src/main.scss

@@ -1,7 +1,17 @@
 body {
   padding: 0;
   margin: 0;
-  font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica,
-    Segoe UI, Arial, Roboto, PingFang SC, miui, Hiragino Sans GB,
-    Microsoft Yahei, sans-serif;
+  font-family:
+    -apple-system,
+    BlinkMacSystemFont,
+    Helvetica Neue,
+    Helvetica,
+    Segoe UI,
+    Arial,
+    Roboto,
+    PingFang SC,
+    miui,
+    Hiragino Sans GB,
+    Microsoft Yahei,
+    sans-serif;
 }

+ 1 - 0
src/store/app/index.ts

@@ -13,6 +13,7 @@ export type AppRootState = {
     /** 1开启;2关闭 */
     video: number;
     id: string;
+    deviceId?: string;
     mediaName: string;
     type: MediaTypeEnum;
     track?: MediaStreamTrack;

+ 61 - 4
src/views/push/index.vue

@@ -784,6 +784,7 @@ async function handleCache() {
     obj.audio = item.audio;
     obj.video = item.video;
     obj.id = item.id;
+    obj.deviceId = item.deviceId;
     obj.type = item.type;
     obj.hidden = item.hidden;
     obj.mediaName = item.mediaName;
@@ -883,8 +884,59 @@ async function handleCache() {
         console.error('读取文件失败');
       }
     }
+
+    async function handleMicrophone() {
+      const event = await navigator.mediaDevices.getUserMedia({
+        video: false,
+        audio: { deviceId: obj.deviceId },
+      });
+      const videoEl = createVideo({ appendChild: true, muted: false });
+      videoEl.srcObject = event;
+      obj.videoEl = videoEl;
+    }
+
+    async function handleCamera() {
+      const event = await navigator.mediaDevices.getUserMedia({
+        video: { deviceId: obj.deviceId },
+        audio: false,
+      });
+      const videoEl = createVideo({ appendChild: true });
+      videoEl.srcObject = event;
+      await new Promise((resolve) => {
+        videoEl.onloadedmetadata = () => {
+          const stream = videoEl
+            // @ts-ignore
+            .captureStream();
+          const width = stream.getVideoTracks()[0].getSettings().width!;
+          const height = stream.getVideoTracks()[0].getSettings().height!;
+          videoEl.width = width;
+          videoEl.height = height;
+
+          const canvasDom = markRaw(
+            new fabric.Image(videoEl, {
+              top: (item.rect?.top || 0) / window.devicePixelRatio,
+              left: (item.rect?.left || 0) / window.devicePixelRatio,
+              width,
+              height,
+            })
+          );
+          handleMoving({ canvasDom, id: item.id });
+          handleScaling({ canvasDom, id: item.id });
+          canvasDom.scale(item.scaleInfo[window.devicePixelRatio].scaleX || 1);
+          fabricCanvas.value!.add(canvasDom);
+          obj.videoEl = videoEl;
+          obj.canvasDom = canvasDom;
+          resolve({ videoEl, canvasDom });
+        };
+      });
+    }
+
     if (item.type === MediaTypeEnum.media && item.video === 1) {
       queue.push(handleMediaVideo());
+    } else if (item.type === MediaTypeEnum.camera) {
+      queue.push(handleCamera());
+    } else if (item.type === MediaTypeEnum.microphone) {
+      queue.push(handleMicrophone());
     } else if (item.type === MediaTypeEnum.img) {
       queue.push(handleImg());
     } else if (item.type === MediaTypeEnum.txt) {
@@ -1066,6 +1118,7 @@ async function addMediaOk(val: {
     });
     const videoTrack: AppRootState['allTrack'][0] = {
       id: getRandomEnglishString(8),
+      deviceId: val.deviceId,
       audio: 2,
       video: 1,
       mediaName: val.mediaName,
@@ -1098,8 +1151,9 @@ async function addMediaOk(val: {
       video: false,
       audio: { deviceId: val.deviceId },
     });
-    const audioTrack: AppRootState['allTrack'][0] = {
+    const microphoneVideoTrack: AppRootState['allTrack'][0] = {
       id: getRandomEnglishString(8),
+      deviceId: val.deviceId,
       audio: 1,
       video: 2,
       mediaName: val.mediaName,
@@ -1113,12 +1167,15 @@ async function addMediaOk(val: {
       volume: 60,
       scaleInfo: {},
     };
-    const res = [...appStore.allTrack, audioTrack];
+    const videoEl = createVideo({ appendChild: true, muted: false });
+    videoEl.srcObject = event;
+    microphoneVideoTrack.videoEl = videoEl;
+    const res = [...appStore.allTrack, microphoneVideoTrack];
     appStore.setAllTrack(res);
     resourceCacheStore.setList(res);
     handleMixedAudio();
     // @ts-ignore
-    addTrack(audioTrack);
+    addTrack(microphoneVideoTrack);
 
     console.log('获取麦克风成功');
   } else if (val.type === MediaTypeEnum.txt) {
@@ -1406,7 +1463,7 @@ async function addMediaOk(val: {
 }
 
 function updateVolume(item: AppRootState['allTrack'][0], v) {
-  console.log(item.volume, v);
+  console.log(item, item.volume, v);
   if (item.volume !== undefined) {
     item.volume = v;
     item.videoEl!.volume = v / 100;