├── .eslintignore
├── README.md
├── .eslintrc.json
├── src
├── worker.js
├── components
│ ├── style.css
│ ├── Excalidraw.js
│ ├── TimelinePreview.js
│ ├── Video.js
│ └── Timeline.js
├── styles.css
├── index.js
├── atoms.js
├── utils.js
├── App.js
└── mp4.js
├── .editorconfig
├── .gitignore
├── .codesandbox
└── workspace.json
├── public
└── index.html
├── package.json
└── LICENSE.md
/.eslintignore:
--------------------------------------------------------------------------------
1 | src/mp4.js
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # video-editor
2 | Created with CodeSandbox
3 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@excalidraw/eslint-config", "react-app"],
3 | "rules": {
4 | "import/no-anonymous-default-export": "off",
5 | "no-restricted-globals": "off"
6 | }
7 | }
--------------------------------------------------------------------------------
/src/worker.js:
--------------------------------------------------------------------------------
1 |
2 | var CALLS = {
3 | processFrame: ({frameID}) => {
4 | self.postMessage('42');
5 | }
6 | }
7 |
8 | self.onmessage = ({ data: {call, ...args} }) => {
9 | CALLS[call](args);
10 | };
11 |
--------------------------------------------------------------------------------
/src/components/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | }
5 |
6 | .excalidraw-wrapper {
7 | width: 1200px;
8 | height: 500px;
9 | }
10 |
11 | .excalidraw .App-menu_top .Stack_vertical .Island {
12 | min-width: 204px;
13 | }
14 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://EditorConfig.org
2 |
3 | # top-level EditorConfig file
4 | root = true
5 |
6 | [*]
7 | charset = utf-8
8 | end_of_line = lf
9 | indent_size = 2
10 | indent_style = space
11 | insert_final_newline = true
12 | trim_trailing_whitespace = true
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .eslintcache
3 | .history
4 | .idea
5 | .vercel
6 | .vscode
7 | .yarn
8 | *.log
9 | *.tgz
10 | build
11 | dist
12 | logs
13 | node_modules
14 | npm-debug.log*
15 | package-lock.json
16 | static
17 | yarn-debug.log*
18 | yarn-error.log*
19 |
--------------------------------------------------------------------------------
/.codesandbox/workspace.json:
--------------------------------------------------------------------------------
1 | {
2 | "responsive-preview": {
3 | "Mobile": [
4 | 320,
5 | 675
6 | ],
7 | "Tablet": [
8 | 1024,
9 | 765
10 | ],
11 | "Desktop": [
12 | 1400,
13 | 800
14 | ],
15 | "Desktop HD": [
16 | 1920,
17 | 1080
18 | ]
19 | }
20 | }
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: rgb(13, 17, 23);
3 | }
4 |
5 | .App {
6 | font-family: sans-serif;
7 | text-align: center;
8 | width: 100vw;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: center;
12 | align-items: center;
13 | /* overflow: hidden; */
14 | }
15 |
16 | .cursor {
17 | display: inline-block;
18 | width: 4px;
19 | height: 140px;
20 | background-color: green;
21 | position: absolute;
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/Excalidraw.js:
--------------------------------------------------------------------------------
1 | import { Excalidraw as ExcalidrawComponent } from "@excalidraw/excalidraw";
2 |
3 | import "./style.css";
4 |
5 | export const Excalidraw = () => {
6 | return (
7 |
8 | {}}
16 | onLinkOpen={() => {}}
17 | />
18 |
19 | );
20 | };
21 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { StrictMode } from "react";
2 | import { createRoot } from "react-dom/client";
3 | import { RecoilRoot } from "recoil";
4 |
5 | import App from "./App";
6 |
7 | const worker = new Worker(new URL('./worker.js', import.meta.url));
8 |
9 | /*
10 | worker.postMessage({ call: 'processFrame' });
11 |
12 | worker.onmessage = ({ data: { answer } }) => {
13 | console.log(answer);
14 | };
15 | */
16 |
17 | const rootElement = document.getElementById("root");
18 | const root = createRoot(rootElement);
19 |
20 | root.render(
21 |
22 |
23 |
24 | );
25 |
--------------------------------------------------------------------------------
/src/atoms.js:
--------------------------------------------------------------------------------
1 | import { atom, atomFamily, selectorFamily } from "recoil";
2 |
3 | export const loadingStateAtom = atom({
4 | key: "loadingState",
5 | default: "idle",
6 | });
7 |
8 | export const durationStateAtom = atom({
9 | key: "durationStateAtom",
10 | default: 0,
11 | });
12 |
13 | export const rangeStateAtom = atomFamily({
14 | key: "rangeStateAtom",
15 | default: selectorFamily({
16 | key: "rangeStateAtom/Default",
17 | get: (data) => () => {
18 | return data;
19 | },
20 | }),
21 | });
22 |
23 | export const cursorPositionStateAtom = atom({
24 | key: "cursorPositionStateAtom",
25 | default: 0,
26 | });
27 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | React App
9 |
10 |
11 |
12 |
15 |
16 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | export const generateRange = (duration) => {
2 | return {
3 | [Symbol.iterator]: function* rangeGenerator() {
4 | let x = 0;
5 | const step = 1;
6 |
7 | while (x < duration) {
8 | let hours = Math.floor(x / 3600);
9 | let minutes = Math.floor((x - hours * 3600) / 60);
10 | let seconds = Math.ceil(parseInt(x - hours * 3600 - minutes * 60, 10));
11 | if (hours < 10) {
12 | hours = `0${hours}`;
13 | }
14 | if (minutes < 10) {
15 | minutes = `0${minutes}`;
16 | }
17 | if (seconds < 10) {
18 | seconds = `0${seconds}`;
19 | }
20 | x += step;
21 | yield `${hours}:${minutes}:${seconds}`;
22 | }
23 | },
24 | };
25 | };
26 |
27 | export const getSeconds = (duration) => {
28 | const [hours, minutes, seconds] = duration.split(":");
29 | const totalSeconds = +hours * 60 * 60 + +minutes * 60 + +seconds;
30 | return totalSeconds;
31 | };
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react",
3 | "version": "1.0.0",
4 | "description": "React example starter project",
5 | "keywords": [
6 | "react",
7 | "starter"
8 | ],
9 | "main": "src/index.js",
10 | "dependencies": {
11 | "@excalidraw/excalidraw": "^0.12.0",
12 | "idb-keyval": "^6.2.0",
13 | "react": "18.0.0",
14 | "react-dom": "18.0.0",
15 | "react-scripts": "^5.0.1",
16 | "react-window": "^1.8.8",
17 | "recoil": "^0.7.6"
18 | },
19 | "devDependencies": {
20 | "@babel/runtime": "7.13.8",
21 | "@excalidraw/eslint-config": "^1.0.3",
22 | "@excalidraw/prettier-config": "^1.0.2",
23 | "eslint-config-prettier": "^8.5.0",
24 | "eslint-plugin-prettier": "^4.2.1",
25 | "prettier": "^2.7.1",
26 | "typescript": "4.1.3"
27 | },
28 | "scripts": {
29 | "start": "react-scripts --openssl-legacy-provider start",
30 | "build": "react-scripts build",
31 | "test": "react-scripts test --env=jsdom",
32 | "eject": "react-scripts eject"
33 | },
34 | "browserslist": [
35 | ">0.2%",
36 | "not dead",
37 | "not ie <= 11",
38 | "not op_mini all"
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Christopher Chedeau
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/components/TimelinePreview.js:
--------------------------------------------------------------------------------
1 | import { get } from "idb-keyval";
2 | import { useCallback, useEffect, useRef } from "react";
3 | import { getSeconds } from "../utils";
4 |
5 | export const TimelinePreview = ({ data, index, style }) => {
6 | const canvasRef = useRef();
7 | const imgRef = useRef();
8 | const ref = useRef();
9 | const range = data[index];
10 | const tempo = getSeconds(range);
11 |
12 | const setFrame = useCallback(async () => {
13 | const file = await get("file");
14 | const video = document.createElement("video");
15 | const source = document.createElement("source");
16 | video.appendChild(source);
17 | source.src = URL.createObjectURL(file);
18 |
19 | const img = imgRef.current;
20 | const canvas = canvasRef.current;
21 |
22 | video.currentTime = tempo;
23 | video.load();
24 | video.ontimeupdate = async function () {
25 | const context = canvas.getContext("2d");
26 | context.drawImage(video, 0, 0, canvas.width, canvas.height);
27 | img.src = canvas.toDataURL();
28 | };
29 | }, [tempo]);
30 |
31 | const onMouseMove = useCallback(() => {
32 | const video = document.querySelector("#video");
33 | video.currentTime = tempo;
34 | }, [tempo]);
35 |
36 | useEffect(() => {
37 | const div = ref.current;
38 | div.addEventListener("mousemove", onMouseMove);
39 | return () => div.removeEventListener("mousemove", onMouseMove);
40 | }, [onMouseMove]);
41 |
42 | useEffect(() => {
43 | // setFrame().then();
44 | }, []);
45 |
46 | // return null;
47 | return (
48 |
60 | {/*
*/}
64 |
{range}
65 | {/*
![]()
*/}
66 |
67 | );
68 | };
69 |
--------------------------------------------------------------------------------
/src/components/Video.js:
--------------------------------------------------------------------------------
1 | import { get } from "idb-keyval";
2 | import { useCallback } from "react";
3 | import { loadingStateAtom } from "../atoms";
4 | import { useRecoilValue } from "recoil";
5 | import { Excalidraw } from "./Excalidraw";
6 |
7 | export const Video = () => {
8 | const loadingState = useRecoilValue(loadingStateAtom);
9 |
10 | const onVideoLoad = useCallback(
11 | async (video) => {
12 | if (loadingState === "loaded") {
13 | const file = await get("file");
14 | const source = document.querySelector("#source");
15 | source.src = URL.createObjectURL(file);
16 |
17 | video.load();
18 | video.ontimeupdate = async function () {
19 | const stream = video.captureStream();
20 | const tracks = stream.getTracks();
21 | const track = tracks.find((track) => track.kind === "video");
22 | if (!track) {
23 | return;
24 | }
25 |
26 | const trackProcessor = new window.MediaStreamTrackProcessor(track);
27 |
28 | const reader = trackProcessor.readable.getReader();
29 | const result = await reader.read();
30 | if (result.done) {
31 | return;
32 | }
33 | const frame = result.value;
34 |
35 | const [canvas] = document.getElementsByTagName("canvas");
36 | const context = canvas.getContext("2d");
37 | context.drawImage(
38 | frame,
39 | 0,
40 | 0,
41 | frame.codedWidth,
42 | frame.codedHeight,
43 | 0,
44 | 0,
45 | canvas.width,
46 | canvas.height
47 | );
48 | frame.close();
49 | };
50 | }
51 | },
52 | [loadingState]
53 | );
54 |
55 | return (
56 |
57 |
58 |
68 |
69 | );
70 | };
71 |
--------------------------------------------------------------------------------
/src/components/Timeline.js:
--------------------------------------------------------------------------------
1 | import { cursorPositionStateAtom, rangeStateAtom } from "../atoms";
2 | import { useCallback, useEffect, useRef } from "react";
3 |
4 | import { useRecoilState, useRecoilValue } from "recoil";
5 |
6 | import { TimelinePreview } from "./TimelinePreview";
7 | import { generateRange } from "../utils";
8 | import { FixedSizeList as List } from "react-window";
9 |
10 | const ITEM_SIZE = 100;
11 | const LIST_WIDTH = 800;
12 |
13 | export const Timeline = ({ duration }) => {
14 | const cursorDivRef = useRef();
15 | const timelineDivRef = useRef();
16 | const range = useRecoilValue(rangeStateAtom([...generateRange(duration)]));
17 | const [, setCursorPosition] = useRecoilState(cursorPositionStateAtom);
18 |
19 | const onMouseMove = useCallback(
20 | (e) => {
21 | const video = document.querySelector("#video");
22 | const rect = timelineDivRef.current.getBoundingClientRect();
23 | const cursorPosition = e.clientX - rect.x;
24 | cursorDivRef.current.style.transform = `translateX(${cursorPosition}px)`;
25 | const percentage = cursorPosition / rect.width;
26 | // video.currentTime = video.duration * percentage;
27 | setCursorPosition(cursorPosition);
28 | },
29 | [setCursorPosition]
30 | );
31 |
32 | useEffect(() => {
33 | const listElement = document.querySelector(".list");
34 | listElement.addEventListener("mousemove", onMouseMove);
35 | return () => listElement.removeEventListener("mousemove", onMouseMove);
36 | }, [onMouseMove]);
37 |
38 | return (
39 |
50 |
60 |
70 | {TimelinePreview}
71 |
72 |
73 | );
74 | };
75 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import { useCallback } from "react";
2 | import { set } from "idb-keyval";
3 | import { loadingStateAtom, durationStateAtom } from "./atoms";
4 | import { useRecoilState } from "recoil";
5 | import { Video } from "./components/Video";
6 | import "./styles.css";
7 | import { Timeline } from "./components/Timeline";
8 |
9 | import { useState, useEffect, useRef } from 'react';
10 | import loadMP4Module from "./mp4.js";
11 |
12 |
13 | function createVideoFile(file) {
14 | const videoElement = document.createElement('video');
15 | videoElement.style = 'display: none';
16 | const sourceElement = document.createElement('source');
17 | sourceElement.src = URL.createObjectURL(file);
18 | videoElement.appendChild(sourceElement);
19 | document.body.appendChild(videoElement);
20 |
21 | return {
22 | file,
23 | videoElement,
24 | sourceElement
25 | };
26 | }
27 |
28 | function asyncGetDuration(videoFile) {
29 | return new Promise((resolve, reject) => {
30 | const videoElement = videoFile.videoElement;
31 | const listener = (event) => {
32 | videoElement.removeEventListener('durationchange', listener);
33 | resolve(videoElement.duration);
34 | };
35 | videoElement.addEventListener('durationchange', listener);
36 | });
37 | }
38 |
39 | var RANDOM_COLORS = ['red', 'green', 'blue', 'orange', 'yellow'];
40 | function getRandomColor() {
41 | const randomColor = RANDOM_COLORS.shift();
42 | RANDOM_COLORS.push(randomColor);
43 | return randomColor;
44 | }
45 |
46 | function getReaderFromVideoElement(videoElement) {
47 | const stream = videoElement.captureStream();
48 | const tracks = stream.getVideoTracks();
49 | const track = tracks[0];
50 | if (!track) {
51 | return null;
52 | }
53 | const trackProcessor = new window.MediaStreamTrackProcessor(track);
54 | return trackProcessor.readable.getReader();
55 | }
56 |
57 | async function extractFrameFromVideoFile(videoFile, time, targetCanvas) {
58 | await new Promise((resolve) => {
59 | const videoElement = videoFile.videoElement;
60 |
61 | const listener = async function() {
62 | videoElement.removeEventListener('timeupdate', listener);
63 |
64 | const reader = getReaderFromVideoElement(videoElement);
65 | if (!reader) {
66 | return;
67 | }
68 |
69 | const result = await reader.read();
70 | if (result.done) {
71 | return;
72 | }
73 | const frame = result.value;
74 |
75 | const context = targetCanvas.getContext('2d');
76 |
77 | context.imageSmoothingEnabled = true;
78 | context.imageSmoothingQuality = 'high';
79 | context.drawImage(
80 | frame,
81 | 0,
82 | 0,
83 | frame.codedWidth,
84 | frame.codedHeight,
85 | 0,
86 | 0,
87 | targetCanvas.width,
88 | targetCanvas.height
89 | );
90 | frame.close();
91 | resolve();
92 | }
93 | videoElement.addEventListener('timeupdate', listener);
94 |
95 | videoElement.currentTime = time;
96 | })
97 | }
98 |
99 | // https://medium.com/@karenmarkosyan/how-to-manage-promises-into-dynamic-queue-with-vanilla-javascript-9d0d1f8d4df5
100 | class PromiseQueue {
101 | static queue = [];
102 | static pendingPromise = false;
103 |
104 | static enqueue(promise) {
105 | return new Promise((resolve, reject) => {
106 | this.queue.push({
107 | promise,
108 | resolve,
109 | reject,
110 | });
111 | this.dequeue();
112 | });
113 | }
114 |
115 | static dequeue() {
116 | if (this.workingOnPromise) {
117 | return false;
118 | }
119 | const item = this.queue.shift();
120 | if (!item) {
121 | return false;
122 | }
123 | try {
124 | this.workingOnPromise = true;
125 | item.promise()
126 | .then((value) => {
127 | this.workingOnPromise = false;
128 | item.resolve(value);
129 | this.dequeue();
130 | })
131 | .catch(err => {
132 | this.workingOnPromise = false;
133 | item.reject(err);
134 | this.dequeue();
135 | })
136 | } catch (err) {
137 | this.workingOnPromise = false;
138 | item.reject(err);
139 | this.dequeue();
140 | }
141 | return true;
142 | }
143 | }
144 |
145 | function Preview({clip, time}) {
146 | const canvasElement = useRef(null);
147 |
148 | useEffect(() => {
149 | // PromiseQueue.enqueue(() => extractFrameFromVideoFile(clip.videoFile, time, canvasElement.current));
150 | }, [clip, time]);
151 |
152 | return (
153 |
159 | );
160 | }
161 |
162 | async function record(videoElement) {
163 | const reader = getReaderFromVideoElement(videoElement);
164 | if (!reader) {
165 | return;
166 | }
167 |
168 | const width = 1920;
169 | const height = 1080;
170 | const fps = 30;
171 | const MP4 = await loadMP4Module();
172 | const encoder = MP4.createWebCodecsEncoder({
173 | width,
174 | height,
175 | fps
176 | });
177 | const duration = videoElement.duration;
178 | console.log(videoElement.duration);
179 |
180 | let currentTime = 0;
181 | let frameCount = 0;
182 | const startNow = performance.now();
183 |
184 | const listener = async () => {
185 | reader.read().then(async (frame) => {
186 | if (frame.value) {
187 | const bitmap = await createImageBitmap(frame.value);
188 | await encoder.addFrame(bitmap);
189 | frameCount++;
190 |
191 | if (frameCount % 10 === 0) {
192 | console.log("Encoding " + Math.round(100 * currentTime / duration) + "% " + Math.round(1000 * frameCount / (performance.now() - startNow)) + " fps");
193 | }
194 | frame.value.close();
195 | }
196 | if (currentTime < duration) {
197 | currentTime += 1/fps;
198 | videoElement.currentTime = currentTime;
199 | } else {
200 | videoElement.removeEventListener('timeupdate', listener);
201 | const data = await encoder.end();
202 | const url = URL.createObjectURL(new Blob([data], { type: "video/mp4" }));
203 |
204 | const anchor = document.createElement("a");
205 | anchor.href = url;
206 | anchor.download = "download.mp4";
207 | anchor.click();
208 | }
209 | });
210 | }
211 | videoElement.addEventListener('timeupdate', listener);
212 | videoElement.currentTime = currentTime;
213 | }
214 |
215 | export default function App({worker}) {
216 | const [tracks, setTracks] = useState(
217 | [
218 | {
219 | clips: []
220 | }
221 | ]
222 | );
223 |
224 | const windowStart = 0;
225 | const windowEnd = Math.max(0, ...tracks[0].clips.map(clip => clip.end));
226 | const windowWidth = document.body.clientWidth;
227 |
228 | return (
229 |
230 |
Video Editor
231 |
232 | Select a video:{" "}
233 | clip.end));
245 | const duration = await asyncGetDuration(videoFile);
246 | newTracks[0].clips.push({
247 | start: start,
248 | end: start + duration,
249 | videoFile,
250 | backgroundColor: getRandomColor()
251 | });
252 | }
253 | setTracks(newTracks);
254 | }}
255 | />
256 |
257 |
258 |
259 |
Tracks
260 | {tracks.map((track, i) =>
261 |
262 | {track.clips.map(clip => {
263 | const width = ((clip.end - clip.start) / (windowEnd - windowStart)) * windowWidth;
264 | return (
265 |
277 | {Array.from({length: Math.ceil(width / 70)}).map((_, i) =>
278 |
283 | )}
284 |
285 | );
286 | })}
287 |
288 | )}
289 |
290 |
291 |
292 |
299 |
300 |
301 | );
302 | };
303 |
--------------------------------------------------------------------------------
/src/mp4.js:
--------------------------------------------------------------------------------
1 | // https://unpkg.com/mp4-wasm@1.0.6/build/mp4.js
2 | // With the path to the wasm file changed. Search for CHANGED
3 |
4 | var Module = (function () {
5 | var _ = import.meta.url;
6 | return function (t) {
7 | t = t || {};
8 | var t = typeof t != "undefined" ? t : {},
9 | u,
10 | h;
11 | (t.ready = new Promise(function (r, n) {
12 | (u = r), (h = n);
13 | })),
14 | (t.create_buffer = function (n) {
15 | return t._malloc(n);
16 | }),
17 | (t.free_buffer = function (n) {
18 | return t._free(n);
19 | }),
20 | (t.locateFile = function (n, e) {
21 | return (
22 | t.simd && (n = n.replace(/\.wasm$/i, ".simd.wasm")),
23 | t.getWasmPath ? t.getWasmPath(n, e, t.simd) : e + n
24 | );
25 | }),
26 | (t.createWebCodecsEncoder = function (n) {
27 | return createWebCodecsEncoderWithModule(t, n);
28 | });
29 | var m = {},
30 | l;
31 | for (l in t) t.hasOwnProperty(l) && (m[l] = t[l]);
32 | var p = [],
33 | j = "./this.program",
34 | N = function (r, n) {
35 | throw n;
36 | },
37 | W = !1,
38 | k = !1,
39 | x = !1,
40 | L = !1;
41 | (W = typeof window == "object"),
42 | (k = typeof importScripts == "function"),
43 | (x =
44 | typeof process == "object" &&
45 | typeof process.versions == "object" &&
46 | typeof process.versions.node == "string"),
47 | (L = !W && !x && !k);
48 | var y = "";
49 | function z(r) {
50 | return t.locateFile ? t.locateFile(r, y) : y + r;
51 | }
52 | var sr, nr, J, lr;
53 | (W || k) &&
54 | (k
55 | ? (y = self.location.href)
56 | : typeof document != "undefined" &&
57 | document.currentScript &&
58 | (y = document.currentScript.src),
59 | _ && (y = _),
60 | y.indexOf("blob:") !== 0
61 | ? (y = y.substr(0, y.lastIndexOf("/") + 1))
62 | : (y = ""),
63 | (sr = function (r) {
64 | var n = new XMLHttpRequest();
65 | return n.open("GET", r, !1), n.send(null), n.responseText;
66 | }),
67 | k &&
68 | (J = function (r) {
69 | var n = new XMLHttpRequest();
70 | return (
71 | n.open("GET", r, !1),
72 | (n.responseType = "arraybuffer"),
73 | n.send(null),
74 | new Uint8Array(n.response)
75 | );
76 | }),
77 | (nr = function (r, n, e) {
78 | var i = new XMLHttpRequest();
79 | i.open("GET", r, !0),
80 | (i.responseType = "arraybuffer"),
81 | (i.onload = function () {
82 | if (i.status == 200 || (i.status == 0 && i.response)) {
83 | n(i.response);
84 | return;
85 | }
86 | e();
87 | }),
88 | (i.onerror = e),
89 | i.send(null);
90 | }),
91 | (lr = function (r) {
92 | document.title = r;
93 | }));
94 | var er = t.print || console.log.bind(console),
95 | P = t.printErr || console.warn.bind(console);
96 | for (l in m) m.hasOwnProperty(l) && (t[l] = m[l]);
97 | (m = null),
98 | t.arguments && (p = t.arguments),
99 | t.thisProgram && (j = t.thisProgram),
100 | t.quit && (N = t.quit);
101 | var X;
102 | t.wasmBinary && (X = t.wasmBinary);
103 | var Wr = t.noExitRuntime || !0;
104 | typeof WebAssembly != "object" && ar("no native wasm support detected");
105 | var K,
106 | w = !1,
107 | b;
108 | function I(r, n, e) {
109 | for (var i = n + e, a = ""; !(n >= i); ) {
110 | var f = r[n++];
111 | if (!f) return a;
112 | if (!(f & 128)) {
113 | a += String.fromCharCode(f);
114 | continue;
115 | }
116 | var c = r[n++] & 63;
117 | if ((f & 224) == 192) {
118 | a += String.fromCharCode(((f & 31) << 6) | c);
119 | continue;
120 | }
121 | var o = r[n++] & 63;
122 | if (
123 | ((f & 240) == 224
124 | ? (f = ((f & 15) << 12) | (c << 6) | o)
125 | : (f = ((f & 7) << 18) | (c << 12) | (o << 6) | (r[n++] & 63)),
126 | f < 65536)
127 | )
128 | a += String.fromCharCode(f);
129 | else {
130 | var s = f - 65536;
131 | a += String.fromCharCode(55296 | (s >> 10), 56320 | (s & 1023));
132 | }
133 | }
134 | return a;
135 | }
136 | function A(r, n) {
137 | return r ? I(U, r, n) : "";
138 | }
139 | function O(r, n, e, i) {
140 | if (!(i > 0)) return 0;
141 | for (var a = e, f = e + i - 1, c = 0; c < r.length; ++c) {
142 | var o = r.charCodeAt(c);
143 | if (o >= 55296 && o <= 57343) {
144 | var s = r.charCodeAt(++c);
145 | o = (65536 + ((o & 1023) << 10)) | (s & 1023);
146 | }
147 | if (o <= 127) {
148 | if (e >= f) break;
149 | n[e++] = o;
150 | } else if (o <= 2047) {
151 | if (e + 1 >= f) break;
152 | (n[e++] = 192 | (o >> 6)), (n[e++] = 128 | (o & 63));
153 | } else if (o <= 65535) {
154 | if (e + 2 >= f) break;
155 | (n[e++] = 224 | (o >> 12)),
156 | (n[e++] = 128 | ((o >> 6) & 63)),
157 | (n[e++] = 128 | (o & 63));
158 | } else {
159 | if (e + 3 >= f) break;
160 | (n[e++] = 240 | (o >> 18)),
161 | (n[e++] = 128 | ((o >> 12) & 63)),
162 | (n[e++] = 128 | ((o >> 6) & 63)),
163 | (n[e++] = 128 | (o & 63));
164 | }
165 | }
166 | return (n[e] = 0), e - a;
167 | }
168 | function E(r, n, e) {
169 | return O(r, U, n, e);
170 | }
171 | function vr(r) {
172 | for (var n = 0, e = 0; e < r.length; ++e) {
173 | var i = r.charCodeAt(e);
174 | i >= 55296 &&
175 | i <= 57343 &&
176 | (i = (65536 + ((i & 1023) << 10)) | (r.charCodeAt(++e) & 1023)),
177 | i <= 127
178 | ? ++n
179 | : i <= 2047
180 | ? (n += 2)
181 | : i <= 65535
182 | ? (n += 3)
183 | : (n += 4);
184 | }
185 | return n;
186 | }
187 | function Zr(r, n) {
188 | for (var e = "", i = 0; !(i >= n / 2); ++i) {
189 | var a = Z[(r + i * 2) >> 1];
190 | if (a == 0) break;
191 | e += String.fromCharCode(a);
192 | }
193 | return e;
194 | }
195 | function Qr(r, n, e) {
196 | if ((e === void 0 && (e = 2147483647), e < 2)) return 0;
197 | e -= 2;
198 | for (
199 | var i = n, a = e < r.length * 2 ? e / 2 : r.length, f = 0;
200 | f < a;
201 | ++f
202 | ) {
203 | var c = r.charCodeAt(f);
204 | (Z[n >> 1] = c), (n += 2);
205 | }
206 | return (Z[n >> 1] = 0), n - i;
207 | }
208 | function Mr(r) {
209 | return r.length * 2;
210 | }
211 | function rn(r, n) {
212 | for (var e = 0, i = ""; !(e >= n / 4); ) {
213 | var a = V[(r + e * 4) >> 2];
214 | if (a == 0) break;
215 | if ((++e, a >= 65536)) {
216 | var f = a - 65536;
217 | i += String.fromCharCode(55296 | (f >> 10), 56320 | (f & 1023));
218 | } else i += String.fromCharCode(a);
219 | }
220 | return i;
221 | }
222 | function nn(r, n, e) {
223 | if ((e === void 0 && (e = 2147483647), e < 4)) return 0;
224 | for (var i = n, a = i + e - 4, f = 0; f < r.length; ++f) {
225 | var c = r.charCodeAt(f);
226 | if (c >= 55296 && c <= 57343) {
227 | var o = r.charCodeAt(++f);
228 | c = (65536 + ((c & 1023) << 10)) | (o & 1023);
229 | }
230 | if (((V[n >> 2] = c), (n += 4), n + 4 > a)) break;
231 | }
232 | return (V[n >> 2] = 0), n - i;
233 | }
234 | function en(r) {
235 | for (var n = 0, e = 0; e < r.length; ++e) {
236 | var i = r.charCodeAt(e);
237 | i >= 55296 && i <= 57343 && ++e, (n += 4);
238 | }
239 | return n;
240 | }
241 | function tn(r, n) {
242 | return r % n > 0 && (r += n - (r % n)), r;
243 | }
244 | var pr, _r, U, Z, hr, V, D, kr, Ir;
245 | function Or(r) {
246 | (pr = r),
247 | (t.HEAP8 = _r = new Int8Array(r)),
248 | (t.HEAP16 = Z = new Int16Array(r)),
249 | (t.HEAP32 = V = new Int32Array(r)),
250 | (t.HEAPU8 = U = new Uint8Array(r)),
251 | (t.HEAPU16 = hr = new Uint16Array(r)),
252 | (t.HEAPU32 = D = new Uint32Array(r)),
253 | (t.HEAPF32 = kr = new Float32Array(r)),
254 | (t.HEAPF64 = Ir = new Float64Array(r));
255 | }
256 | var me = t.INITIAL_MEMORY || 16777216,
257 | tr,
258 | Lr = [],
259 | Vr = [],
260 | Dr = [],
261 | an = !1;
262 | function on() {
263 | if (t.preRun)
264 | for (
265 | typeof t.preRun == "function" && (t.preRun = [t.preRun]);
266 | t.preRun.length;
267 |
268 | )
269 | cn(t.preRun.shift());
270 | yr(Lr);
271 | }
272 | function fn() {
273 | (an = !0), yr(Vr);
274 | }
275 | function sn() {
276 | if (t.postRun)
277 | for (
278 | typeof t.postRun == "function" && (t.postRun = [t.postRun]);
279 | t.postRun.length;
280 |
281 | )
282 | ln(t.postRun.shift());
283 | yr(Dr);
284 | }
285 | function cn(r) {
286 | Lr.unshift(r);
287 | }
288 | function un(r) {
289 | Vr.unshift(r);
290 | }
291 | function ln(r) {
292 | Dr.unshift(r);
293 | }
294 | var G = 0,
295 | gr = null,
296 | ir = null;
297 | function vn(r) {
298 | G++, t.monitorRunDependencies && t.monitorRunDependencies(G);
299 | }
300 | function pn(r) {
301 | if (
302 | (G--,
303 | t.monitorRunDependencies && t.monitorRunDependencies(G),
304 | G == 0 && (gr !== null && (clearInterval(gr), (gr = null)), ir))
305 | ) {
306 | var n = ir;
307 | (ir = null), n();
308 | }
309 | }
310 | (t.preloadedImages = {}), (t.preloadedAudios = {});
311 | function ar(r) {
312 | t.onAbort && t.onAbort(r),
313 | (r += ""),
314 | P(r),
315 | (w = !0),
316 | (b = 1),
317 | (r = "abort(" + r + "). Build with -s ASSERTIONS=1 for more info.");
318 | var n = new WebAssembly.RuntimeError(r);
319 | throw (h(n), n);
320 | }
321 | var _n = "data:application/octet-stream;base64,";
322 | function Hr(r) {
323 | return r.startsWith(_n);
324 | }
325 |
326 | // START CHANGED
327 |
328 | var R = 'https://unpkg.com/mp4-wasm@1.0.6/build/mp4.wasm';
329 | /*
330 | t.locateFile
331 | ? ((R = "mp4.wasm"), Hr(R) || (R = z(R)))
332 | : (R = new URL("mp4.wasm", import.meta.url).toString());
333 | */
334 |
335 | // END CHANGED
336 |
337 | function Br(r) {
338 | try {
339 | if (r == R && X) return new Uint8Array(X);
340 | if (J) return J(r);
341 | throw "both async and sync fetching of the wasm failed";
342 | } catch (n) {
343 | ar(n);
344 | }
345 | }
346 | function hn() {
347 | return !X && (W || k) && typeof fetch == "function"
348 | ? fetch(R, { credentials: "same-origin" })
349 | .then(function (r) {
350 | if (!r.ok)
351 | throw "failed to load wasm binary file at '" + R + "'";
352 | return r.arrayBuffer();
353 | })
354 | .catch(function () {
355 | return Br(R);
356 | })
357 | : Promise.resolve().then(function () {
358 | return Br(R);
359 | });
360 | }
361 | function gn() {
362 | var r = { a: ce };
363 | function n(c, o) {
364 | var s = c.exports;
365 | (t.asm = s),
366 | (K = t.asm.x),
367 | Or(K.buffer),
368 | (tr = t.asm.B),
369 | un(t.asm.y),
370 | pn("wasm-instantiate");
371 | }
372 | vn("wasm-instantiate");
373 | function e(c) {
374 | n(c.instance);
375 | }
376 | function i(c) {
377 | return hn()
378 | .then(function (o) {
379 | var s = WebAssembly.instantiate(o, r);
380 | return s;
381 | })
382 | .then(c, function (o) {
383 | P("failed to asynchronously prepare wasm: " + o), ar(o);
384 | });
385 | }
386 | function a() {
387 | return !X &&
388 | typeof WebAssembly.instantiateStreaming == "function" &&
389 | !Hr(R) &&
390 | typeof fetch == "function"
391 | ? fetch(R, { credentials: "same-origin" }).then(function (c) {
392 | var o = WebAssembly.instantiateStreaming(c, r);
393 | return o.then(e, function (s) {
394 | return (
395 | P("wasm streaming compile failed: " + s),
396 | P("falling back to ArrayBuffer instantiation"),
397 | i(e)
398 | );
399 | });
400 | })
401 | : i(e);
402 | }
403 | if (t.instantiateWasm)
404 | try {
405 | var f = t.instantiateWasm(r, n);
406 | return f;
407 | } catch (c) {
408 | return (
409 | P("Module.instantiateWasm callback failed with error: " + c), !1
410 | );
411 | }
412 | return a().catch(h), {};
413 | }
414 | function yr(r) {
415 | for (; r.length > 0; ) {
416 | var n = r.shift();
417 | if (typeof n == "function") {
418 | n(t);
419 | continue;
420 | }
421 | var e = n.func;
422 | typeof e == "number"
423 | ? n.arg === void 0
424 | ? tr.get(e)()
425 | : tr.get(e)(n.arg)
426 | : e(n.arg === void 0 ? null : n.arg);
427 | }
428 | }
429 | function yn(r, n, e, i) {
430 | ar(
431 | "Assertion failed: " +
432 | A(r) +
433 | ", at: " +
434 | [n ? A(n) : "unknown filename", e, i ? A(i) : "unknown function"]
435 | );
436 | }
437 | function dn(r, n, e, i, a) {}
438 | function dr(r) {
439 | switch (r) {
440 | case 1:
441 | return 0;
442 | case 2:
443 | return 1;
444 | case 4:
445 | return 2;
446 | case 8:
447 | return 3;
448 | default:
449 | throw new TypeError("Unknown type size: " + r);
450 | }
451 | }
452 | function mn() {
453 | for (var r = new Array(256), n = 0; n < 256; ++n)
454 | r[n] = String.fromCharCode(n);
455 | jr = r;
456 | }
457 | var jr = void 0;
458 | function S(r) {
459 | for (var n = "", e = r; U[e]; ) n += jr[U[e++]];
460 | return n;
461 | }
462 | var Q = {},
463 | Y = {},
464 | cr = {},
465 | wn = 48,
466 | bn = 57;
467 | function Nr(r) {
468 | if (r === void 0) return "_unknown";
469 | r = r.replace(/[^a-zA-Z0-9_]/g, "$");
470 | var n = r.charCodeAt(0);
471 | return n >= wn && n <= bn ? "_" + r : r;
472 | }
473 | function qr(r, n) {
474 | return (
475 | (r = Nr(r)),
476 | new Function(
477 | "body",
478 | "return function " +
479 | r +
480 | `() {
481 | "use strict"; return body.apply(this, arguments);
482 | };
483 | `
484 | )(n)
485 | );
486 | }
487 | function mr(r, n) {
488 | var e = qr(n, function (i) {
489 | (this.name = n), (this.message = i);
490 | var a = new Error(i).stack;
491 | a !== void 0 &&
492 | (this.stack =
493 | this.toString() +
494 | `
495 | ` +
496 | a.replace(/^Error(:[^\n]*)?\n/, ""));
497 | });
498 | return (
499 | (e.prototype = Object.create(r.prototype)),
500 | (e.prototype.constructor = e),
501 | (e.prototype.toString = function () {
502 | return this.message === void 0
503 | ? this.name
504 | : this.name + ": " + this.message;
505 | }),
506 | e
507 | );
508 | }
509 | var xr = void 0;
510 | function T(r) {
511 | throw new xr(r);
512 | }
513 | var zr = void 0;
514 | function Xr(r) {
515 | throw new zr(r);
516 | }
517 | function An(r, n, e) {
518 | r.forEach(function (o) {
519 | cr[o] = n;
520 | });
521 | function i(o) {
522 | var s = e(o);
523 | s.length !== r.length && Xr("Mismatched type converter count");
524 | for (var v = 0; v < r.length; ++v) H(r[v], s[v]);
525 | }
526 | var a = new Array(n.length),
527 | f = [],
528 | c = 0;
529 | n.forEach(function (o, s) {
530 | Y.hasOwnProperty(o)
531 | ? (a[s] = Y[o])
532 | : (f.push(o),
533 | Q.hasOwnProperty(o) || (Q[o] = []),
534 | Q[o].push(function () {
535 | (a[s] = Y[o]), ++c, c === f.length && i(a);
536 | }));
537 | }),
538 | f.length === 0 && i(a);
539 | }
540 | function H(r, n, e) {
541 | if (((e = e || {}), !("argPackAdvance" in n)))
542 | throw new TypeError(
543 | "registerType registeredInstance requires argPackAdvance"
544 | );
545 | var i = n.name;
546 | if (
547 | (r ||
548 | T('type "' + i + '" must have a positive integer typeid pointer'),
549 | Y.hasOwnProperty(r))
550 | ) {
551 | if (e.ignoreDuplicateRegistrations) return;
552 | T("Cannot register type '" + i + "' twice");
553 | }
554 | if (((Y[r] = n), delete cr[r], Q.hasOwnProperty(r))) {
555 | var a = Q[r];
556 | delete Q[r],
557 | a.forEach(function (f) {
558 | f();
559 | });
560 | }
561 | }
562 | function En(r, n, e, i, a) {
563 | var f = dr(e);
564 | (n = S(n)),
565 | H(r, {
566 | name: n,
567 | fromWireType: function (c) {
568 | return !!c;
569 | },
570 | toWireType: function (c, o) {
571 | return o ? i : a;
572 | },
573 | argPackAdvance: 8,
574 | readValueFromPointer: function (c) {
575 | var o;
576 | if (e === 1) o = _r;
577 | else if (e === 2) o = Z;
578 | else if (e === 4) o = V;
579 | else throw new TypeError("Unknown boolean type size: " + n);
580 | return this.fromWireType(o[c >> f]);
581 | },
582 | destructorFunction: null,
583 | });
584 | }
585 | var wr = [],
586 | C = [
587 | {},
588 | { value: void 0 },
589 | { value: null },
590 | { value: !0 },
591 | { value: !1 },
592 | ];
593 | function br(r) {
594 | r > 4 && --C[r].refcount == 0 && ((C[r] = void 0), wr.push(r));
595 | }
596 | function Tn() {
597 | for (var r = 0, n = 5; n < C.length; ++n) C[n] !== void 0 && ++r;
598 | return r;
599 | }
600 | function Cn() {
601 | for (var r = 5; r < C.length; ++r) if (C[r] !== void 0) return C[r];
602 | return null;
603 | }
604 | function Fn() {
605 | (t.count_emval_handles = Tn), (t.get_first_emval = Cn);
606 | }
607 | function M(r) {
608 | switch (r) {
609 | case void 0:
610 | return 1;
611 | case null:
612 | return 2;
613 | case !0:
614 | return 3;
615 | case !1:
616 | return 4;
617 | default: {
618 | var n = wr.length ? wr.pop() : C.length;
619 | return (C[n] = { refcount: 1, value: r }), n;
620 | }
621 | }
622 | }
623 | function Ar(r) {
624 | return this.fromWireType(D[r >> 2]);
625 | }
626 | function Pn(r, n) {
627 | (n = S(n)),
628 | H(r, {
629 | name: n,
630 | fromWireType: function (e) {
631 | var i = C[e].value;
632 | return br(e), i;
633 | },
634 | toWireType: function (e, i) {
635 | return M(i);
636 | },
637 | argPackAdvance: 8,
638 | readValueFromPointer: Ar,
639 | destructorFunction: null,
640 | });
641 | }
642 | function Er(r) {
643 | if (r === null) return "null";
644 | var n = typeof r;
645 | return n === "object" || n === "array" || n === "function"
646 | ? r.toString()
647 | : "" + r;
648 | }
649 | function Un(r, n) {
650 | switch (n) {
651 | case 2:
652 | return function (e) {
653 | return this.fromWireType(kr[e >> 2]);
654 | };
655 | case 3:
656 | return function (e) {
657 | return this.fromWireType(Ir[e >> 3]);
658 | };
659 | default:
660 | throw new TypeError("Unknown float type: " + r);
661 | }
662 | }
663 | function Rn(r, n, e) {
664 | var i = dr(e);
665 | (n = S(n)),
666 | H(r, {
667 | name: n,
668 | fromWireType: function (a) {
669 | return a;
670 | },
671 | toWireType: function (a, f) {
672 | if (typeof f != "number" && typeof f != "boolean")
673 | throw new TypeError(
674 | 'Cannot convert "' + Er(f) + '" to ' + this.name
675 | );
676 | return f;
677 | },
678 | argPackAdvance: 8,
679 | readValueFromPointer: Un(n, i),
680 | destructorFunction: null,
681 | });
682 | }
683 | function Sn(r, n) {
684 | if (!(r instanceof Function))
685 | throw new TypeError(
686 | "new_ called with constructor type " +
687 | typeof r +
688 | " which is not a function"
689 | );
690 | var e = qr(r.name || "unknownFunctionName", function () {});
691 | e.prototype = r.prototype;
692 | var i = new e(),
693 | a = r.apply(i, n);
694 | return a instanceof Object ? a : i;
695 | }
696 | function Gr(r) {
697 | for (; r.length; ) {
698 | var n = r.pop(),
699 | e = r.pop();
700 | e(n);
701 | }
702 | }
703 | function Wn(r, n, e, i, a) {
704 | var f = n.length;
705 | f < 2 &&
706 | T(
707 | "argTypes array size mismatch! Must at least get return value and 'this' types!"
708 | );
709 | for (
710 | var c = n[1] !== null && e !== null, o = !1, s = 1;
711 | s < n.length;
712 | ++s
713 | )
714 | if (n[s] !== null && n[s].destructorFunction === void 0) {
715 | o = !0;
716 | break;
717 | }
718 | for (
719 | var v = n[0].name !== "void", g = "", d = "", s = 0;
720 | s < f - 2;
721 | ++s
722 | )
723 | (g += (s !== 0 ? ", " : "") + "arg" + s),
724 | (d += (s !== 0 ? ", " : "") + "arg" + s + "Wired");
725 | var F =
726 | "return function " +
727 | Nr(r) +
728 | "(" +
729 | g +
730 | `) {
731 | if (arguments.length !== ` +
732 | (f - 2) +
733 | `) {
734 | throwBindingError('function ` +
735 | r +
736 | " called with ' + arguments.length + ' arguments, expected " +
737 | (f - 2) +
738 | ` args!');
739 | }
740 | `;
741 | o &&
742 | (F += `var destructors = [];
743 | `);
744 | var $ = o ? "destructors" : "null",
745 | q = [
746 | "throwBindingError",
747 | "invoker",
748 | "fn",
749 | "runDestructors",
750 | "retType",
751 | "classParam",
752 | ],
753 | fr = [T, i, a, Gr, n[0], n[1]];
754 | c &&
755 | (F +=
756 | "var thisWired = classParam.toWireType(" +
757 | $ +
758 | `, this);
759 | `);
760 | for (var s = 0; s < f - 2; ++s)
761 | (F +=
762 | "var arg" +
763 | s +
764 | "Wired = argType" +
765 | s +
766 | ".toWireType(" +
767 | $ +
768 | ", arg" +
769 | s +
770 | "); // " +
771 | n[s + 2].name +
772 | `
773 | `),
774 | q.push("argType" + s),
775 | fr.push(n[s + 2]);
776 | if (
777 | (c && (d = "thisWired" + (d.length > 0 ? ", " : "") + d),
778 | (F +=
779 | (v ? "var rv = " : "") +
780 | "invoker(fn" +
781 | (d.length > 0 ? ", " : "") +
782 | d +
783 | `);
784 | `),
785 | o)
786 | )
787 | F += `runDestructors(destructors);
788 | `;
789 | else
790 | for (var s = c ? 1 : 2; s < n.length; ++s) {
791 | var rr = s === 1 ? "thisWired" : "arg" + (s - 2) + "Wired";
792 | n[s].destructorFunction !== null &&
793 | ((F +=
794 | rr +
795 | "_dtor(" +
796 | rr +
797 | "); // " +
798 | n[s].name +
799 | `
800 | `),
801 | q.push(rr + "_dtor"),
802 | fr.push(n[s].destructorFunction));
803 | }
804 | v &&
805 | (F += `var ret = retType.fromWireType(rv);
806 | return ret;
807 | `),
808 | (F += `}
809 | `),
810 | q.push(F);
811 | var pe = Sn(Function, q).apply(null, fr);
812 | return pe;
813 | }
814 | function kn(r, n, e) {
815 | if (r[n].overloadTable === void 0) {
816 | var i = r[n];
817 | (r[n] = function () {
818 | return (
819 | r[n].overloadTable.hasOwnProperty(arguments.length) ||
820 | T(
821 | "Function '" +
822 | e +
823 | "' called with an invalid number of arguments (" +
824 | arguments.length +
825 | ") - expects one of (" +
826 | r[n].overloadTable +
827 | ")!"
828 | ),
829 | r[n].overloadTable[arguments.length].apply(this, arguments)
830 | );
831 | }),
832 | (r[n].overloadTable = []),
833 | (r[n].overloadTable[i.argCount] = i);
834 | }
835 | }
836 | function In(r, n, e) {
837 | t.hasOwnProperty(r)
838 | ? ((e === void 0 ||
839 | (t[r].overloadTable !== void 0 &&
840 | t[r].overloadTable[e] !== void 0)) &&
841 | T("Cannot register public name '" + r + "' twice"),
842 | kn(t, r, r),
843 | t.hasOwnProperty(e) &&
844 | T(
845 | "Cannot register multiple overloads of a function with the same number of arguments (" +
846 | e +
847 | ")!"
848 | ),
849 | (t[r].overloadTable[e] = n))
850 | : ((t[r] = n), e !== void 0 && (t[r].numArguments = e));
851 | }
852 | function On(r, n) {
853 | for (var e = [], i = 0; i < r; i++) e.push(V[(n >> 2) + i]);
854 | return e;
855 | }
856 | function Ln(r, n, e) {
857 | t.hasOwnProperty(r) || Xr("Replacing nonexistant public symbol"),
858 | t[r].overloadTable !== void 0 && e !== void 0
859 | ? (t[r].overloadTable[e] = n)
860 | : ((t[r] = n), (t[r].argCount = e));
861 | }
862 | function Vn(r, n, e) {
863 | var i = t["dynCall_" + r];
864 | return e && e.length ? i.apply(null, [n].concat(e)) : i.call(null, n);
865 | }
866 | function Dn(r, n, e) {
867 | return r.includes("j") ? Vn(r, n, e) : tr.get(n).apply(null, e);
868 | }
869 | function Hn(r, n) {
870 | var e = [];
871 | return function () {
872 | e.length = arguments.length;
873 | for (var i = 0; i < arguments.length; i++) e[i] = arguments[i];
874 | return Dn(r, n, e);
875 | };
876 | }
877 | function Bn(r, n) {
878 | r = S(r);
879 | function e() {
880 | return r.includes("j") ? Hn(r, n) : tr.get(n);
881 | }
882 | var i = e();
883 | return (
884 | typeof i != "function" &&
885 | T("unknown function pointer with signature " + r + ": " + n),
886 | i
887 | );
888 | }
889 | var Yr = void 0;
890 | function $r(r) {
891 | var n = Jr(r),
892 | e = S(n);
893 | return B(n), e;
894 | }
895 | function jn(r, n) {
896 | var e = [],
897 | i = {};
898 | function a(f) {
899 | if (!i[f] && !Y[f]) {
900 | if (cr[f]) {
901 | cr[f].forEach(a);
902 | return;
903 | }
904 | e.push(f), (i[f] = !0);
905 | }
906 | }
907 | throw (n.forEach(a), new Yr(r + ": " + e.map($r).join([", "])));
908 | }
909 | function Nn(r, n, e, i, a, f) {
910 | var c = On(n, e);
911 | (r = S(r)),
912 | (a = Bn(i, a)),
913 | In(
914 | r,
915 | function () {
916 | jn("Cannot call " + r + " due to unbound types", c);
917 | },
918 | n - 1
919 | ),
920 | An([], c, function (o) {
921 | var s = [o[0], null].concat(o.slice(1));
922 | return Ln(r, Wn(r, s, null, a, f), n - 1), [];
923 | });
924 | }
925 | function qn(r, n, e) {
926 | switch (n) {
927 | case 0:
928 | return e
929 | ? function (a) {
930 | return _r[a];
931 | }
932 | : function (a) {
933 | return U[a];
934 | };
935 | case 1:
936 | return e
937 | ? function (a) {
938 | return Z[a >> 1];
939 | }
940 | : function (a) {
941 | return hr[a >> 1];
942 | };
943 | case 2:
944 | return e
945 | ? function (a) {
946 | return V[a >> 2];
947 | }
948 | : function (a) {
949 | return D[a >> 2];
950 | };
951 | default:
952 | throw new TypeError("Unknown integer type: " + r);
953 | }
954 | }
955 | function xn(r, n, e, i, a) {
956 | (n = S(n)), a === -1 && (a = 4294967295);
957 | var f = dr(e),
958 | c = function (v) {
959 | return v;
960 | };
961 | if (i === 0) {
962 | var o = 32 - 8 * e;
963 | c = function (v) {
964 | return (v << o) >>> o;
965 | };
966 | }
967 | var s = n.includes("unsigned");
968 | H(r, {
969 | name: n,
970 | fromWireType: c,
971 | toWireType: function (v, g) {
972 | if (typeof g != "number" && typeof g != "boolean")
973 | throw new TypeError(
974 | 'Cannot convert "' + Er(g) + '" to ' + this.name
975 | );
976 | if (g < i || g > a)
977 | throw new TypeError(
978 | 'Passing a number "' +
979 | Er(g) +
980 | '" from JS side to C/C++ side to an argument of type "' +
981 | n +
982 | '", which is outside the valid range [' +
983 | i +
984 | ", " +
985 | a +
986 | "]!"
987 | );
988 | return s ? g >>> 0 : g | 0;
989 | },
990 | argPackAdvance: 8,
991 | readValueFromPointer: qn(n, f, i !== 0),
992 | destructorFunction: null,
993 | });
994 | }
995 | function zn(r, n, e) {
996 | var i = [
997 | Int8Array,
998 | Uint8Array,
999 | Int16Array,
1000 | Uint16Array,
1001 | Int32Array,
1002 | Uint32Array,
1003 | Float32Array,
1004 | Float64Array,
1005 | ],
1006 | a = i[n];
1007 | function f(c) {
1008 | c = c >> 2;
1009 | var o = D,
1010 | s = o[c],
1011 | v = o[c + 1];
1012 | return new a(pr, v, s);
1013 | }
1014 | (e = S(e)),
1015 | H(
1016 | r,
1017 | {
1018 | name: e,
1019 | fromWireType: f,
1020 | argPackAdvance: 8,
1021 | readValueFromPointer: f,
1022 | },
1023 | { ignoreDuplicateRegistrations: !0 }
1024 | );
1025 | }
1026 | function Xn(r, n) {
1027 | n = S(n);
1028 | var e = n === "std::string";
1029 | H(r, {
1030 | name: n,
1031 | fromWireType: function (i) {
1032 | var a = D[i >> 2],
1033 | f;
1034 | if (e)
1035 | for (var c = i + 4, o = 0; o <= a; ++o) {
1036 | var s = i + 4 + o;
1037 | if (o == a || U[s] == 0) {
1038 | var v = s - c,
1039 | g = A(c, v);
1040 | f === void 0
1041 | ? (f = g)
1042 | : ((f += String.fromCharCode(0)), (f += g)),
1043 | (c = s + 1);
1044 | }
1045 | }
1046 | else {
1047 | for (var d = new Array(a), o = 0; o < a; ++o)
1048 | d[o] = String.fromCharCode(U[i + 4 + o]);
1049 | f = d.join("");
1050 | }
1051 | return B(i), f;
1052 | },
1053 | toWireType: function (i, a) {
1054 | a instanceof ArrayBuffer && (a = new Uint8Array(a));
1055 | var f,
1056 | c = typeof a == "string";
1057 | c ||
1058 | a instanceof Uint8Array ||
1059 | a instanceof Uint8ClampedArray ||
1060 | a instanceof Int8Array ||
1061 | T("Cannot pass non-string to std::string"),
1062 | e && c
1063 | ? (f = function () {
1064 | return vr(a);
1065 | })
1066 | : (f = function () {
1067 | return a.length;
1068 | });
1069 | var o = f(),
1070 | s = Cr(4 + o + 1);
1071 | if (((D[s >> 2] = o), e && c)) E(a, s + 4, o + 1);
1072 | else if (c)
1073 | for (var v = 0; v < o; ++v) {
1074 | var g = a.charCodeAt(v);
1075 | g > 255 &&
1076 | (B(s),
1077 | T("String has UTF-16 code units that do not fit in 8 bits")),
1078 | (U[s + 4 + v] = g);
1079 | }
1080 | else for (var v = 0; v < o; ++v) U[s + 4 + v] = a[v];
1081 | return i !== null && i.push(B, s), s;
1082 | },
1083 | argPackAdvance: 8,
1084 | readValueFromPointer: Ar,
1085 | destructorFunction: function (i) {
1086 | B(i);
1087 | },
1088 | });
1089 | }
1090 | function Gn(r, n, e) {
1091 | e = S(e);
1092 | var i, a, f, c, o;
1093 | n === 2
1094 | ? ((i = Zr),
1095 | (a = Qr),
1096 | (c = Mr),
1097 | (f = function () {
1098 | return hr;
1099 | }),
1100 | (o = 1))
1101 | : n === 4 &&
1102 | ((i = rn),
1103 | (a = nn),
1104 | (c = en),
1105 | (f = function () {
1106 | return D;
1107 | }),
1108 | (o = 2)),
1109 | H(r, {
1110 | name: e,
1111 | fromWireType: function (s) {
1112 | for (
1113 | var v = D[s >> 2], g = f(), d, F = s + 4, $ = 0;
1114 | $ <= v;
1115 | ++$
1116 | ) {
1117 | var q = s + 4 + $ * n;
1118 | if ($ == v || g[q >> o] == 0) {
1119 | var fr = q - F,
1120 | rr = i(F, fr);
1121 | d === void 0
1122 | ? (d = rr)
1123 | : ((d += String.fromCharCode(0)), (d += rr)),
1124 | (F = q + n);
1125 | }
1126 | }
1127 | return B(s), d;
1128 | },
1129 | toWireType: function (s, v) {
1130 | typeof v != "string" &&
1131 | T("Cannot pass non-string to C++ string type " + e);
1132 | var g = c(v),
1133 | d = Cr(4 + g + n);
1134 | return (
1135 | (D[d >> 2] = g >> o),
1136 | a(v, d + 4, g + n),
1137 | s !== null && s.push(B, d),
1138 | d
1139 | );
1140 | },
1141 | argPackAdvance: 8,
1142 | readValueFromPointer: Ar,
1143 | destructorFunction: function (s) {
1144 | B(s);
1145 | },
1146 | });
1147 | }
1148 | function Yn(r, n) {
1149 | (n = S(n)),
1150 | H(r, {
1151 | isVoid: !0,
1152 | name: n,
1153 | argPackAdvance: 0,
1154 | fromWireType: function () {},
1155 | toWireType: function (e, i) {},
1156 | });
1157 | }
1158 | function or(r) {
1159 | return r || T("Cannot use deleted val. handle = " + r), C[r].value;
1160 | }
1161 | function Tr(r, n) {
1162 | var e = Y[r];
1163 | return e === void 0 && T(n + " has unknown type " + $r(r)), e;
1164 | }
1165 | function $n(r, n, e) {
1166 | (r = or(r)), (n = Tr(n, "emval::as"));
1167 | var i = [],
1168 | a = M(i);
1169 | return (V[e >> 2] = a), n.toWireType(i, r);
1170 | }
1171 | function Jn(r, n) {
1172 | for (var e = new Array(r), i = 0; i < r; ++i)
1173 | e[i] = Tr(V[(n >> 2) + i], "parameter " + i);
1174 | return e;
1175 | }
1176 | function Kn(r, n, e, i) {
1177 | r = or(r);
1178 | for (var a = Jn(n, e), f = new Array(n), c = 0; c < n; ++c) {
1179 | var o = a[c];
1180 | (f[c] = o.readValueFromPointer(i)), (i += o.argPackAdvance);
1181 | }
1182 | var s = r.apply(void 0, f);
1183 | return M(s);
1184 | }
1185 | function Zn(r, n) {
1186 | return (r = or(r)), (n = or(n)), M(r[n]);
1187 | }
1188 | function Qn(r) {
1189 | r > 4 && (C[r].refcount += 1);
1190 | }
1191 | function Mn(r) {
1192 | return (r = or(r)), typeof r == "number";
1193 | }
1194 | var re = {};
1195 | function ne(r) {
1196 | var n = re[r];
1197 | return n === void 0 ? S(r) : n;
1198 | }
1199 | function ee(r) {
1200 | return M(ne(r));
1201 | }
1202 | function te(r) {
1203 | var n = C[r].value;
1204 | Gr(n), br(r);
1205 | }
1206 | function ie(r, n) {
1207 | r = Tr(r, "_emval_take_value");
1208 | var e = r.readValueFromPointer(n);
1209 | return M(e);
1210 | }
1211 | function ae() {
1212 | ar();
1213 | }
1214 | function oe(r, n, e) {
1215 | U.copyWithin(r, n, n + e);
1216 | }
1217 | function fe(r) {
1218 | try {
1219 | return K.grow((r - pr.byteLength + 65535) >>> 16), Or(K.buffer), 1;
1220 | } catch (n) {}
1221 | }
1222 | function se(r) {
1223 | var n = U.length;
1224 | r = r >>> 0;
1225 | var e = 2147483648;
1226 | if (r > e) return !1;
1227 | for (var i = 1; i <= 4; i *= 2) {
1228 | var a = n * (1 + 0.2 / i);
1229 | a = Math.min(a, r + 100663296);
1230 | var f = Math.min(e, tn(Math.max(r, a), 65536)),
1231 | c = fe(f);
1232 | if (c) return !0;
1233 | }
1234 | return !1;
1235 | }
1236 | mn(),
1237 | (xr = t.BindingError = mr(Error, "BindingError")),
1238 | (zr = t.InternalError = mr(Error, "InternalError")),
1239 | Fn(),
1240 | (Yr = t.UnboundTypeError = mr(Error, "UnboundTypeError"));
1241 | var ce = {
1242 | a: yn,
1243 | q: dn,
1244 | u: En,
1245 | t: Pn,
1246 | m: Rn,
1247 | k: Nn,
1248 | d: xn,
1249 | c: zn,
1250 | n: Xn,
1251 | l: Gn,
1252 | v: Yn,
1253 | j: $n,
1254 | w: Kn,
1255 | b: br,
1256 | e: Zn,
1257 | g: Qn,
1258 | p: Mn,
1259 | f: ee,
1260 | i: te,
1261 | h: ie,
1262 | o: ae,
1263 | r: oe,
1264 | s: se,
1265 | },
1266 | we = gn(),
1267 | ue = (t.___wasm_call_ctors = function () {
1268 | return (ue = t.___wasm_call_ctors = t.asm.y).apply(null, arguments);
1269 | }),
1270 | Cr = (t._malloc = function () {
1271 | return (Cr = t._malloc = t.asm.z).apply(null, arguments);
1272 | }),
1273 | B = (t._free = function () {
1274 | return (B = t._free = t.asm.A).apply(null, arguments);
1275 | }),
1276 | Jr = (t.___getTypeName = function () {
1277 | return (Jr = t.___getTypeName = t.asm.C).apply(null, arguments);
1278 | }),
1279 | le = (t.___embind_register_native_and_builtin_types = function () {
1280 | return (le = t.___embind_register_native_and_builtin_types =
1281 | t.asm.D).apply(null, arguments);
1282 | }),
1283 | ve = (t.dynCall_ijiii = function () {
1284 | return (ve = t.dynCall_ijiii = t.asm.E).apply(null, arguments);
1285 | }),
1286 | ur;
1287 | ir = function r() {
1288 | ur || Fr(), ur || (ir = r);
1289 | };
1290 | function Fr(r) {
1291 | if (((r = r || p), G > 0 || (on(), G > 0))) return;
1292 | function n() {
1293 | ur ||
1294 | ((ur = !0),
1295 | (t.calledRun = !0),
1296 | !w &&
1297 | (fn(),
1298 | u(t),
1299 | t.onRuntimeInitialized && t.onRuntimeInitialized(),
1300 | sn()));
1301 | }
1302 | t.setStatus
1303 | ? (t.setStatus("Running..."),
1304 | setTimeout(function () {
1305 | setTimeout(function () {
1306 | t.setStatus("");
1307 | }, 1),
1308 | n();
1309 | }, 1))
1310 | : n();
1311 | }
1312 | if (((t.run = Fr), t.preInit))
1313 | for (
1314 | typeof t.preInit == "function" && (t.preInit = [t.preInit]);
1315 | t.preInit.length > 0;
1316 |
1317 | )
1318 | t.preInit.pop()();
1319 | return Fr(), t.ready;
1320 | };
1321 | })();
1322 |
1323 | /* post code */
1324 | const START_CODE = new Uint8Array([0, 0, 0, 1]);
1325 |
1326 | function defaultError(error) {
1327 | console.error(error);
1328 | }
1329 |
1330 | Module.createFile = createFile;
1331 | export function createFile(initialCapacity = 256) {
1332 | let cursor = 0;
1333 | let usedBytes = 0;
1334 | let contents = new Uint8Array(initialCapacity);
1335 | return {
1336 | contents: function () {
1337 | return contents.slice(0, usedBytes);
1338 | },
1339 | seek: function (offset) {
1340 | // offset in bytes
1341 | cursor = offset;
1342 | },
1343 | write: function (data) {
1344 | const size = data.byteLength;
1345 | expand(cursor + size);
1346 | contents.set(data, cursor);
1347 | cursor += size;
1348 | usedBytes = Math.max(usedBytes, cursor);
1349 | return size;
1350 | },
1351 | };
1352 |
1353 | function expand(newCapacity) {
1354 | var prevCapacity = contents.length;
1355 | if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
1356 | // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
1357 | // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
1358 | // avoid overshooting the allocation cap by a very large margin.
1359 | var CAPACITY_DOUBLING_MAX = 1024 * 1024;
1360 | newCapacity = Math.max(
1361 | newCapacity,
1362 | (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>>
1363 | 0
1364 | );
1365 | if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
1366 | const oldContents = contents;
1367 | contents = new Uint8Array(newCapacity); // Allocate new storage.
1368 | if (usedBytes > 0) contents.set(oldContents.subarray(0, usedBytes), 0);
1369 | }
1370 | }
1371 |
1372 | Module.isWebCodecsSupported = isWebCodecsSupported;
1373 | export function isWebCodecsSupported() {
1374 | return (
1375 | typeof window !== "undefined" && typeof window.VideoEncoder === "function"
1376 | );
1377 | }
1378 |
1379 | export function createWebCodecsEncoderWithModule(MP4, opts = {}) {
1380 | const {
1381 | width,
1382 | height,
1383 | groupOfPictures = 20,
1384 | fps = 30,
1385 | fragmentation = false,
1386 | sequential = false,
1387 | hevc = false,
1388 | format = "annexb",
1389 | // codec = "avc1.420034", // Baseline 4.2
1390 | codec = "avc1.4d0034", // Main 5.2
1391 | acceleration,
1392 | bitrate,
1393 | error = defaultError,
1394 | encoderOptions = {},
1395 | flushFrequency = 10,
1396 | } = opts;
1397 |
1398 | if (!isWebCodecsSupported()) {
1399 | throw new Error(
1400 | "MP4 H264 encoding/decoding depends on WebCodecs API which is not supported in this environment"
1401 | );
1402 | }
1403 |
1404 | if (typeof width !== "number" || typeof height !== "number") {
1405 | throw new Error("Must specify { width, height } options");
1406 | }
1407 |
1408 | if (!isFinite(width) || width < 0 || !isFinite(height) || height < 0) {
1409 | throw new Error("{ width, height } options must be positive integers");
1410 | }
1411 |
1412 | const file = createFile();
1413 | const mux = MP4.create_muxer(
1414 | {
1415 | width,
1416 | height,
1417 | fps,
1418 | fragmentation,
1419 | sequential,
1420 | hevc,
1421 | },
1422 | mux_write
1423 | );
1424 |
1425 | const config = {
1426 | codec,
1427 | width: width,
1428 | height: height,
1429 | avc: {
1430 | format,
1431 | },
1432 | hardwareAcceleration: acceleration,
1433 | // There is a bug on macOS if this is greater than 30 fps
1434 | // framerate: fps,
1435 | bitrate,
1436 | ...encoderOptions,
1437 | };
1438 |
1439 | let frameIndex = 0;
1440 |
1441 | const encoder = new window.VideoEncoder({
1442 | output(chunk, opts) {
1443 | writeAVC(chunk, opts);
1444 | },
1445 | error,
1446 | });
1447 | encoder.configure(config);
1448 |
1449 | return {
1450 | async end() {
1451 | await encoder.flush();
1452 | encoder.close();
1453 | MP4.finalize_muxer(mux);
1454 | return file.contents();
1455 | },
1456 | async addFrame(bitmap) {
1457 | const timestamp = (1 / fps) * frameIndex * 1000000;
1458 | const keyFrame = frameIndex % groupOfPictures === 0;
1459 | let frame = new VideoFrame(bitmap, { timestamp });
1460 | encoder.encode(frame, { keyFrame });
1461 | frame.close();
1462 | if (flushFrequency != null && (frameIndex + 1) % flushFrequency === 0) {
1463 | await encoder.flush();
1464 | }
1465 | frameIndex++;
1466 | },
1467 | async flush() {
1468 | return encoder.flush();
1469 | },
1470 | };
1471 |
1472 | function mux_write(data_ptr, size, offset) {
1473 | // seek to byte offset in file
1474 | file.seek(offset);
1475 | // get subarray of memory we are writing
1476 | const data = MP4.HEAPU8.subarray(data_ptr, data_ptr + size);
1477 | // write into virtual file
1478 | return file.write(data) !== data.byteLength;
1479 | }
1480 |
1481 | function write_nal(uint8) {
1482 | const p = MP4._malloc(uint8.byteLength);
1483 | MP4.HEAPU8.set(uint8, p);
1484 | MP4.mux_nal(mux, p, uint8.byteLength);
1485 | MP4._free(p);
1486 | }
1487 |
1488 | function writeAVC(chunk, opts) {
1489 | let avccConfig = null;
1490 |
1491 | let description;
1492 | if (opts) {
1493 | if (opts.description) {
1494 | description = opts.description;
1495 | }
1496 | if (opts.decoderConfig && opts.decoderConfig.description) {
1497 | description = opts.decoderConfig.description;
1498 | }
1499 | }
1500 |
1501 | if (description) {
1502 | try {
1503 | avccConfig = parseAVCC(description);
1504 | } catch (err) {
1505 | error(err);
1506 | return;
1507 | }
1508 | }
1509 |
1510 | const nal = [];
1511 | if (avccConfig) {
1512 | avccConfig.sps_list.forEach((sps) => {
1513 | nal.push(START_CODE);
1514 | nal.push(sps);
1515 | });
1516 | avccConfig.pps_list.forEach((pps) => {
1517 | nal.push(START_CODE);
1518 | nal.push(pps);
1519 | });
1520 | }
1521 |
1522 | if (format === "annexb") {
1523 | const uint8 = new Uint8Array(chunk.byteLength);
1524 | chunk.copyTo(uint8);
1525 | nal.push(uint8);
1526 | } else {
1527 | try {
1528 | const arrayBuf = new ArrayBuffer(chunk.byteLength);
1529 | chunk.copyTo(arrayBuf);
1530 | convertAVCToAnnexBInPlaceForLength4(arrayBuf).forEach((sub) => {
1531 | nal.push(START_CODE);
1532 | nal.push(sub);
1533 | });
1534 | } catch (err) {
1535 | error(err);
1536 | return;
1537 | }
1538 | }
1539 |
1540 | write_nal(concatBuffers(nal));
1541 | }
1542 | }
1543 |
1544 | function concatBuffers(arrays) {
1545 | // Calculate byteSize from all arrays
1546 | const size = arrays.reduce((a, b) => a + b.byteLength, 0);
1547 | // Allcolate a new buffer
1548 | const result = new Uint8Array(size);
1549 | let offset = 0;
1550 | for (let i = 0; i < arrays.length; i++) {
1551 | const arr = arrays[i];
1552 | result.set(arr, offset);
1553 | offset += arr.byteLength;
1554 | }
1555 | return result;
1556 | }
1557 |
1558 | function convertAVCToAnnexBInPlaceForLength4(arrayBuf) {
1559 | const kLengthSize = 4;
1560 | let pos = 0;
1561 | const chunks = [];
1562 | const size = arrayBuf.byteLength;
1563 | const uint8 = new Uint8Array(arrayBuf);
1564 | while (pos + kLengthSize < size) {
1565 | // read uint 32, 4 byte NAL length
1566 | let nal_length = uint8[pos];
1567 | nal_length = (nal_length << 8) + uint8[pos + 1];
1568 | nal_length = (nal_length << 8) + uint8[pos + 2];
1569 | nal_length = (nal_length << 8) + uint8[pos + 3];
1570 |
1571 | chunks.push(new Uint8Array(arrayBuf, pos + kLengthSize, nal_length));
1572 | if (nal_length == 0) throw new Error("Error: invalid nal_length 0");
1573 | pos += kLengthSize + nal_length;
1574 | }
1575 | return chunks;
1576 | }
1577 |
1578 | function parseAVCC(avcc) {
1579 | const view = new DataView(avcc);
1580 | let off = 0;
1581 | const version = view.getUint8(off++);
1582 | const profile = view.getUint8(off++);
1583 | const compat = view.getUint8(off++);
1584 | const level = view.getUint8(off++);
1585 | const length_size = (view.getUint8(off++) & 0x3) + 1;
1586 | if (length_size !== 4)
1587 | throw new Error("Expected length_size to indicate 4 bytes");
1588 | const numSPS = view.getUint8(off++) & 0x1f;
1589 | const sps_list = [];
1590 | for (let i = 0; i < numSPS; i++) {
1591 | const sps_len = view.getUint16(off, false);
1592 | off += 2;
1593 | const sps = new Uint8Array(view.buffer, off, sps_len);
1594 | sps_list.push(sps);
1595 | off += sps_len;
1596 | }
1597 | const numPPS = view.getUint8(off++);
1598 | const pps_list = [];
1599 | for (let i = 0; i < numPPS; i++) {
1600 | const pps_len = view.getUint16(off, false);
1601 | off += 2;
1602 | const pps = new Uint8Array(view.buffer, off, pps_len);
1603 | pps_list.push(pps);
1604 | off += pps_len;
1605 | }
1606 | return {
1607 | offset: off,
1608 | version,
1609 | profile,
1610 | compat,
1611 | level,
1612 | length_size,
1613 | pps_list,
1614 | sps_list,
1615 | numSPS,
1616 | };
1617 | }
1618 |
1619 | export {Module as default};
1620 |
--------------------------------------------------------------------------------