@remotion/media 4.0.394 → 4.0.395
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/esm/index.mjs
CHANGED
|
@@ -3387,8 +3387,26 @@ var extractFrameAndAudio = async ({
|
|
|
3387
3387
|
}
|
|
3388
3388
|
};
|
|
3389
3389
|
|
|
3390
|
-
// src/video-extraction/
|
|
3391
|
-
|
|
3390
|
+
// src/video-extraction/add-broadcast-channel-listener.ts
|
|
3391
|
+
var emitReadiness = (channel) => {
|
|
3392
|
+
channel.postMessage({
|
|
3393
|
+
type: "main-tab-ready"
|
|
3394
|
+
});
|
|
3395
|
+
let times = 0;
|
|
3396
|
+
const interval = setInterval(() => {
|
|
3397
|
+
channel.postMessage({
|
|
3398
|
+
type: "main-tab-ready"
|
|
3399
|
+
});
|
|
3400
|
+
times++;
|
|
3401
|
+
if (times > 30) {
|
|
3402
|
+
clearInterval(interval);
|
|
3403
|
+
}
|
|
3404
|
+
}, 300);
|
|
3405
|
+
};
|
|
3406
|
+
var addBroadcastChannelListener = () => {
|
|
3407
|
+
if (!(typeof window !== "undefined" && window.remotion_broadcastChannel && window.remotion_isMainTab)) {
|
|
3408
|
+
return;
|
|
3409
|
+
}
|
|
3392
3410
|
window.remotion_broadcastChannel.addEventListener("message", async (event) => {
|
|
3393
3411
|
const data = event.data;
|
|
3394
3412
|
if (data.type === "request") {
|
|
@@ -3467,8 +3485,29 @@ if (typeof window !== "undefined" && window.remotion_broadcastChannel && window.
|
|
|
3467
3485
|
throw new Error("Invalid message: " + JSON.stringify(data));
|
|
3468
3486
|
}
|
|
3469
3487
|
});
|
|
3470
|
-
|
|
3471
|
-
|
|
3488
|
+
emitReadiness(window.remotion_broadcastChannel);
|
|
3489
|
+
};
|
|
3490
|
+
var mainTabIsReadyProm = null;
|
|
3491
|
+
var waitForMainTabToBeReady = (channel) => {
|
|
3492
|
+
if (mainTabIsReadyProm) {
|
|
3493
|
+
return mainTabIsReadyProm;
|
|
3494
|
+
}
|
|
3495
|
+
mainTabIsReadyProm = new Promise((resolve) => {
|
|
3496
|
+
const onMessage = (event) => {
|
|
3497
|
+
const data = event.data;
|
|
3498
|
+
if (data.type === "main-tab-ready") {
|
|
3499
|
+
resolve();
|
|
3500
|
+
channel.removeEventListener("message", onMessage);
|
|
3501
|
+
}
|
|
3502
|
+
};
|
|
3503
|
+
channel.addEventListener("message", onMessage);
|
|
3504
|
+
});
|
|
3505
|
+
return mainTabIsReadyProm;
|
|
3506
|
+
};
|
|
3507
|
+
|
|
3508
|
+
// src/video-extraction/extract-frame-via-broadcast-channel.ts
|
|
3509
|
+
addBroadcastChannelListener();
|
|
3510
|
+
var extractFrameViaBroadcastChannel = async ({
|
|
3472
3511
|
src,
|
|
3473
3512
|
timeInSeconds,
|
|
3474
3513
|
logLevel,
|
|
@@ -3501,6 +3540,7 @@ var extractFrameViaBroadcastChannel = ({
|
|
|
3501
3540
|
maxCacheSize
|
|
3502
3541
|
});
|
|
3503
3542
|
}
|
|
3543
|
+
await waitForMainTabToBeReady(window.remotion_broadcastChannel);
|
|
3504
3544
|
const requestId = crypto.randomUUID();
|
|
3505
3545
|
const resolvePromise = new Promise((resolve, reject) => {
|
|
3506
3546
|
const onMessage = (event) => {
|
|
@@ -3508,6 +3548,9 @@ var extractFrameViaBroadcastChannel = ({
|
|
|
3508
3548
|
if (!data) {
|
|
3509
3549
|
return;
|
|
3510
3550
|
}
|
|
3551
|
+
if (data.type === "main-tab-ready") {
|
|
3552
|
+
return;
|
|
3553
|
+
}
|
|
3511
3554
|
if (data.id !== requestId) {
|
|
3512
3555
|
return;
|
|
3513
3556
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { LogLevel } from 'remotion';
|
|
2
|
+
import type { PcmS16AudioData } from '../convert-audiodata/convert-audiodata';
|
|
3
|
+
export type MessageFromMainTab = {
|
|
4
|
+
type: 'response-success';
|
|
5
|
+
id: string;
|
|
6
|
+
frame: ImageBitmap | null;
|
|
7
|
+
audio: PcmS16AudioData | null;
|
|
8
|
+
durationInSeconds: number | null;
|
|
9
|
+
} | {
|
|
10
|
+
type: 'response-error';
|
|
11
|
+
id: string;
|
|
12
|
+
errorStack: string;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'response-cannot-decode';
|
|
15
|
+
id: string;
|
|
16
|
+
durationInSeconds: number | null;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'response-cannot-decode-alpha';
|
|
19
|
+
id: string;
|
|
20
|
+
durationInSeconds: number | null;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'response-network-error';
|
|
23
|
+
id: string;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'response-unknown-container-format';
|
|
26
|
+
id: string;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'main-tab-ready';
|
|
29
|
+
};
|
|
30
|
+
export type ExtractFrameRequest = {
|
|
31
|
+
type: 'request';
|
|
32
|
+
src: string;
|
|
33
|
+
timeInSeconds: number;
|
|
34
|
+
durationInSeconds: number;
|
|
35
|
+
playbackRate: number;
|
|
36
|
+
id: string;
|
|
37
|
+
logLevel: LogLevel;
|
|
38
|
+
includeAudio: boolean;
|
|
39
|
+
includeVideo: boolean;
|
|
40
|
+
loop: boolean;
|
|
41
|
+
audioStreamIndex: number;
|
|
42
|
+
trimAfter: number | undefined;
|
|
43
|
+
trimBefore: number | undefined;
|
|
44
|
+
fps: number;
|
|
45
|
+
maxCacheSize: number;
|
|
46
|
+
};
|
|
47
|
+
export declare const addBroadcastChannelListener: () => void;
|
|
48
|
+
export declare const waitForMainTabToBeReady: (channel: BroadcastChannel) => Promise<void>;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { extractFrameAndAudio } from '../extract-frame-and-audio';
|
|
2
|
+
// Send to other channels a message to let them know that the
|
|
3
|
+
// tab was loaded and is ready to receive requests.
|
|
4
|
+
// Emit "readiness" messages for approximately 10 seconds.
|
|
5
|
+
const emitReadiness = (channel) => {
|
|
6
|
+
channel.postMessage({
|
|
7
|
+
type: 'main-tab-ready',
|
|
8
|
+
});
|
|
9
|
+
let times = 0;
|
|
10
|
+
const interval = setInterval(() => {
|
|
11
|
+
channel.postMessage({
|
|
12
|
+
type: 'main-tab-ready',
|
|
13
|
+
});
|
|
14
|
+
times++;
|
|
15
|
+
if (times > 30) {
|
|
16
|
+
clearInterval(interval);
|
|
17
|
+
}
|
|
18
|
+
}, 300);
|
|
19
|
+
};
|
|
20
|
+
export const addBroadcastChannelListener = () => {
|
|
21
|
+
// Doesn't exist in studio
|
|
22
|
+
if (!(typeof window !== 'undefined' &&
|
|
23
|
+
window.remotion_broadcastChannel &&
|
|
24
|
+
window.remotion_isMainTab)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
window.remotion_broadcastChannel.addEventListener('message', async (event) => {
|
|
28
|
+
const data = event.data;
|
|
29
|
+
if (data.type === 'request') {
|
|
30
|
+
try {
|
|
31
|
+
const result = await extractFrameAndAudio({
|
|
32
|
+
src: data.src,
|
|
33
|
+
timeInSeconds: data.timeInSeconds,
|
|
34
|
+
logLevel: data.logLevel,
|
|
35
|
+
durationInSeconds: data.durationInSeconds,
|
|
36
|
+
playbackRate: data.playbackRate,
|
|
37
|
+
includeAudio: data.includeAudio,
|
|
38
|
+
includeVideo: data.includeVideo,
|
|
39
|
+
loop: data.loop,
|
|
40
|
+
audioStreamIndex: data.audioStreamIndex,
|
|
41
|
+
trimAfter: data.trimAfter,
|
|
42
|
+
trimBefore: data.trimBefore,
|
|
43
|
+
fps: data.fps,
|
|
44
|
+
maxCacheSize: data.maxCacheSize,
|
|
45
|
+
});
|
|
46
|
+
if (result.type === 'cannot-decode') {
|
|
47
|
+
const cannotDecodeResponse = {
|
|
48
|
+
type: 'response-cannot-decode',
|
|
49
|
+
id: data.id,
|
|
50
|
+
durationInSeconds: result.durationInSeconds,
|
|
51
|
+
};
|
|
52
|
+
window.remotion_broadcastChannel.postMessage(cannotDecodeResponse);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (result.type === 'cannot-decode-alpha') {
|
|
56
|
+
const cannotDecodeAlphaResponse = {
|
|
57
|
+
type: 'response-cannot-decode-alpha',
|
|
58
|
+
id: data.id,
|
|
59
|
+
durationInSeconds: result.durationInSeconds,
|
|
60
|
+
};
|
|
61
|
+
window.remotion_broadcastChannel.postMessage(cannotDecodeAlphaResponse);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (result.type === 'network-error') {
|
|
65
|
+
const networkErrorResponse = {
|
|
66
|
+
type: 'response-network-error',
|
|
67
|
+
id: data.id,
|
|
68
|
+
};
|
|
69
|
+
window.remotion_broadcastChannel.postMessage(networkErrorResponse);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (result.type === 'unknown-container-format') {
|
|
73
|
+
const unknownContainerFormatResponse = {
|
|
74
|
+
type: 'response-unknown-container-format',
|
|
75
|
+
id: data.id,
|
|
76
|
+
};
|
|
77
|
+
window.remotion_broadcastChannel.postMessage(unknownContainerFormatResponse);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const { frame, audio, durationInSeconds } = result;
|
|
81
|
+
const imageBitmap = frame ? await createImageBitmap(frame) : null;
|
|
82
|
+
if (frame) {
|
|
83
|
+
frame.close();
|
|
84
|
+
}
|
|
85
|
+
const response = {
|
|
86
|
+
type: 'response-success',
|
|
87
|
+
id: data.id,
|
|
88
|
+
frame: imageBitmap,
|
|
89
|
+
audio,
|
|
90
|
+
durationInSeconds: durationInSeconds ?? null,
|
|
91
|
+
};
|
|
92
|
+
window.remotion_broadcastChannel.postMessage(response);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
const response = {
|
|
96
|
+
type: 'response-error',
|
|
97
|
+
id: data.id,
|
|
98
|
+
errorStack: error.stack ?? 'No stack trace',
|
|
99
|
+
};
|
|
100
|
+
window.remotion_broadcastChannel.postMessage(response);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
throw new Error('Invalid message: ' + JSON.stringify(data));
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
emitReadiness(window.remotion_broadcastChannel);
|
|
108
|
+
};
|
|
109
|
+
let mainTabIsReadyProm = null;
|
|
110
|
+
export const waitForMainTabToBeReady = (channel) => {
|
|
111
|
+
if (mainTabIsReadyProm) {
|
|
112
|
+
return mainTabIsReadyProm;
|
|
113
|
+
}
|
|
114
|
+
mainTabIsReadyProm = new Promise((resolve) => {
|
|
115
|
+
const onMessage = (event) => {
|
|
116
|
+
const data = event.data;
|
|
117
|
+
if (data.type === 'main-tab-ready') {
|
|
118
|
+
resolve();
|
|
119
|
+
channel.removeEventListener('message', onMessage);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
channel.addEventListener('message', onMessage);
|
|
123
|
+
});
|
|
124
|
+
return mainTabIsReadyProm;
|
|
125
|
+
};
|
|
@@ -1,90 +1,7 @@
|
|
|
1
1
|
import { extractFrameAndAudio } from '../extract-frame-and-audio';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
window.remotion_isMainTab) {
|
|
6
|
-
window.remotion_broadcastChannel.addEventListener('message', async (event) => {
|
|
7
|
-
const data = event.data;
|
|
8
|
-
if (data.type === 'request') {
|
|
9
|
-
try {
|
|
10
|
-
const result = await extractFrameAndAudio({
|
|
11
|
-
src: data.src,
|
|
12
|
-
timeInSeconds: data.timeInSeconds,
|
|
13
|
-
logLevel: data.logLevel,
|
|
14
|
-
durationInSeconds: data.durationInSeconds,
|
|
15
|
-
playbackRate: data.playbackRate,
|
|
16
|
-
includeAudio: data.includeAudio,
|
|
17
|
-
includeVideo: data.includeVideo,
|
|
18
|
-
loop: data.loop,
|
|
19
|
-
audioStreamIndex: data.audioStreamIndex,
|
|
20
|
-
trimAfter: data.trimAfter,
|
|
21
|
-
trimBefore: data.trimBefore,
|
|
22
|
-
fps: data.fps,
|
|
23
|
-
maxCacheSize: data.maxCacheSize,
|
|
24
|
-
});
|
|
25
|
-
if (result.type === 'cannot-decode') {
|
|
26
|
-
const cannotDecodeResponse = {
|
|
27
|
-
type: 'response-cannot-decode',
|
|
28
|
-
id: data.id,
|
|
29
|
-
durationInSeconds: result.durationInSeconds,
|
|
30
|
-
};
|
|
31
|
-
window.remotion_broadcastChannel.postMessage(cannotDecodeResponse);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (result.type === 'cannot-decode-alpha') {
|
|
35
|
-
const cannotDecodeAlphaResponse = {
|
|
36
|
-
type: 'response-cannot-decode-alpha',
|
|
37
|
-
id: data.id,
|
|
38
|
-
durationInSeconds: result.durationInSeconds,
|
|
39
|
-
};
|
|
40
|
-
window.remotion_broadcastChannel.postMessage(cannotDecodeAlphaResponse);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (result.type === 'network-error') {
|
|
44
|
-
const networkErrorResponse = {
|
|
45
|
-
type: 'response-network-error',
|
|
46
|
-
id: data.id,
|
|
47
|
-
};
|
|
48
|
-
window.remotion_broadcastChannel.postMessage(networkErrorResponse);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
if (result.type === 'unknown-container-format') {
|
|
52
|
-
const unknownContainerFormatResponse = {
|
|
53
|
-
type: 'response-unknown-container-format',
|
|
54
|
-
id: data.id,
|
|
55
|
-
};
|
|
56
|
-
window.remotion_broadcastChannel.postMessage(unknownContainerFormatResponse);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const { frame, audio, durationInSeconds } = result;
|
|
60
|
-
const imageBitmap = frame ? await createImageBitmap(frame) : null;
|
|
61
|
-
if (frame) {
|
|
62
|
-
frame.close();
|
|
63
|
-
}
|
|
64
|
-
const response = {
|
|
65
|
-
type: 'response-success',
|
|
66
|
-
id: data.id,
|
|
67
|
-
frame: imageBitmap,
|
|
68
|
-
audio,
|
|
69
|
-
durationInSeconds: durationInSeconds ?? null,
|
|
70
|
-
};
|
|
71
|
-
window.remotion_broadcastChannel.postMessage(response);
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
const response = {
|
|
75
|
-
type: 'response-error',
|
|
76
|
-
id: data.id,
|
|
77
|
-
errorStack: error.stack ?? 'No stack trace',
|
|
78
|
-
};
|
|
79
|
-
window.remotion_broadcastChannel.postMessage(response);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
throw new Error('Invalid message: ' + JSON.stringify(data));
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
export const extractFrameViaBroadcastChannel = ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, isClientSideRendering, loop, audioStreamIndex, trimAfter, trimBefore, fps, maxCacheSize, }) => {
|
|
2
|
+
import { addBroadcastChannelListener, waitForMainTabToBeReady, } from './add-broadcast-channel-listener';
|
|
3
|
+
addBroadcastChannelListener();
|
|
4
|
+
export const extractFrameViaBroadcastChannel = async ({ src, timeInSeconds, logLevel, durationInSeconds, playbackRate, includeAudio, includeVideo, isClientSideRendering, loop, audioStreamIndex, trimAfter, trimBefore, fps, maxCacheSize, }) => {
|
|
88
5
|
if (isClientSideRendering || window.remotion_isMainTab) {
|
|
89
6
|
return extractFrameAndAudio({
|
|
90
7
|
logLevel,
|
|
@@ -102,6 +19,7 @@ export const extractFrameViaBroadcastChannel = ({ src, timeInSeconds, logLevel,
|
|
|
102
19
|
maxCacheSize,
|
|
103
20
|
});
|
|
104
21
|
}
|
|
22
|
+
await waitForMainTabToBeReady(window.remotion_broadcastChannel);
|
|
105
23
|
const requestId = crypto.randomUUID();
|
|
106
24
|
const resolvePromise = new Promise((resolve, reject) => {
|
|
107
25
|
const onMessage = (event) => {
|
|
@@ -109,6 +27,9 @@ export const extractFrameViaBroadcastChannel = ({ src, timeInSeconds, logLevel,
|
|
|
109
27
|
if (!data) {
|
|
110
28
|
return;
|
|
111
29
|
}
|
|
30
|
+
if (data.type === 'main-tab-ready') {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
112
33
|
if (data.id !== requestId) {
|
|
113
34
|
return;
|
|
114
35
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remotion/media",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.395",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/esm/index.mjs",
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
"make": "tsc -d && bun --env-file=../.env.bundle bundle.ts"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"mediabunny": "1.27.
|
|
25
|
-
"remotion": "4.0.
|
|
24
|
+
"mediabunny": "1.27.2",
|
|
25
|
+
"remotion": "4.0.395"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": ">=16.8.0",
|
|
29
29
|
"react-dom": ">=16.8.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
32
|
+
"@remotion/eslint-config-internal": "4.0.395",
|
|
33
33
|
"@vitest/browser-webdriverio": "4.0.9",
|
|
34
34
|
"eslint": "9.19.0",
|
|
35
35
|
"react": "19.2.3",
|