Преглед изворни кода

Merge branch 'webrtc' of http://192.168.0.115:3000/xushiting/Metaverse into webrtc版

# Conflicts:
#	src/Signal.js
#	src/Workers.js
#	src/XMaterialComponent.js
#	src/main.js
xushiting пре 3 година
родитељ
комит
5dfd36867c
100 измењених фајлова са 4747 додато и 0 уклоњено
  1. 2801 0
      dist/js/video.js
  2. 1 0
      dist/js/video.js.map
  3. 1371 0
      dist/libs/decoder copy.js
  4. 15 0
      dist/libs/toastify.js
  5. 218 0
      dist/texture.html
  6. BIN
      dist/video/0
  7. BIN
      dist/video/0_1_0.mp4
  8. BIN
      dist/video/264/0
  9. BIN
      dist/video/264/1
  10. BIN
      dist/video/264/1.jpg
  11. BIN
      dist/video/264/10
  12. BIN
      dist/video/264/10.jpg
  13. BIN
      dist/video/264/11
  14. BIN
      dist/video/264/11.jpg
  15. BIN
      dist/video/264/12
  16. BIN
      dist/video/264/12.jpg
  17. BIN
      dist/video/264/13
  18. BIN
      dist/video/264/13.jpg
  19. BIN
      dist/video/264/14
  20. BIN
      dist/video/264/14.jpg
  21. BIN
      dist/video/264/15
  22. BIN
      dist/video/264/15.jpg
  23. BIN
      dist/video/264/16
  24. BIN
      dist/video/264/16.jpg
  25. BIN
      dist/video/264/17
  26. BIN
      dist/video/264/17.jpg
  27. BIN
      dist/video/264/18
  28. BIN
      dist/video/264/18.jpg
  29. BIN
      dist/video/264/19
  30. BIN
      dist/video/264/19.jpg
  31. BIN
      dist/video/264/2
  32. BIN
      dist/video/264/2.jpg
  33. BIN
      dist/video/264/20
  34. BIN
      dist/video/264/20.jpg
  35. BIN
      dist/video/264/21
  36. BIN
      dist/video/264/21.jpg
  37. BIN
      dist/video/264/22
  38. BIN
      dist/video/264/22.jpg
  39. BIN
      dist/video/264/23
  40. BIN
      dist/video/264/23.jpg
  41. BIN
      dist/video/264/24
  42. BIN
      dist/video/264/24.jpg
  43. BIN
      dist/video/264/25
  44. BIN
      dist/video/264/25.jpg
  45. BIN
      dist/video/264/26
  46. BIN
      dist/video/264/26.jpg
  47. BIN
      dist/video/264/27
  48. BIN
      dist/video/264/27.jpg
  49. BIN
      dist/video/264/28
  50. BIN
      dist/video/264/28.jpg
  51. BIN
      dist/video/264/29
  52. BIN
      dist/video/264/29.jpg
  53. BIN
      dist/video/264/3
  54. BIN
      dist/video/264/3.jpg
  55. BIN
      dist/video/264/30
  56. BIN
      dist/video/264/30.jpg
  57. BIN
      dist/video/264/31
  58. BIN
      dist/video/264/31.jpg
  59. BIN
      dist/video/264/32
  60. BIN
      dist/video/264/32.jpg
  61. BIN
      dist/video/264/33
  62. BIN
      dist/video/264/33.jpg
  63. BIN
      dist/video/264/34
  64. BIN
      dist/video/264/34.jpg
  65. BIN
      dist/video/264/35
  66. BIN
      dist/video/264/35.jpg
  67. BIN
      dist/video/264/36
  68. BIN
      dist/video/264/36.jpg
  69. BIN
      dist/video/264/37
  70. BIN
      dist/video/264/37.jpg
  71. BIN
      dist/video/264/38
  72. BIN
      dist/video/264/38.jpg
  73. BIN
      dist/video/264/39
  74. BIN
      dist/video/264/39.jpg
  75. BIN
      dist/video/264/4
  76. BIN
      dist/video/264/4.jpg
  77. BIN
      dist/video/264/40
  78. BIN
      dist/video/264/40.jpg
  79. BIN
      dist/video/264/41
  80. BIN
      dist/video/264/41.jpg
  81. BIN
      dist/video/264/42
  82. BIN
      dist/video/264/42.jpg
  83. BIN
      dist/video/264/5
  84. BIN
      dist/video/264/5.jpg
  85. BIN
      dist/video/264/6
  86. BIN
      dist/video/264/6.jpg
  87. BIN
      dist/video/264/7
  88. BIN
      dist/video/264/7.jpg
  89. BIN
      dist/video/264/8
  90. BIN
      dist/video/264/8.jpg
  91. BIN
      dist/video/264/9
  92. BIN
      dist/video/264/9.jpg
  93. 1 0
      dist/video/out.yuv
  94. BIN
      dist/video/test.h264
  95. BIN
      dist/video/tt.mp4
  96. 70 0
      rollup.config.ba.js
  97. 83 0
      src/Response.js
  98. 184 0
      src/h264Decoder/VDecoder.js
  99. 3 0
      src/h264Decoder/h264.worker.js
  100. 0 0
      src/h264Decoder/index.js

