@revideo/2d 0.4.8-alpha.1031 → 0.4.8
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/editor/editor/tsconfig.build.tsbuildinfo +1 -1
- package/lib/components/Asset.d.ts +24 -0
- package/lib/components/Asset.d.ts.map +1 -0
- package/lib/components/Asset.js +40 -0
- package/lib/components/Img.d.ts +3 -18
- package/lib/components/Img.d.ts.map +1 -1
- package/lib/components/Img.js +4 -7
- package/lib/components/Media.d.ts +3 -5
- package/lib/components/Media.d.ts.map +1 -1
- package/lib/components/Media.js +4 -23
- package/lib/components/Video.js +3 -3
- package/lib/components/View2D.js +2 -2
- package/lib/tsconfig.build.tsbuildinfo +1 -1
- package/lib/utils/video/parser/parser.js +2 -2
- package/lib/utils/video/parser/segment.d.ts +1 -1
- package/lib/utils/video/parser/segment.d.ts.map +1 -1
- package/lib/utils/video/parser/segment.js +40 -6
- package/package.json +5 -5
- package/src/lib/components/Asset.ts +51 -0
- package/src/lib/components/Img.ts +4 -21
- package/src/lib/components/Media.ts +3 -29
- package/src/lib/components/Video.ts +2 -2
- package/src/lib/components/View2D.ts +1 -1
- package/src/lib/utils/video/parser/parser.ts +1 -1
- package/src/lib/utils/video/parser/segment.ts +46 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segment.d.ts","sourceRoot":"","sources":["../../../../src/lib/utils/video/parser/segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAE7B,qBAAa,OAAO;IAClB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,IAAI,CAAO;IAEnB,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,OAAO,CAAe;IAE9B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,WAAW,CAAoB;IAEvC,OAAO,CAAC,QAAQ,CAAuC;gBAGrD,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,IAAI,EAAE,EACb,cAAc,EAAE,MAAM,EACtB,SAAS,GAAE,MAAU;IAsBV,KAAK,CAAC,aAAa,EAAE,kBAAkB;
|
|
1
|
+
{"version":3,"file":"segment.d.ts","sourceRoot":"","sources":["../../../../src/lib/utils/video/parser/segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAC;AAE7B,qBAAa,OAAO;IAClB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,GAAG,CAAS;IAEpB,OAAO,CAAC,IAAI,CAAM;IAClB,OAAO,CAAC,IAAI,CAAO;IAEnB,OAAO,CAAC,gBAAgB,CAAkB;IAC1C,OAAO,CAAC,OAAO,CAAe;IAE9B,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,WAAW,CAAoB;IAEvC,OAAO,CAAC,QAAQ,CAAuC;gBAGrD,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,IAAI,EAAE,EACb,cAAc,EAAE,MAAM,EACtB,SAAS,GAAE,MAAU;IAsBV,KAAK,CAAC,aAAa,EAAE,kBAAkB;IAoDpD;;;;;;OAMG;YACW,sBAAsB;IAgCpC;;;OAGG;IACH,OAAO,CAAC,SAAS;IAiBjB;;;OAGG;YACW,OAAO;YA4BP,cAAc;IA2Bf,YAAY;IASzB;;OAEG;IACU,KAAK;IAaX,kBAAkB;IAIlB,YAAY;CAGpB"}
|
|
@@ -24,6 +24,32 @@ export class Segment {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
async start(decoderConfig) {
|
|
27
|
+
// If this is an empty edit, we just need to fill the buffer with empty frames.
|
|
28
|
+
if (this.edit.mediaTime === -1) {
|
|
29
|
+
this.done = true;
|
|
30
|
+
this.responseFinished = true;
|
|
31
|
+
this.decoder.close();
|
|
32
|
+
const segmentDurationInSeconds = this.edit.segmentDuration /
|
|
33
|
+
this.file.getInfo().videoTracks[0].movie_timescale;
|
|
34
|
+
const framesToFill = segmentDurationInSeconds * this.edit.fps;
|
|
35
|
+
const height = this.file.getInfo().videoTracks[0].track_height;
|
|
36
|
+
const width = this.file.getInfo().videoTracks[0].track_width;
|
|
37
|
+
const bufferSize = height * width * 4;
|
|
38
|
+
const buffer = new ArrayBuffer(bufferSize);
|
|
39
|
+
const uint8Array = new Uint8Array(buffer);
|
|
40
|
+
// Make the frame black
|
|
41
|
+
uint8Array.fill(0);
|
|
42
|
+
this.frameBuffer = Array.from({ length: framesToFill }, () => {
|
|
43
|
+
return new VideoFrame(uint8Array, {
|
|
44
|
+
timestamp: 0,
|
|
45
|
+
duration: 1 / this.edit.fps,
|
|
46
|
+
codedHeight: height,
|
|
47
|
+
codedWidth: width,
|
|
48
|
+
format: 'BGRA',
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
27
53
|
this.decoder.configure(decoderConfig);
|
|
28
54
|
const videoTrack = this.file.getInfo().videoTracks[0];
|
|
29
55
|
const trak = this.file.getTrackById(videoTrack.id);
|
|
@@ -60,8 +86,8 @@ export class Segment {
|
|
|
60
86
|
if (done) {
|
|
61
87
|
this.responseFinished = true;
|
|
62
88
|
this.abortController.abort();
|
|
63
|
-
this.decoder.flush();
|
|
64
89
|
sink.close();
|
|
90
|
+
this.decoder.flush();
|
|
65
91
|
return;
|
|
66
92
|
}
|
|
67
93
|
sink.write(value);
|
|
@@ -92,7 +118,7 @@ export class Segment {
|
|
|
92
118
|
* Called when the decoder has a frame ready.
|
|
93
119
|
* Pushes the frame to the buffer so it can be consumed.
|
|
94
120
|
*/
|
|
95
|
-
onFrame(frame) {
|
|
121
|
+
async onFrame(frame) {
|
|
96
122
|
this.framesDue--;
|
|
97
123
|
// If the frame comes before the seek time, close it.
|
|
98
124
|
const mediaTimeInSec = this.edit.mediaTime / this.file.getInfo().videoTracks[0].timescale;
|
|
@@ -109,7 +135,7 @@ export class Segment {
|
|
|
109
135
|
if (frameTimeInSec > segmentEndTime) {
|
|
110
136
|
frame.close();
|
|
111
137
|
this.done = true;
|
|
112
|
-
this.decoder.flush();
|
|
138
|
+
await this.decoder.flush();
|
|
113
139
|
return;
|
|
114
140
|
}
|
|
115
141
|
this.frameBuffer.push(frame);
|
|
@@ -146,10 +172,18 @@ export class Segment {
|
|
|
146
172
|
/**
|
|
147
173
|
* Called when we are done with the extractor.
|
|
148
174
|
*/
|
|
149
|
-
close() {
|
|
175
|
+
async close() {
|
|
150
176
|
this.abortController.abort();
|
|
151
177
|
this.frameBuffer.forEach(frame => frame.close());
|
|
152
|
-
|
|
178
|
+
try {
|
|
179
|
+
if (this.decoder.state === 'configured') {
|
|
180
|
+
await this.decoder.flush();
|
|
181
|
+
this.decoder.close();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
// Ignore
|
|
186
|
+
}
|
|
153
187
|
}
|
|
154
188
|
getFramesProcessed() {
|
|
155
189
|
return this.framesProcessed;
|
|
@@ -158,4 +192,4 @@ export class Segment {
|
|
|
158
192
|
return this.startTime;
|
|
159
193
|
}
|
|
160
194
|
}
|
|
161
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
195
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VnbWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvdXRpbHMvdmlkZW8vcGFyc2VyL3NlZ21lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLFFBQVEsQ0FBQztBQUduQyxNQUFNLE9BQU8sT0FBTztJQWtCbEIsWUFDRSxHQUFXLEVBQ1gsSUFBUyxFQUNULEtBQWEsRUFDYixjQUFzQixFQUN0QixZQUFvQixDQUFDO1FBdEJmLFNBQUksR0FBWSxLQUFLLENBQUM7UUFDdEIsb0JBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1FBTXhDLHFCQUFnQixHQUFZLEtBQUssQ0FBQztRQUdsQyxvQkFBZSxHQUFHLENBQUMsQ0FBQztRQUVwQixjQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsZ0JBQVcsR0FBaUIsRUFBRSxDQUFDO1FBRS9CLGFBQVEsR0FBd0IsS0FBSyxJQUFJLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFTckQsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFFZixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztRQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUVsQyxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUUzQixrR0FBa0c7UUFDbEcsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDakUsSUFBSSxDQUFDLGVBQWUsSUFBSSxhQUFhLENBQUM7UUFFdEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLFlBQVks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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revideo/2d",
|
|
3
|
-
"version": "0.4.8
|
|
3
|
+
"version": "0.4.8",
|
|
4
4
|
"description": "A 2D renderer for revideo",
|
|
5
5
|
"author": "revideo",
|
|
6
6
|
"homepage": "https://re.video/",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@preact/signals": "^1.2.1",
|
|
32
|
-
"@revideo/internal": "
|
|
33
|
-
"@revideo/ui": "
|
|
32
|
+
"@revideo/internal": "0.0.0",
|
|
33
|
+
"@revideo/ui": "0.4.8",
|
|
34
34
|
"clsx": "^2.0.0",
|
|
35
35
|
"jsdom": "^22.1.0",
|
|
36
36
|
"preact": "^10.19.2",
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
"@codemirror/language": "^6.10.1",
|
|
41
41
|
"@lezer/common": "^1.2.1",
|
|
42
42
|
"@lezer/highlight": "^1.2.0",
|
|
43
|
-
"@revideo/core": "
|
|
43
|
+
"@revideo/core": "0.4.8",
|
|
44
44
|
"code-fns": "^0.8.2",
|
|
45
45
|
"hls.js": "^1.5.11",
|
|
46
46
|
"mathjax-full": "^3.2.2",
|
|
47
47
|
"mp4box": "^0.5.2",
|
|
48
48
|
"parse-svg-path": "^0.1.2"
|
|
49
49
|
},
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "a00c4e08ea9560e4f4e3a3c9e76c8997f4d5a78d"
|
|
51
51
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {SimpleSignal, useAssetBase} from '@revideo/core';
|
|
2
|
+
import {nodeName, signal} from '../decorators';
|
|
3
|
+
import {Rect} from './Rect';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A component that has a source. Used as a base class for `Media` and `Img` components.
|
|
7
|
+
*/
|
|
8
|
+
@nodeName('Asset')
|
|
9
|
+
export abstract class Asset extends Rect {
|
|
10
|
+
/**
|
|
11
|
+
* The source of this asset.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* Using a local path, with the resource inside the /public folder:
|
|
15
|
+
* ```tsx
|
|
16
|
+
* view.add(<Img src={'/image.png} />)
|
|
17
|
+
* ```
|
|
18
|
+
* Loading a resource from the internet:
|
|
19
|
+
* ```tsx
|
|
20
|
+
* view.add(<Img src="https://example.com/image.png" />)
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
@signal()
|
|
24
|
+
public declare readonly src: SimpleSignal<string, this>;
|
|
25
|
+
|
|
26
|
+
public assetRoot?: `${string}/`;
|
|
27
|
+
|
|
28
|
+
public fullSource(): string {
|
|
29
|
+
console.log(`Calling fullSource for ${this.src()}`);
|
|
30
|
+
|
|
31
|
+
if (!this.assetRoot) {
|
|
32
|
+
console.log('Setting assetRoot', useAssetBase());
|
|
33
|
+
this.assetRoot = useAssetBase();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let src = this.src();
|
|
37
|
+
const isUrl = src.startsWith('http://') || src.startsWith('https://');
|
|
38
|
+
|
|
39
|
+
if (isUrl) {
|
|
40
|
+
return src;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// We remove the trailing slash from the assetRoot
|
|
44
|
+
// and make sure there is a leading slash in the src
|
|
45
|
+
if (src[0] !== '/') {
|
|
46
|
+
src = '/' + src;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return this.assetRoot.slice(0, -1) + src;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
15
15
|
import {DesiredLength} from '../partials';
|
|
16
16
|
import {drawImage} from '../utils';
|
|
17
|
-
import {
|
|
17
|
+
import {Asset} from './Asset';
|
|
18
|
+
import {RectProps} from './Rect';
|
|
18
19
|
import imageWithoutSource from './__logs__/image-without-source.md';
|
|
19
20
|
|
|
20
21
|
export interface ImgProps extends RectProps {
|
|
@@ -66,7 +67,7 @@ export interface ImgProps extends RectProps {
|
|
|
66
67
|
* ```
|
|
67
68
|
*/
|
|
68
69
|
@nodeName('Img')
|
|
69
|
-
export class Img extends
|
|
70
|
+
export class Img extends Asset {
|
|
70
71
|
private static pool: Record<string, HTMLImageElement> = {};
|
|
71
72
|
|
|
72
73
|
static {
|
|
@@ -81,24 +82,6 @@ export class Img extends Rect {
|
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
/**
|
|
85
|
-
* The source of this image.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* Using a local image:
|
|
89
|
-
* ```tsx
|
|
90
|
-
* import image from './example.png';
|
|
91
|
-
* // ...
|
|
92
|
-
* view.add(<Img src={image} />)
|
|
93
|
-
* ```
|
|
94
|
-
* Loading an image from the internet:
|
|
95
|
-
* ```tsx
|
|
96
|
-
* view.add(<Img src="https://example.com/image.png" />)
|
|
97
|
-
* ```
|
|
98
|
-
*/
|
|
99
|
-
@signal()
|
|
100
|
-
public declare readonly src: SimpleSignal<string, this>;
|
|
101
|
-
|
|
102
85
|
/**
|
|
103
86
|
* The alpha value of this image.
|
|
104
87
|
*
|
|
@@ -149,7 +132,7 @@ export class Img extends Rect {
|
|
|
149
132
|
|
|
150
133
|
@computed()
|
|
151
134
|
protected image(): HTMLImageElement {
|
|
152
|
-
const rawSrc = this.
|
|
135
|
+
const rawSrc = this.fullSource();
|
|
153
136
|
let src = '';
|
|
154
137
|
let key = '';
|
|
155
138
|
if (rawSrc) {
|
|
@@ -5,11 +5,11 @@ import {
|
|
|
5
5
|
clamp,
|
|
6
6
|
isReactive,
|
|
7
7
|
useLogger,
|
|
8
|
-
useScene,
|
|
9
8
|
useThread,
|
|
10
9
|
} from '@revideo/core';
|
|
11
10
|
import {computed, initial, nodeName, signal} from '../decorators';
|
|
12
|
-
import {
|
|
11
|
+
import {Asset} from './Asset';
|
|
12
|
+
import {RectProps} from './Rect';
|
|
13
13
|
import reactivePlaybackRate from './__logs__/reactive-playback-rate.md';
|
|
14
14
|
|
|
15
15
|
export interface MediaProps extends RectProps {
|
|
@@ -22,10 +22,7 @@ export interface MediaProps extends RectProps {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
@nodeName('Media')
|
|
25
|
-
export abstract class Media extends
|
|
26
|
-
@signal()
|
|
27
|
-
public declare readonly src: SimpleSignal<string, this>;
|
|
28
|
-
|
|
25
|
+
export abstract class Media extends Asset {
|
|
29
26
|
@initial(false)
|
|
30
27
|
@signal()
|
|
31
28
|
public declare readonly loop: SimpleSignal<boolean, this>;
|
|
@@ -55,29 +52,6 @@ export abstract class Media extends Rect {
|
|
|
55
52
|
}
|
|
56
53
|
}
|
|
57
54
|
|
|
58
|
-
public assetRoot?: `${string}/`;
|
|
59
|
-
|
|
60
|
-
public fullSource(): string {
|
|
61
|
-
if (!this.assetRoot) {
|
|
62
|
-
this.assetRoot = useScene().assetRoot;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
let src = this.src();
|
|
66
|
-
const isUrl = src.startsWith('http://') || src.startsWith('https://');
|
|
67
|
-
|
|
68
|
-
if (isUrl) {
|
|
69
|
-
return src;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// We remove the trailing slash from the assetRoot
|
|
73
|
-
// and make sure there is a leading slash in the src
|
|
74
|
-
if (src[0] !== '/') {
|
|
75
|
-
src = '/' + src;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return this.assetRoot.slice(0, -1) + src;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
55
|
public isPlaying(): boolean {
|
|
82
56
|
return this.playing();
|
|
83
57
|
}
|
|
@@ -342,8 +342,8 @@ export class Video extends Media {
|
|
|
342
342
|
if (this.fullSource().split('?')[0].endsWith('.mov')) return 'mov';
|
|
343
343
|
|
|
344
344
|
if (
|
|
345
|
-
this.fullSource().startsWith('http
|
|
346
|
-
this.fullSource().startsWith('https
|
|
345
|
+
this.fullSource().startsWith('http://') ||
|
|
346
|
+
this.fullSource().startsWith('https://')
|
|
347
347
|
) {
|
|
348
348
|
try {
|
|
349
349
|
const response = await fetch(this.fullSource(), {method: 'HEAD'});
|
|
@@ -21,7 +21,7 @@ export class View2D extends Rect {
|
|
|
21
21
|
frame.style.pointerEvents = 'none';
|
|
22
22
|
frame.style.top = '0';
|
|
23
23
|
frame.style.left = '0';
|
|
24
|
-
frame.style.fontFeatureSettings = 'normal';
|
|
24
|
+
frame.style.fontFeatureSettings = 'normal'; // TODO: find solution that fully isolates CSS
|
|
25
25
|
frame.style.opacity = '0';
|
|
26
26
|
frame.style.overflow = 'hidden';
|
|
27
27
|
document.body.prepend(frame);
|
|
@@ -194,7 +194,7 @@ export class Mp4Parser {
|
|
|
194
194
|
frame = this.sampler.getLastFrame();
|
|
195
195
|
|
|
196
196
|
// We can close the segment
|
|
197
|
-
this.sampler.getSegment().close();
|
|
197
|
+
await this.sampler.getSegment().close();
|
|
198
198
|
|
|
199
199
|
// If we still don't have a frame, throw an error
|
|
200
200
|
if (!frame) {
|
|
@@ -47,6 +47,40 @@ export class Segment {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
public async start(decoderConfig: VideoDecoderConfig) {
|
|
50
|
+
// If this is an empty edit, we just need to fill the buffer with empty frames.
|
|
51
|
+
if (this.edit.mediaTime === -1) {
|
|
52
|
+
this.done = true;
|
|
53
|
+
this.responseFinished = true;
|
|
54
|
+
this.decoder.close();
|
|
55
|
+
|
|
56
|
+
const segmentDurationInSeconds =
|
|
57
|
+
this.edit.segmentDuration /
|
|
58
|
+
this.file.getInfo().videoTracks[0].movie_timescale;
|
|
59
|
+
const framesToFill = segmentDurationInSeconds * this.edit.fps;
|
|
60
|
+
|
|
61
|
+
const height = this.file.getInfo().videoTracks[0].track_height;
|
|
62
|
+
const width = this.file.getInfo().videoTracks[0].track_width;
|
|
63
|
+
|
|
64
|
+
const bufferSize = height * width * 4;
|
|
65
|
+
const buffer = new ArrayBuffer(bufferSize);
|
|
66
|
+
const uint8Array = new Uint8Array(buffer);
|
|
67
|
+
|
|
68
|
+
// Make the frame black
|
|
69
|
+
uint8Array.fill(0);
|
|
70
|
+
|
|
71
|
+
this.frameBuffer = Array.from({length: framesToFill}, () => {
|
|
72
|
+
return new VideoFrame(uint8Array, {
|
|
73
|
+
timestamp: 0,
|
|
74
|
+
duration: 1 / this.edit.fps,
|
|
75
|
+
codedHeight: height,
|
|
76
|
+
codedWidth: width,
|
|
77
|
+
format: 'BGRA',
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
50
84
|
this.decoder.configure(decoderConfig);
|
|
51
85
|
const videoTrack = this.file.getInfo().videoTracks[0];
|
|
52
86
|
const trak = this.file.getTrackById(videoTrack.id);
|
|
@@ -92,8 +126,8 @@ export class Segment {
|
|
|
92
126
|
if (done) {
|
|
93
127
|
this.responseFinished = true;
|
|
94
128
|
this.abortController.abort();
|
|
95
|
-
this.decoder.flush();
|
|
96
129
|
sink.close();
|
|
130
|
+
this.decoder.flush();
|
|
97
131
|
return;
|
|
98
132
|
}
|
|
99
133
|
|
|
@@ -128,7 +162,7 @@ export class Segment {
|
|
|
128
162
|
* Called when the decoder has a frame ready.
|
|
129
163
|
* Pushes the frame to the buffer so it can be consumed.
|
|
130
164
|
*/
|
|
131
|
-
private onFrame(frame: VideoFrame) {
|
|
165
|
+
private async onFrame(frame: VideoFrame) {
|
|
132
166
|
this.framesDue--;
|
|
133
167
|
|
|
134
168
|
// If the frame comes before the seek time, close it.
|
|
@@ -149,7 +183,7 @@ export class Segment {
|
|
|
149
183
|
if (frameTimeInSec > segmentEndTime) {
|
|
150
184
|
frame.close();
|
|
151
185
|
this.done = true;
|
|
152
|
-
this.decoder.flush();
|
|
186
|
+
await this.decoder.flush();
|
|
153
187
|
return;
|
|
154
188
|
}
|
|
155
189
|
|
|
@@ -195,10 +229,17 @@ export class Segment {
|
|
|
195
229
|
/**
|
|
196
230
|
* Called when we are done with the extractor.
|
|
197
231
|
*/
|
|
198
|
-
public close() {
|
|
232
|
+
public async close() {
|
|
199
233
|
this.abortController.abort();
|
|
200
234
|
this.frameBuffer.forEach(frame => frame.close());
|
|
201
|
-
|
|
235
|
+
try {
|
|
236
|
+
if (this.decoder.state === 'configured') {
|
|
237
|
+
await this.decoder.flush();
|
|
238
|
+
this.decoder.close();
|
|
239
|
+
}
|
|
240
|
+
} catch (e) {
|
|
241
|
+
// Ignore
|
|
242
|
+
}
|
|
202
243
|
}
|
|
203
244
|
|
|
204
245
|
public getFramesProcessed() {
|