@revideo/2d 0.5.8-alpha.1083 → 0.5.8-beta.1082

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.
@@ -1,33 +1,45 @@
1
1
  export class ImageCommunication {
2
2
  constructor() {
3
+ this.nextFrameHandlers = [];
3
4
  if (!import.meta.hot) {
4
5
  throw new Error('FfmpegVideoFrame can only be used with HMR.');
5
6
  }
7
+ import.meta.hot.on('revideo:ffmpeg-decoder:video-frame-res', this.handler.bind(this));
8
+ }
9
+ handler(event) {
10
+ const handlers = this.nextFrameHandlers;
11
+ this.nextFrameHandlers = [];
12
+ for (const handler of handlers) {
13
+ handler(event);
14
+ }
6
15
  }
7
16
  async getFrame(id, src, time, duration, fps) {
8
- const response = await fetch('/revideo-ffmpeg-decoder/video-frame', {
9
- method: 'POST',
10
- headers: {
11
- // eslint-disable-next-line
12
- 'Content-Type': 'application/json',
13
- },
14
- body: JSON.stringify({
15
- id,
16
- filePath: src,
17
- startTime: time,
18
- duration,
19
- fps,
20
- }),
17
+ return new Promise((resolve, reject) => {
18
+ if (!import.meta.hot) {
19
+ reject('FfmpegVideoFrame can only be used with HMR.');
20
+ return;
21
+ }
22
+ function handler(event) {
23
+ const image = new Image();
24
+ const uint8Array = new Uint8Array(event.data.frame.data);
25
+ const blob = new Blob([uint8Array], { type: 'image/png' });
26
+ const url = URL.createObjectURL(blob);
27
+ image.src = url;
28
+ image.onload = () => {
29
+ resolve(image);
30
+ };
31
+ }
32
+ this.nextFrameHandlers.push(handler);
33
+ import.meta.hot.send('revideo:ffmpeg-decoder:video-frame', {
34
+ data: {
35
+ id: id,
36
+ filePath: src,
37
+ startTime: time,
38
+ duration,
39
+ fps,
40
+ },
41
+ });
21
42
  });
22
- if (!response.ok) {
23
- throw new Error(`HTTP error! status: ${response.status}`);
24
- }
25
- const width = parseInt(response.headers.get('X-Frame-Width') || '1080', 10);
26
- const height = parseInt(response.headers.get('X-Frame-Height') || '1920', 10);
27
- const arrayBuffer = await response.arrayBuffer();
28
- const imageData = new ImageData(new Uint8ClampedArray(arrayBuffer), width, height);
29
- const imageBitmap = await createImageBitmap(imageData);
30
- return imageBitmap;
31
43
  }
32
44
  }
33
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmZtcGVnLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvdXRpbHMvdmlkZW8vZmZtcGVnLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCO1FBQ0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7SUFDSCxDQUFDO0lBRU0sS0FBSyxDQUFDLFFBQVEsQ0FDbkIsRUFBVSxFQUNWLEdBQVcsRUFDWCxJQUFZLEVBQ1osUUFBZ0IsRUFDaEIsR0FBVztRQUVYLE1BQU0sUUFBUSxHQUFHLE1BQU0sS0FBSyxDQUFDLHFDQUFxQyxFQUFFO1lBQ2xFLE1BQU0sRUFBRSxNQUFNO1lBQ2QsT0FBTyxFQUFFO2dCQUNQLDJCQUEyQjtnQkFDM0IsY0FBYyxFQUFFLGtCQUFrQjthQUNuQztZQUNELElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNuQixFQUFFO2dCQUNGLFFBQVEsRUFBRSxHQUFHO2dCQUNiLFNBQVMsRUFBRSxJQUFJO2dCQUNmLFFBQVE7Z0JBQ1IsR0FBRzthQUNKLENBQUM7U0FDSCxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQzVFLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FDckIsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxNQUFNLEVBQ2hELEVBQUUsQ0FDSCxDQUFDO1FBRUYsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsV0FBVyxFQUFFLENBQUM7UUFFakQsTUFBTSxTQUFTLEdBQUcsSUFBSSxTQUFTLENBQzdCLElBQUksaUJBQWlCLENBQUMsV0FBVyxDQUFDLEVBQ2xDLEtBQUssRUFDTCxNQUFNLENBQ1AsQ0FBQztRQUVGLE1BQU0sV0FBVyxHQUFHLE1BQU0saUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDdkQsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztDQUNGIn0=
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmZtcGVnLWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9saWIvdXRpbHMvdmlkZW8vZmZtcGVnLWNsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCO1FBV1Esc0JBQWlCLEdBQXNDLEVBQUUsQ0FBQztRQVZoRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7UUFDakUsQ0FBQztRQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FDaEIsd0NBQXdDLEVBQ3hDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUN4QixDQUFDO0lBQ0osQ0FBQztJQUlPLE9BQU8sQ0FBQyxLQUFtQjtRQUNqQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFDeEMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUU1QixLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQy9CLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQztJQUVNLEtBQUssQ0FBQyxRQUFRLENBQ25CLEVBQVUsRUFDVixHQUFXLEVBQ1gsSUFBWSxFQUNaLFFBQWdCLEVBQ2hCLEdBQVc7UUFFWCxPQUFPLElBQUksT0FBTyxDQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUN2RCxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxDQUFDLDZDQUE2QyxDQUFDLENBQUM7Z0JBQ3RELE9BQU87WUFDVCxDQUFDO1lBRUQsU0FBUyxPQUFPLENBQUMsS0FBbUI7Z0JBQ2xDLE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBRTFCLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN6RCxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUMsSUFBSSxFQUFFLFdBQVcsRUFBQyxDQUFDLENBQUM7Z0JBQ3pELE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBRXRDLEtBQUssQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDO2dCQUVoQixLQUFLLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRTtvQkFDbEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUNqQixDQUFDLENBQUM7WUFDSixDQUFDO1lBRUQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUVyQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsb0NBQW9DLEVBQUU7Z0JBQ3pELElBQUksRUFBRTtvQkFDSixFQUFFLEVBQUUsRUFBRTtvQkFDTixRQUFRLEVBQUUsR0FBRztvQkFDYixTQUFTLEVBQUUsSUFBSTtvQkFDZixRQUFRO29CQUNSLEdBQUc7aUJBQ0o7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRiJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revideo/2d",
3
- "version": "0.5.8-alpha.1083+9fe3f4c0",
3
+ "version": "0.5.8-beta.1082+5514e32d",
4
4
  "description": "A 2D renderer for revideo",
5
5
  "author": "revideo",
6
6
  "homepage": "https://re.video/",
@@ -30,7 +30,7 @@
30
30
  "devDependencies": {
31
31
  "@preact/signals": "^1.2.1",
32
32
  "@revideo/internal": "^0.0.0",
33
- "@revideo/ui": "^0.5.8-alpha.1083+9fe3f4c0",
33
+ "@revideo/ui": "^0.5.8-beta.1082+5514e32d",
34
34
  "clsx": "^2.0.0",
35
35
  "jsdom": "^22.1.0",
36
36
  "preact": "^10.19.2",
@@ -40,7 +40,7 @@
40
40
  "@codemirror/language": "^6.10.1",
41
41
  "@lezer/common": "^1.2.1",
42
42
  "@lezer/highlight": "^1.2.0",
43
- "@revideo/core": "^0.5.8-alpha.1083+9fe3f4c0",
43
+ "@revideo/core": "^0.5.8-beta.1082+5514e32d",
44
44
  "@rive-app/canvas-advanced": "2.7.3",
45
45
  "code-fns": "^0.8.2",
46
46
  "hls.js": "^1.5.11",
@@ -48,5 +48,5 @@
48
48
  "mp4box": "^0.5.2",
49
49
  "parse-svg-path": "^0.1.2"
50
50
  },
51
- "gitHead": "9fe3f4c0157a41487144398d997636205ce6ce1d"
51
+ "gitHead": "5514e32d74656cbbc12f121b48d4d3078850d817"
52
52
  }
@@ -95,10 +95,6 @@ export abstract class Media extends Asset {
95
95
  return this.volume;
96
96
  }
97
97
 
98
- public getUrl(): string {
99
- return this.mediaElement().src;
100
- }
101
-
102
98
  public override dispose() {
103
99
  this.pause();
104
100
  this.remove();
@@ -197,7 +197,7 @@ export class Video extends Media {
197
197
  return video;
198
198
  }
199
199
 
200
- protected lastFrame: ImageBitmap | null = null;
200
+ protected lastFrame: HTMLImageElement | null = null;
201
201
 
202
202
  protected async webcodecSeekedVideo(): Promise<CanvasImageSource> {
203
203
  const video = this.video();
@@ -213,7 +213,7 @@ export class Video extends Media {
213
213
  return getFrame(this.key, video.src, time, fps);
214
214
  }
215
215
 
216
- protected async ffmpegSeekedVideo(): Promise<ImageBitmap> {
216
+ protected async ffmpegSeekedVideo(): Promise<HTMLImageElement> {
217
217
  const video = this.video();
218
218
  const time = this.clampTime(this.time());
219
219
  const duration = this.getDuration();
@@ -170,8 +170,7 @@ export class Scene2D extends GeneratorScene<View2D> implements Inspectable {
170
170
  ...playingVideos.map(vid => ({
171
171
  key: vid.key,
172
172
  type: 'video' as const,
173
- src: vid.getUrl(),
174
- decoder: vid.decoder(),
173
+ src: vid.fullSource(),
175
174
  playbackRate:
176
175
  typeof vid.playbackRate === 'function'
177
176
  ? vid.playbackRate()
@@ -3,6 +3,22 @@ export class ImageCommunication {
3
3
  if (!import.meta.hot) {
4
4
  throw new Error('FfmpegVideoFrame can only be used with HMR.');
5
5
  }
6
+
7
+ import.meta.hot.on(
8
+ 'revideo:ffmpeg-decoder:video-frame-res',
9
+ this.handler.bind(this),
10
+ );
11
+ }
12
+
13
+ private nextFrameHandlers: ((event: MessageEvent) => void)[] = [];
14
+
15
+ private handler(event: MessageEvent) {
16
+ const handlers = this.nextFrameHandlers;
17
+ this.nextFrameHandlers = [];
18
+
19
+ for (const handler of handlers) {
20
+ handler(event);
21
+ }
6
22
  }
7
23
 
8
24
  public async getFrame(
@@ -12,40 +28,37 @@ export class ImageCommunication {
12
28
  duration: number,
13
29
  fps: number,
14
30
  ) {
15
- const response = await fetch('/revideo-ffmpeg-decoder/video-frame', {
16
- method: 'POST',
17
- headers: {
18
- // eslint-disable-next-line
19
- 'Content-Type': 'application/json',
20
- },
21
- body: JSON.stringify({
22
- id,
23
- filePath: src,
24
- startTime: time,
25
- duration,
26
- fps,
27
- }),
28
- });
31
+ return new Promise<HTMLImageElement>((resolve, reject) => {
32
+ if (!import.meta.hot) {
33
+ reject('FfmpegVideoFrame can only be used with HMR.');
34
+ return;
35
+ }
29
36
 
30
- if (!response.ok) {
31
- throw new Error(`HTTP error! status: ${response.status}`);
32
- }
37
+ function handler(event: MessageEvent) {
38
+ const image = new Image();
33
39
 
34
- const width = parseInt(response.headers.get('X-Frame-Width') || '1080', 10);
35
- const height = parseInt(
36
- response.headers.get('X-Frame-Height') || '1920',
37
- 10,
38
- );
40
+ const uint8Array = new Uint8Array(event.data.frame.data);
41
+ const blob = new Blob([uint8Array], {type: 'image/png'});
42
+ const url = URL.createObjectURL(blob);
39
43
 
40
- const arrayBuffer = await response.arrayBuffer();
44
+ image.src = url;
41
45
 
42
- const imageData = new ImageData(
43
- new Uint8ClampedArray(arrayBuffer),
44
- width,
45
- height,
46
- );
46
+ image.onload = () => {
47
+ resolve(image);
48
+ };
49
+ }
50
+
51
+ this.nextFrameHandlers.push(handler);
47
52
 
48
- const imageBitmap = await createImageBitmap(imageData);
49
- return imageBitmap;
53
+ import.meta.hot.send('revideo:ffmpeg-decoder:video-frame', {
54
+ data: {
55
+ id: id,
56
+ filePath: src,
57
+ startTime: time,
58
+ duration,
59
+ fps,
60
+ },
61
+ });
62
+ });
50
63
  }
51
64
  }