Разлика између датотеке није приказан због своје велике величине
+ 2801 - 0
dist/js/video.js


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
dist/js/video.js.map


Разлика између датотеке није приказан због своје велике величине
+ 1371 - 0
dist/libs/decoder copy.js


Разлика између датотеке није приказан због своје велике величине
+ 15 - 0
dist/libs/toastify.js


+ 218 - 0
dist/texture.html

@@ -0,0 +1,218 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+        <title>Babylon.js sample code</title>
+
+        <!-- Babylon.js -->
+    <!-- Babylon.js -->
+    <script src="./libs/jquery-1.10.2.min.js"></script>
+    <script src="./libs/dat.gui.min.js"></script>
+    <script src="./libs/ammo.js"></script>
+    <script src="./libs/cannon.js"></script>
+    <script src="./libs/Oimo.js"></script>
+    <script src="./libs/earcut.min.js"></script>
+    <script src="./libs/recast.js"></script>
+
+    <script src="./libs/babylon.js"></script>
+    <script src="./libs/babylonjs.materials.min.js"></script>
+    <script src="./libs/babylonjs.proceduralTextures.min.js"></script>
+    <script src="./libs/babylonjs.postProcess.min.js"></script>
+    <script src="./libs/babylonjs.loaders.js"></script>
+    <script src="./libs/babylonjs.serializers.min.js"></script>
+    <script src="./libs/babylon.gui.min.js"></script>
+    <script src="./libs/babylon.inspector.bundle.js"></script>
+    <script src="https://cdn.socket.io/4.4.1/socket.io.min.js"></script>
+        <script src="js/video.js"></script>
+        <style>
+            html, body {
+                overflow: hidden;
+                width: 100%;
+                height: 100%;
+                margin: 0;
+                padding: 0;
+            }
+
+            #renderCanvas {
+                width: 100%;
+                height: 100%;
+                touch-action: none;
+            }
+        </style>
+    </head>
+<body>
+    <canvas id="renderCanvas"></canvas>
+    <script>
+        var canvas = document.getElementById("renderCanvas");
+
+        var startRenderLoop = function (engine, canvas) {
+            engine.runRenderLoop(function () {
+                if (sceneToRender && sceneToRender.activeCamera) {
+                    sceneToRender.render();
+                }
+            });
+        }
+
+        var engine = null;
+        var scene = null;
+        var sceneToRender = null;
+        var createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true,  disableWebGL2Support: false}); };
+        var createScene = function () {
+    // This creates a basic Babylon Scene object (non-mesh)
+    var scene = new BABYLON.Scene(engine);
+
+    scene.debugLayer.show({embedMode: true})
+
+    // This creates and positions a free camera (non-mesh)
+    var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
+
+    // This targets the camera to scene origin
+    camera.setTarget(BABYLON.Vector3.Zero());
+
+    // This attaches the camera to the canvas
+    camera.attachControl(canvas, true);
+
+    // This creates a light, aiming 0,1,0 - to the sky (non-mesh)
+    var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
+
+    // Default intensity is 1. Let's dim the light a small amount
+    light.intensity = 0.7;
+
+    // Our built-in 'ground' shape.
+    var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 6, height: 6}, scene);
+
+
+
+
+BABYLON.Effect.ShadersStore['customVertexShader'] = `
+precision highp float; 
+attribute vec2 uv;
+attribute vec3 position;
+
+varying vec2 vUV;
+ 
+uniform mat4 view;
+uniform mat4 projection; 
+uniform mat4 world;
+uniform mat4 worldViewProjection;
+void main()
+{ 
+    vUV = uv;
+    gl_Position = projection * view * world * vec4(position , 1.0); 
+}
+`;
+
+
+BABYLON.Effect.ShadersStore["customFragmentShader"]=`
+    precision highp float;
+ 
+varying vec2 vUV;
+uniform sampler2D chrominanceYTexture;
+
+void main()
+{    
+    vec2 uv = vUV;
+    vec3 color = vec3(0,0,0);
+
+    color = texture2D(chrominanceYTexture, uv).rgb;     
+
+    gl_FragColor = vec4( color, 1.0); 
+}
+
+
+`;
+
+
+    var width=512;
+    var height=1024;
+    window._videoRawYTexture = BABYLON.RawTexture.CreateLuminanceTexture(
+          null,
+          width,
+          height,
+          scene,
+          true,
+          true,
+        )
+
+    /*
+    var selfShader = new BABYLON.ShaderMaterial(
+      'customShader',
+      scene,
+      { 
+        vertex: "custom",
+        fragment: "custom",
+      },
+      {
+        attributes: ['uv', 'position'],
+        uniforms: ['view', 'projection', 'worldViewProjection', 'world'],
+      },
+    )
+    
+    selfShader.setTexture('chrominanceYTexture', _videoRawYTexture)
+*/
+
+    var selfShader = new BABYLON.StandardMaterial("xsttest",this.scene);
+    selfShader.diffuseTexture = window._videoRawYTexture
+    ground.material = selfShader
+    return scene;
+};
+
+
+window.generateRandomArray = ()=>{
+      var rnd=[];
+        for(let i=0;i< 512*1024;i++)
+        {
+            rnd[i] = Math.floor(Math.random()*255);
+        }
+        return rnd;
+}
+
+window.updateTexture = (yuv)=>
+{
+        let Y = yuv.subarray(0, 512*1024);
+        window._videoRawYTexture.update(Y)
+        window._videoRawYTexture.updateSamplingMode(BABYLON.Texture.BILINEAR_SAMPLINGMODE)
+        Y = undefined;
+}
+
+window.changeTexture = (data)=>{ 
+        for(let i=0;i< 512*1024;i++)
+        {
+            data[i] = Math.floor(Math.random()*255);
+        }
+        return data;
+}
+
+window.data = new Uint8Array(window.generateRandomArray());
+// start 
+// window.setInterval( ()=>{ 
+//     data = window.changeTexture(data);
+//     window.updateTexture( data );
+// }, 60);
+                window.initFunction = async function() {
+                    
+                    
+                    var asyncEngineCreation = async function() {
+                        try {
+                        return createDefaultEngine();
+                        } catch(e) {
+                        console.log("the available createEngine function failed. Creating the default engine instead");
+                        return createDefaultEngine();
+                        }
+                    }
+
+                    window.engine = await asyncEngineCreation();
+        if (!engine) throw 'engine should not be null.';
+        startRenderLoop(engine, canvas);
+        window.scene = createScene();};
+        initFunction().then(() => {sceneToRender = scene                    
+        });
+
+        // Resize
+        window.addEventListener("resize", function () {
+            engine.resize();
+        });
+    </script>
+</body>
+</html>


