@brandbrigade/ott-bb-player 1.0.45 → 1.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/OTTPlayer.js +50 -21
- package/package.json +4 -2
- package/src/Ads.js +0 -82
- package/src/Augmentor.js +0 -1288
- package/src/Composer3DBase.js +0 -754
- package/src/Composer3DForMainThread.js +0 -131
- package/src/Composer3DForWorker.js +0 -80
- package/src/Composer3DWorker.js +0 -60
- package/src/MetaDataDecoder.js +0 -143
- package/src/MetaDataFetcher.js +0 -88
- package/src/OTTPlayer.js +0 -254
- package/src/Socket.js +0 -44
- package/src/composer_worker.js +0 -30
- package/src/configs/OTT_Dev_Config_Debug.json +0 -8
- package/src/configs/OTT_Dev_Config_Debug_14fps.json +0 -8
- package/src/configs/OTT_Dev_Config_Debug_29fps.json +0 -8
- package/src/configs/OTT_Dev_Config_Debug_General.json +0 -7
- package/src/enums/RenderingMode.js +0 -5
- package/src/enums/SyncMethod.js +0 -5
- package/src/index.js +0 -241
- package/src/meta_worker.js +0 -144
- package/src/shaders/v1.js +0 -87
- package/src/shaders/v1Old.js +0 -174
- package/src/shaders/v2.js +0 -193
- package/src/test-pages/mp4/index.html +0 -63
- package/src/test-pages/mp4/index.js +0 -23
- package/src/test-pages/mp4/style.css +0 -16
- package/src/utils/FPSFetter.js +0 -94
- package/src/utils/MedianCalculator.js +0 -27
- package/src/utils/index.js +0 -5
- package/src/utils/isPowerOf2.js +0 -3
- package/src/utils/platform.js +0 -191
- package/src/utils/timeCodeUtils.js +0 -274
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import Composer3DBase from "./Composer3DBase";
|
|
2
|
-
import { createProgramFromSources } from "twgl.js";
|
|
3
|
-
import { vertexShaderSourceV1, fragmentShaderSourceV1 } from "./shaders/v1";
|
|
4
|
-
import { vertexShaderSourceV1Old, fragmentShaderSourceV1Old } from "./shaders/v1Old";
|
|
5
|
-
|
|
6
|
-
export default class Composer3DForMainThread extends Composer3DBase {
|
|
7
|
-
constructor(options, videoContainer) {
|
|
8
|
-
super(options);
|
|
9
|
-
|
|
10
|
-
this.canvas = document.createElement("canvas");
|
|
11
|
-
this.ctx = this.canvas.getContext("webgl", {
|
|
12
|
-
premultipliedAlpha: false,
|
|
13
|
-
antialias: false,
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
let videoTag = videoContainer.getElementsByTagName("video")[0];
|
|
17
|
-
this.canvas.style.top = 0;
|
|
18
|
-
this.canvas.style.left = 0;
|
|
19
|
-
this.canvas.style.width = "100%";
|
|
20
|
-
this.canvas.style.zIndex = 100000;
|
|
21
|
-
this.canvas.width = videoContainer.clientWidth;
|
|
22
|
-
this.canvas.height = videoContainer.clientHeight;
|
|
23
|
-
this.canvas.style.position = "absolute";
|
|
24
|
-
this.canvas.width = 1280;
|
|
25
|
-
this.canvas.height = 720;
|
|
26
|
-
|
|
27
|
-
let nextElement = videoTag.nextSibling;
|
|
28
|
-
|
|
29
|
-
if (nextElement) videoContainer.insertBefore(this.canvas, nextElement);
|
|
30
|
-
else videoContainer.appendChild(this.canvas);
|
|
31
|
-
this.canvas.style["pointer-events"] = "none";
|
|
32
|
-
videoTag.addEventListener("click", (e) => {
|
|
33
|
-
this.onUserClickOnCanvas(e);
|
|
34
|
-
});
|
|
35
|
-
this.canvas.addEventListener("dblclick", this.ToggleFullscreen);
|
|
36
|
-
this.initGL();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
initGL() {
|
|
40
|
-
const shaders = this.options.maskMP4 ?
|
|
41
|
-
[vertexShaderSourceV1, fragmentShaderSourceV1] :
|
|
42
|
-
[vertexShaderSourceV1Old, fragmentShaderSourceV1Old]
|
|
43
|
-
this.program = createProgramFromSources(this.ctx, shaders);
|
|
44
|
-
|
|
45
|
-
this.ctx.useProgram(this.program);
|
|
46
|
-
this.counter = 0;
|
|
47
|
-
this.cleanGL();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
createDigitImg(str) {
|
|
51
|
-
let canvas = document.createElement("canvas");
|
|
52
|
-
canvas.width = 50;
|
|
53
|
-
canvas.height = 50;
|
|
54
|
-
let ctx = canvas.getContext("2d");
|
|
55
|
-
ctx.fillStyle = "black";
|
|
56
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
57
|
-
ctx.font = "30px Arial";
|
|
58
|
-
ctx.fillStyle = "white";
|
|
59
|
-
ctx.fillText(str, 10, 35); // Adjust the position as needed
|
|
60
|
-
let dataURL = canvas.toDataURL();
|
|
61
|
-
let img = document.createElement("img");
|
|
62
|
-
img.src = dataURL;
|
|
63
|
-
|
|
64
|
-
return img;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
cleanGL() {
|
|
68
|
-
super.cleanGL();
|
|
69
|
-
}
|
|
70
|
-
getCanvas() {
|
|
71
|
-
return this.canvas;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
addAdvertisement(name, path, cb = null) {
|
|
75
|
-
if (name.indexOf(".json") > -1) {
|
|
76
|
-
fetch(path).then(async (res) => {
|
|
77
|
-
this.place2ad = await res.json();
|
|
78
|
-
this.ad2place = {};
|
|
79
|
-
let placesArr = Object.keys(this.place2ad);
|
|
80
|
-
for (let i = 0; i < placesArr.length; ++i) {
|
|
81
|
-
let place = placesArr[i];
|
|
82
|
-
if (place == "urls") {
|
|
83
|
-
this.ad2Url = this.place2ad[place];
|
|
84
|
-
delete this.place2ad[place];
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
let adsForThisPlace = this.place2ad[place];
|
|
88
|
-
for (let j = 0; j < adsForThisPlace.length; ++j) {
|
|
89
|
-
let ad = adsForThisPlace[j];
|
|
90
|
-
this.ad2place["#" + ad] = place;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (Object.keys(this.place2ad).length > 0) {
|
|
94
|
-
console.log(
|
|
95
|
-
"composer::AddAdvertisement: place-to-ads mapping: ",
|
|
96
|
-
this.place2ad,
|
|
97
|
-
);
|
|
98
|
-
console.log(
|
|
99
|
-
"composer::AddAdvertisement: ads-to-place mapping: ",
|
|
100
|
-
this.ad2place,
|
|
101
|
-
);
|
|
102
|
-
setTimeout(() => {
|
|
103
|
-
this.makeSureAdPerPlace();
|
|
104
|
-
}, 3000); //make sure its ad is in the right place once all ads are loaded
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
if (cb) cb();
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const adImage = new Image();
|
|
111
|
-
adImage.crossOrigin = "Anonymous";
|
|
112
|
-
adImage.onload = () => {
|
|
113
|
-
let isFirst = Object.keys(this.advertisementMap).length === 0;
|
|
114
|
-
this.advertisementMap[name] = adImage;
|
|
115
|
-
console.log("composer::AddAdvertisement", name);
|
|
116
|
-
if (isFirst) {
|
|
117
|
-
this.selectAd(name);
|
|
118
|
-
if (this.options.isAdLoop) {
|
|
119
|
-
clearTimeout(this.autoAddIndex);
|
|
120
|
-
this._nextAdvertisement();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (cb) cb();
|
|
124
|
-
};
|
|
125
|
-
adImage.onerror = () => {
|
|
126
|
-
alert(`( Security ) We cant reach ${path} .`);
|
|
127
|
-
};
|
|
128
|
-
adImage.src = path;
|
|
129
|
-
return adImage;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import Composer3DBase from "./Composer3DBase";
|
|
2
|
-
|
|
3
|
-
export default class Composer3DForWorker extends Composer3DBase {
|
|
4
|
-
constructor(options, canvas) {
|
|
5
|
-
super(options);
|
|
6
|
-
|
|
7
|
-
this.canvas = canvas;
|
|
8
|
-
this.ctx = this.canvas.getContext("webgl", {
|
|
9
|
-
premultipliedAlpha: false,
|
|
10
|
-
antialias: false,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
this.initGL();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async createDigitImg(str) {
|
|
17
|
-
let canvas = new OffscreenCanvas(50, 50);
|
|
18
|
-
let ctx = canvas.getContext("2d");
|
|
19
|
-
ctx.fillStyle = "black";
|
|
20
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
21
|
-
ctx.font = "30px Arial";
|
|
22
|
-
ctx.fillStyle = "white";
|
|
23
|
-
ctx.fillText(str, 10, 35);
|
|
24
|
-
|
|
25
|
-
return await canvas.transferToImageBitmap();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async addAdvertisement(params) {
|
|
29
|
-
let { name, path, isSelected } = params;
|
|
30
|
-
if (name.indexOf(".json") > -1) {
|
|
31
|
-
fetch(path).then(async (res) => {
|
|
32
|
-
this.place2ad = await res.json();
|
|
33
|
-
this.ad2place = {};
|
|
34
|
-
let placesArr = Object.keys(this.place2ad);
|
|
35
|
-
for (let i = 0; i < placesArr.length; ++i) {
|
|
36
|
-
let place = placesArr[i];
|
|
37
|
-
if (place == "urls") {
|
|
38
|
-
this.ad2Url = this.place2ad[place];
|
|
39
|
-
delete this.place2ad[place];
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
let adsForThisPlace = this.place2ad[place];
|
|
43
|
-
for (let j = 0; j < adsForThisPlace.length; ++j) {
|
|
44
|
-
let ad = adsForThisPlace[j];
|
|
45
|
-
this.ad2place["#" + ad] = place;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (Object.keys(this.place2ad).length > 0) {
|
|
49
|
-
console.log(
|
|
50
|
-
"composer::AddAdvertisement: place-to-ads mapping: ",
|
|
51
|
-
this.place2ad,
|
|
52
|
-
);
|
|
53
|
-
console.log(
|
|
54
|
-
"composer::AddAdvertisement: ads-to-place mapping: ",
|
|
55
|
-
this.ad2place,
|
|
56
|
-
);
|
|
57
|
-
setTimeout(() => {
|
|
58
|
-
this.makeSureAdPerPlace();
|
|
59
|
-
}, 3000); //make sure its ad is in the right place once all ads are loaded
|
|
60
|
-
}
|
|
61
|
-
if (isSelected) this.selectAd(name);
|
|
62
|
-
});
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const response = await fetch(path);
|
|
67
|
-
const blob = await response.blob();
|
|
68
|
-
const imageBitmap = await createImageBitmap(blob);
|
|
69
|
-
|
|
70
|
-
let isFirst = Object.keys(this.advertisementMap).length === 0;
|
|
71
|
-
this.advertisementMap[name] = imageBitmap;
|
|
72
|
-
if (isFirst) {
|
|
73
|
-
this.selectAd(name);
|
|
74
|
-
if (this.options.isAdLoop) {
|
|
75
|
-
clearTimeout(this.autoAddIndex);
|
|
76
|
-
this._nextAdvertisement();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
package/src/Composer3DWorker.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import ComposerWorker from "./composer_worker?worker&inline";
|
|
2
|
-
|
|
3
|
-
export default class Composer3DWorker {
|
|
4
|
-
constructor(canvas, options) {
|
|
5
|
-
this.canvas = canvas;
|
|
6
|
-
this.worker = new ComposerWorker();
|
|
7
|
-
|
|
8
|
-
this.worker.onmessage = (e) => {
|
|
9
|
-
const { action, url } = e.data;
|
|
10
|
-
if (action === "open-uri" && url) {
|
|
11
|
-
window.open(url, "_blank"); // Opens the URI in a new tab
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
const offscreen = canvas.transferControlToOffscreen();
|
|
15
|
-
let sourceFPS = 60000 / 1001;
|
|
16
|
-
let renderTimecodes = options.renderTimecode;
|
|
17
|
-
this.worker.postMessage(
|
|
18
|
-
{
|
|
19
|
-
method: "constructor",
|
|
20
|
-
canvas: offscreen,
|
|
21
|
-
options: { sourceFPS, renderTimecodes, maskMP4: options.maskMP4 },
|
|
22
|
-
},
|
|
23
|
-
[offscreen],
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
onUserClickOnCanvas(clientX, clientY, rect) {
|
|
28
|
-
this.worker.postMessage({
|
|
29
|
-
method: "onUserClickOnCanvas",
|
|
30
|
-
data: { clientX, clientY, rect },
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
cleanGL() {
|
|
35
|
-
this.worker.postMessage({ method: "cleanGL", data: "" });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
renderAugmentation(nextTimeCode) {
|
|
39
|
-
this.worker.postMessage({
|
|
40
|
-
method: "renderAugmentation",
|
|
41
|
-
data: nextTimeCode,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
addAdvertisement(params) {
|
|
46
|
-
this.worker.postMessage({ method: "addAdvertisement", data: params });
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
getCanvas() {
|
|
50
|
-
return this.canvas;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
selectAd(name) {
|
|
54
|
-
this.worker.postMessage({ method: "selectAd", data: name });
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
onMetaData(frameMetaData) {
|
|
58
|
-
this.worker.postMessage({ method: "onMetaData", data: frameMetaData });
|
|
59
|
-
}
|
|
60
|
-
}
|
package/src/MetaDataDecoder.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import MP4Box, { DataStream } from "mp4box";
|
|
2
|
-
import UZIP from "uzip";
|
|
3
|
-
|
|
4
|
-
export default class MetaDataDecoder {
|
|
5
|
-
async handleData(data, tc) {
|
|
6
|
-
const result = UZIP.parse(data);
|
|
7
|
-
if (result["alpha.mp4"] || result["alpha.webm"]) {
|
|
8
|
-
await this.decodeAlphaMaskVideo(result, tc);
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let sortedKeys = Object.keys(result).sort();
|
|
13
|
-
|
|
14
|
-
for (const key of sortedKeys) {
|
|
15
|
-
if (key.endsWith(".json")) {
|
|
16
|
-
let transferableArray = [];
|
|
17
|
-
const metadata = JSON.parse(new TextDecoder().decode(result[key]));
|
|
18
|
-
const tc = metadata.timecode.replace(/:/g, "_"); //replaceAll(":", "_");
|
|
19
|
-
if (metadata.placeholders) {
|
|
20
|
-
for (const groupId in metadata.placeholders) {
|
|
21
|
-
let alphaKey = `${tc}_${groupId}.alpha`;
|
|
22
|
-
if (result[alphaKey]) {
|
|
23
|
-
metadata.placeholders[groupId].alphaAsUint8Array = result[alphaKey];
|
|
24
|
-
transferableArray.push(result[alphaKey].buffer);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
postMessage(metadata, transferableArray);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getDescription(trak) {
|
|
34
|
-
for (const entry of trak.mdia.minf.stbl.stsd.entries) {
|
|
35
|
-
const box = entry.avcC || entry.hvcC || entry.vpcC || entry.av1C;
|
|
36
|
-
if (box) {
|
|
37
|
-
const stream = new DataStream(undefined, 0, DataStream.BIG_ENDIAN);
|
|
38
|
-
box.write(stream);
|
|
39
|
-
return new Uint8Array(stream.buffer, 8); // Remove the box header.
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
console.error("avcC, hvcC, vpcC, or av1C box not found on ", trak);
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
numericFileComparator(a, b) {
|
|
47
|
-
const regex = /^(\d{2})_(\d{2})_(\d{2})_(\d{2})(?:\.(\d+))?\.(.+)$/;
|
|
48
|
-
const matchA = a.match(regex);
|
|
49
|
-
const matchB = b.match(regex);
|
|
50
|
-
|
|
51
|
-
if (!matchA || !matchB) return 0;
|
|
52
|
-
|
|
53
|
-
const [, hoursA, minutesA, secondsA, framesA, versionA = "0", extA] =
|
|
54
|
-
matchA;
|
|
55
|
-
const [, hoursB, minutesB, secondsB, framesB, versionB = "0", extB] =
|
|
56
|
-
matchB;
|
|
57
|
-
|
|
58
|
-
return (
|
|
59
|
-
parseInt(hoursA, 10) - parseInt(hoursB, 10) ||
|
|
60
|
-
parseInt(minutesA, 10) - parseInt(minutesB, 10) ||
|
|
61
|
-
parseInt(secondsA, 10) - parseInt(secondsB, 10) ||
|
|
62
|
-
parseInt(framesA, 10) - parseInt(framesB, 10) ||
|
|
63
|
-
parseInt(versionA, 10) - parseInt(versionB, 10) ||
|
|
64
|
-
extA.localeCompare(extB)
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async decodeAlphaMaskVideo(result, tc) {
|
|
69
|
-
let metadatas = Object.keys(result)
|
|
70
|
-
.filter((a) => a.endsWith(".json"))
|
|
71
|
-
.sort(this.numericFileComparator)
|
|
72
|
-
.map((key) => JSON.parse(new TextDecoder().decode(result[key])))
|
|
73
|
-
.filter((json) => json["placeholders"]);
|
|
74
|
-
|
|
75
|
-
const start = performance.now();
|
|
76
|
-
const count = metadatas.length;
|
|
77
|
-
console.info("We need to decode ", count, "frames");
|
|
78
|
-
const blob = new Blob([result["alpha.mp4"] || result["alpha.webm"]], {
|
|
79
|
-
type: result["alpha.mp4"] ? "video/mp4" : "video/webm",
|
|
80
|
-
});
|
|
81
|
-
const arrayBuffer = await blob.arrayBuffer();
|
|
82
|
-
arrayBuffer.fileStart = 0;
|
|
83
|
-
let index = 0;
|
|
84
|
-
|
|
85
|
-
// Initialize the video decoder
|
|
86
|
-
const videoDecoder = new VideoDecoder({
|
|
87
|
-
output: (frame) => {
|
|
88
|
-
metadatas[index].alphaMask = frame;
|
|
89
|
-
postMessage(metadatas[index], [frame]);
|
|
90
|
-
frame.close()
|
|
91
|
-
|
|
92
|
-
index++;
|
|
93
|
-
if (index >= count) {
|
|
94
|
-
console.log(
|
|
95
|
-
tc,
|
|
96
|
-
"Decoded",
|
|
97
|
-
index,
|
|
98
|
-
"Frames in",
|
|
99
|
-
performance.now() - start,
|
|
100
|
-
"milliseconds.",
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
|
-
error: (e) => console.error("--Decoder error:", e),
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// Initialize MP4Box
|
|
108
|
-
const mp4boxfile = MP4Box.createFile();
|
|
109
|
-
mp4boxfile.onError = (e) => console.error("MP4 parsing error:", e);
|
|
110
|
-
|
|
111
|
-
mp4boxfile.onReady = (info) => {
|
|
112
|
-
const videoTrack = info.tracks.find((track) => track.type === "video");
|
|
113
|
-
if (videoTrack) {
|
|
114
|
-
videoDecoder.configure({
|
|
115
|
-
codec: videoTrack.codec,
|
|
116
|
-
width: videoTrack.video.width,
|
|
117
|
-
height: videoTrack.video.height,
|
|
118
|
-
description: this.getDescription(
|
|
119
|
-
mp4boxfile.getTrackById(videoTrack.id),
|
|
120
|
-
),
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
mp4boxfile.setExtractionOptions(videoTrack.id);
|
|
124
|
-
mp4boxfile.start();
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
// Callback to handle parsed samples (video frames)
|
|
129
|
-
mp4boxfile.onSamples = (id, user, samples) => {
|
|
130
|
-
samples.forEach((sample) => {
|
|
131
|
-
const chunk = new EncodedVideoChunk({
|
|
132
|
-
type: sample.is_sync ? "key" : "delta",
|
|
133
|
-
timestamp: sample.cts,
|
|
134
|
-
data: new Uint8Array(sample.data),
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
videoDecoder.decode(chunk);
|
|
138
|
-
});
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
mp4boxfile.appendBuffer(arrayBuffer);
|
|
142
|
-
}
|
|
143
|
-
}
|
package/src/MetaDataFetcher.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import MetaWorker from './meta_worker?worker&inline'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
timeCodeArray2TimeCodeJson,
|
|
5
|
-
frames2Timecode,
|
|
6
|
-
printTimecode,
|
|
7
|
-
} from "./utils";
|
|
8
|
-
|
|
9
|
-
export default class MetaDataFetcher {
|
|
10
|
-
constructor(options, composer) {
|
|
11
|
-
this.options = options;
|
|
12
|
-
this.composer = composer;
|
|
13
|
-
this.sourceFPS = 60000 / 1001;
|
|
14
|
-
this.folderName;
|
|
15
|
-
this.lastFrames;
|
|
16
|
-
this.metadataWorker = null;
|
|
17
|
-
this.getMetaDataFolderName();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
setMetaDataFolderName(_folderName) {
|
|
21
|
-
this.folderName = _folderName;
|
|
22
|
-
console.log(
|
|
23
|
-
"Folder name for " + this.options.gameId + ": " + this.folderName,
|
|
24
|
-
);
|
|
25
|
-
if (this.lastFrames) {
|
|
26
|
-
this.loadMetaData(this.lastFrames);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async getMetaDataFolderName() {
|
|
31
|
-
const res = await fetch(this.options.allGamesURL); //get all the games
|
|
32
|
-
const list = await res.json(); //extract the games' list
|
|
33
|
-
//if (typeof list[options.gameId] != "undefined") {//see if we found the current project
|
|
34
|
-
// setMetaDataFolderName(list[options.gameId].folder);//set the project's folder
|
|
35
|
-
//} else {
|
|
36
|
-
// setTimeout(async ()=>{
|
|
37
|
-
// await getMetaDataFolderName();//Didn't find it ? Don't give up, try again after 2 secs
|
|
38
|
-
// },2000);
|
|
39
|
-
//}
|
|
40
|
-
this.setMetaDataFolderName(this.options.gameId); //set the project's folder
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
setLastFrame(framesNum) {
|
|
44
|
-
this.lastFrames = framesNum;
|
|
45
|
-
if (this.folderName) {
|
|
46
|
-
this.loadMetaData(this.lastFrames);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
loadMetaData(lastFrames) {
|
|
51
|
-
//console.log("loadMetaData");
|
|
52
|
-
if (this.metadataWorker == null) {
|
|
53
|
-
const metadataWorker = new MetaWorker();
|
|
54
|
-
|
|
55
|
-
metadataWorker.onerror = function (error) {
|
|
56
|
-
console.error("Error from worker:", error);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
metadataWorker.addEventListener("message", (msg) => {
|
|
60
|
-
if (msg.data.time) {
|
|
61
|
-
//Debug("prof",msg.data.time);
|
|
62
|
-
} else {
|
|
63
|
-
this.composer.onMetaData(msg.data); //send to composer
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
//get the last timecode with 2-sec round-down
|
|
67
|
-
let timeCode = timeCodeArray2TimeCodeJson(
|
|
68
|
-
frames2Timecode(lastFrames, this.sourceFPS, true),
|
|
69
|
-
);
|
|
70
|
-
metadataWorker.postMessage({
|
|
71
|
-
cloudFrontURL: this.options.cloudFrontURL,
|
|
72
|
-
folderName: this.folderName,
|
|
73
|
-
tc: printTimecode(timeCode, false),
|
|
74
|
-
maskMP4: this.options.maskMP4
|
|
75
|
-
});
|
|
76
|
-
this.metadataWorker = metadataWorker;
|
|
77
|
-
} //the metadata worker is already in action, let it know the current playing data so the max-timecode is updated accordingly
|
|
78
|
-
else {
|
|
79
|
-
let timeCode = timeCodeArray2TimeCodeJson(
|
|
80
|
-
frames2Timecode(this.lastFrames, this.sourceFPS, true),
|
|
81
|
-
);
|
|
82
|
-
this.metadataWorker.postMessage({
|
|
83
|
-
tc: printTimecode(timeCode, false),
|
|
84
|
-
enabled: this.options.enabled,
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|