BIN
dist/video/0_1_0.mp4




BIN
dist/video/264/1.jpg


BIN
dist/video/264/10


BIN
dist/video/264/10.jpg


BIN
dist/video/264/11


BIN
dist/video/264/11.jpg


BIN
dist/video/264/12


BIN
dist/video/264/12.jpg


BIN
dist/video/264/13


BIN
dist/video/264/13.jpg


BIN
dist/video/264/14


BIN
dist/video/264/14.jpg


BIN
dist/video/264/15


BIN
dist/video/264/15.jpg


BIN
dist/video/264/16


BIN
dist/video/264/16.jpg


BIN
dist/video/264/17


BIN
dist/video/264/17.jpg


BIN
dist/video/264/18


BIN
dist/video/264/18.jpg


BIN
dist/video/264/19


BIN
dist/video/264/19.jpg



BIN
dist/video/264/2.jpg


BIN
dist/video/264/20


BIN
dist/video/264/20.jpg


BIN
dist/video/264/21


BIN
dist/video/264/21.jpg


BIN
dist/video/264/22


BIN
dist/video/264/22.jpg


BIN
dist/video/264/23


BIN
dist/video/264/23.jpg


BIN
dist/video/264/24


BIN
dist/video/264/24.jpg


BIN
dist/video/264/25


BIN
dist/video/264/25.jpg


BIN
dist/video/264/26


BIN
dist/video/264/26.jpg


BIN
dist/video/264/27


BIN
dist/video/264/27.jpg


BIN
dist/video/264/28


BIN
dist/video/264/28.jpg


BIN
dist/video/264/29


BIN
dist/video/264/29.jpg



BIN
dist/video/264/3.jpg


BIN
dist/video/264/30


BIN
dist/video/264/30.jpg


BIN
dist/video/264/31


BIN
dist/video/264/31.jpg


BIN
dist/video/264/32


BIN
dist/video/264/32.jpg


BIN
dist/video/264/33


BIN
dist/video/264/33.jpg


BIN
dist/video/264/34


BIN
dist/video/264/34.jpg


BIN
dist/video/264/35


BIN
dist/video/264/35.jpg


BIN
dist/video/264/36


BIN
dist/video/264/36.jpg


BIN
dist/video/264/37


BIN
dist/video/264/37.jpg


BIN
dist/video/264/38


BIN
dist/video/264/38.jpg


BIN
dist/video/264/39


BIN
dist/video/264/39.jpg



BIN
dist/video/264/4.jpg


BIN
dist/video/264/40


BIN
dist/video/264/40.jpg


BIN
dist/video/264/41


BIN
dist/video/264/41.jpg


BIN
dist/video/264/42


BIN
dist/video/264/42.jpg



BIN
dist/video/264/5.jpg



BIN
dist/video/264/6.jpg



BIN
dist/video/264/7.jpg



BIN
dist/video/264/8.jpg



BIN
dist/video/264/9.jpg


Разлика између датотеке није приказан због своје велике величине
+ 1 - 0
dist/video/out.yuv


BIN
dist/video/test.h264


BIN
dist/video/tt.mp4


+ 70 - 0
rollup.config.ba.js

@@ -0,0 +1,70 @@
+import path from 'path'
+import replace from '@rollup/plugin-replace'
+import resolveNode from '@rollup/plugin-node-resolve'
+import commonjs from '@rollup/plugin-commonjs'
+import babel from '@rollup/plugin-babel'
+import babelEnvConfig from './babel.env.config'
+import { terser } from 'rollup-plugin-terser'
+import webWorkerLoader from 'rollup-plugin-web-worker-loader';
+
+
+const pkg = require(`./package.json`)
+const version = pkg.version
+
+const isProd = process.env.NODE_ENV === 'production'
+const dist = file => path.resolve('dist/js/' + file)
+
+function createReplacePlugin() {
+    const replacements = {
+        __COMMIT__: `"${process.env.COMMIT}"`,
+        __VERSION__: `"${version}"`,
+        __ENV__: `"${process.env.NODE_ENV}"`,
+        __PROD__: isProd,
+        __DEV__: !isProd,
+    }
+    Object.keys(replacements).forEach(key => {
+        if (key in process.env) {
+            replacements[key] = process.env[key]
+        }
+    })
+    return replace({
+        values: replacements,
+        preventAssignment: true,
+    })
+}
+
+const sdk_plugins = [
+    resolveNode({
+        mainFields: ['jsnext', 'main'],
+        preferBuiltins: true,
+        browser: true,
+    }),
+    babel(babelEnvConfig()),
+    commonjs(),
+    createReplacePlugin(),
+    webWorkerLoader(/* configuration */),
+]
+
+if (isProd) {
+    sdk_plugins.push(terser())
+}
+
+export default [
+    {
+        input: 'src/h264Decoder/index.js',
+        //external: ['three'],
+        output: [
+            {
+                globals: {
+                   // three: 'THREE',
+                },
+                file: dist('video.js'),
+                format: 'umd',
+                name: 'Metaverse',
+                sourcemap: !isProd,
+                banner: pkg.banner.replace('${date}', new Date().toLocaleDateString()).replace('${author}', pkg.author).replace('${year}', new Date().getFullYear()),
+            },
+        ],
+        plugins: sdk_plugins,
+    },
+]

+ 83 - 0
src/Response.js

@@ -0,0 +1,83 @@
+var Response = {
+	"signal": {
+		"traceIds": [],
+		"vehicle": null,
+		"newUserStates": [{
+			"userId": null,    //要补充
+			"playerState": {
+				"roomTypeId": "",
+				"person": 0,
+				"avatarId": "",
+				"skinId": "",
+				"roomId": "",
+				"isHost": false,
+				"isFollowHost": false,
+				"skinDataVersion": "",
+				"avatarComponents": "",
+				"nickName": "",
+				"movingMode": 0,
+				"attitude": "",
+				"areaName": "",
+				"pathName": "",
+				"pathId": "",
+				"avatarSize": 1,
+				"extra": "",
+				"prioritySync": false,
+                //人物
+				"player": {
+					"position": {              //要补充
+						"x": null,
+						"y": null,
+						"z": null
+					},
+					"angle": {                 //要补充
+						"pitch": 0,
+						"yaw": 0,
+						"roll": 0
+					}
+				},
+				"camera": {
+					"position": {              //要补充
+						"x": null,
+						"y": null,
+						"z": null
+					},
+					"angle": {                 //要补充
+						"pitch": 0,          
+                        "yaw": 0,
+						"roll": 0
+					}
+				},
+				"cameraCenter": {               //要补充
+                    "x": null,
+                    "y": null,
+                    "z": null
+				}
+			},
+			"renderInfo": {
+				"renderType": 0,
+				"videoFrame": null,
+				"cameraStateType": 0,
+				"isMoving": 0,
+				"needIfr": 0,
+				"isVideo": 0,
+				"stillFrame": 0,
+				"isRotating": 0,
+				"isFollowing": 0,
+				"clientPanoTitlesBitmap": [],
+				"clientPanoTreceId": "",
+				"prefetchVideoId": "",
+				"noMedia": false
+			},
+			"event": null,
+			"relation": 1
+		}],
+		"actionResponses": [],
+		"getStateType": 0,
+		"code": 0,
+		"msg": "OK"
+	},
+	"pts": null,
+	"alreadyUpdateYUV": true
+}
+export default Response

+ 184 - 0
src/h264Decoder/VDecoder.js

@@ -0,0 +1,184 @@
+import EventEmitter from "eventemitter3";
+import H264Worker from "web-worker:./h264.worker.js";
+import { range, isArray } from "lodash-es";
+import { v4 as uuidv4 } from "uuid";
+
+export class VDecoder extends EventEmitter {
+  constructor({ chunkSize = 256 * 1024, maxChip = 100 }) {
+    super();
+    // this.cacheSegmentCount = cacheSegmentCount;
+    // this.chunkSize = chunkSize;
+    this.cacheBuffer = [];
+    this.cacheBufferTotal = null;
+    this.worker = new H264Worker();
+    this.initWorker();
+    this.tempVideos = [];
+    this.ready = false;
+    this.decoding = false;
+    this.decodingId = null;
+    this.start = null;
+    this.maxChip = maxChip;
+  }
+
+  static isSupport() {
+    return !!(
+      // UC and Quark browser (iOS/Android) support wasm/asm limited,
+      // its iOS version make wasm/asm performance very slow (maybe hook something)
+      // its Android version removed support for wasm/asm, it just run pure javascript codes,
+      // so it is very easy to cause memory leaks
+      (
+        !/UCBrowser|Quark/.test(window.navigator.userAgent) &&
+        window.fetch &&
+        window.ReadableStream &&
+        window.Promise &&
+        window.URL &&
+        window.URL.createObjectURL &&
+        window.Blob &&
+        window.Worker &&
+        !!new Audio().canPlayType("audio/aac;").replace(/^no$/, "") &&
+        (window.AudioContext || window.webkitAudioContext)
+      )
+    );
+  }
+  initWorker() {
+    this.worker.addEventListener("message", (e) => {
+      const message =
+        /** @type {{type:string, width:number, height:number, data:ArrayBuffer, renderStateId:number}} */ e.data;
+
+      switch (message.type) {
+        case "pictureReady":
+          //   onPictureReady(message);
+          // console.log(
+          //   "[VDecoder]::decodeData",
+          //   Object.assign(message, { clipId: this.decodingId })
+          // );
+          this.emit(
+            "decodeData",
+            Object.assign(message, { clipId: this.decodingId })
+          );
+
+          if (this.decoding && this.decodingId) {
+            this.decodeNext(this.decodingId);
+          }
+          break;
+        case "decoderReady":
+          this.ready = true;
+          this.emit("ready");
+          break;
+      }
+    });
+  }
+
+  /**
+   *
+   * @param {*} rangeArray array [2,100]
+   */
+  fetch({ path, range: rangeArray, decode = true }) {
+    if (!this.ready) {
+      throw new Error("decoder is not ready");
+    }
+    const url = path;
+    if (!(isArray(rangeArray) && rangeArray.length === 2)) {
+      throw new Error("range must is an array!");
+    }
+
+    if (this.tempVideos.length > this.maxChip) {
+      this.flush();
+      console.log("flush");
+    }
+
+    let rangeFetch = [];
+
+    if (rangeArray[0] < 0 || rangeArray[1] < 0) {
+      console.error("[VDecoder]:range: 非法", `${[rangeArray[0], rangeArray[1]]}`);
+      return
+    }
+
+    if (rangeArray[0] < rangeArray[1]) {
+      rangeFetch = range(rangeArray[0], rangeArray[1] + 1);
+      console.log("[VDecoder]:顺时 +", rangeFetch);
+    } else {
+      rangeFetch = range(rangeArray[1], rangeArray[0] + 1).reverse();
+      console.log("[VDecoder]:逆时 -", rangeFetch);
+    }
+
+    const allFetch = rangeFetch.map((i) => {
+      return fetch(`${url}/${i}`).then((response) => {
+        return response.arrayBuffer().then(function (buffer) {
+          return new Uint8Array(buffer);
+        });
+      });
+    });
+
+    return Promise.all(allFetch)
+      .then((data) => {
+        const clip = { id: uuidv4(), data: data };
+        if (data.length > 0) {
+          this.emit("fetchDone", clip);
+          this.cacheBuffer = data.slice();
+          this.tempVideos.push(clip);
+          console.log("[VDecoder]:获取clip,", clip);
+          if (decode) {
+            this.start = Date.now();
+            this.cacheBufferTotal = clip.data.length;
+            this.decodeNext(clip.id);
+          }
+          return Promise.resolve(clip);
+        } else {
+          console.warn("[VDecoder]:fetch取帧为空", rangeFetch);
+        }
+      })
+      .catch((error) => {
+        console.log("error", error);
+      });
+  }
+  /**
+   * @param {Uint8Array} h264Nal
+   */
+  decode(h264Nal, id) {
+    this.worker.postMessage(
+      {
+        type: "decode",
+        data: h264Nal.buffer,
+        offset: h264Nal.byteOffset,
+        length: h264Nal.byteLength,
+        renderStateId: id,
+      },
+      [h264Nal.buffer]
+    );
+  }
+
+  decodeNext(clipId) {
+    const nextFrame = this.cacheBuffer.shift();
+    this.decodingId = clipId;
+    this.decoding = true;
+    let tempId = this.cacheBufferTotal - this.cacheBuffer.length - 1;
+
+    if (nextFrame) {
+      this.decode(nextFrame, tempId);
+    } else {
+      console.log("tempVideos", this.tempVideos.length);
+      const clip = this.tempVideos.find(({ id }) => id === this.decodingId);
+      if (clip) {
+        const fps = (1000 / (Date.now() - this.start)) * clip.data.length;
+        console.log(
+          `Decoded ${clip.data.length} frames in ${
+            Date.now() - this.start
+          }ms @ ${fps >> 0}FPS`
+        );
+      } else {
+        console.warn("不存在clip");
+      }
+
+      this.decoding = false;
+      // this.decodingId = null;
+      tempId = 0;
+      clip && clip.id && this.emit("decodeDone", clip.id);
+    }
+  }
+  flush() {
+    this.tempVideos = [];
+  }
+
+  preloader(preload) {}
+}

+ 3 - 0
src/h264Decoder/h264.worker.js

@@ -0,0 +1,3 @@
+import { init } from 'tinyh264'
+
+init()

+ 0 - 0
src/h264Decoder/index.js


Неке датотеке нису приказане због велике количине промена