@remotion/web-renderer 4.0.402 → 4.0.403
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/can-render-media-on-web.d.ts +3 -0
- package/dist/can-render-types.d.ts +27 -0
- package/dist/check-webgl-support.d.ts +2 -0
- package/dist/create-audio-sample-source.d.ts +9 -0
- package/dist/esm/index.mjs +370 -138
- package/dist/get-encodable-codecs.d.ts +9 -0
- package/dist/index.d.ts +5 -1
- package/dist/mediabunny-mappings.d.ts +5 -0
- package/dist/render-media-on-web.d.ts +3 -1
- package/dist/renoun.d.ts +119 -0
- package/dist/resolve-audio-codec.d.ts +13 -0
- package/dist/validate-dimensions.d.ts +7 -0
- package/package.json +6 -6
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CanRenderMediaOnWebOptions, CanRenderMediaOnWebResult } from './can-render-types';
|
|
2
|
+
export type { CanRenderIssue, CanRenderMediaOnWebOptions, CanRenderMediaOnWebResult, } from './can-render-types';
|
|
3
|
+
export declare const canRenderMediaOnWeb: (options: CanRenderMediaOnWebOptions) => Promise<CanRenderMediaOnWebResult>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { WebRendererAudioCodec, WebRendererContainer, WebRendererQuality, WebRendererVideoCodec } from './mediabunny-mappings';
|
|
2
|
+
import type { WebRendererOutputTarget } from './output-target';
|
|
3
|
+
export type CanRenderIssueType = 'video-codec-unsupported' | 'audio-codec-unsupported' | 'webgl-unsupported' | 'webcodecs-unavailable' | 'container-codec-mismatch' | 'transparent-video-unsupported' | 'invalid-dimensions' | 'output-target-unsupported';
|
|
4
|
+
export type CanRenderIssue = {
|
|
5
|
+
type: CanRenderIssueType;
|
|
6
|
+
message: string;
|
|
7
|
+
severity: 'error' | 'warning';
|
|
8
|
+
};
|
|
9
|
+
export type CanRenderMediaOnWebResult = {
|
|
10
|
+
canRender: boolean;
|
|
11
|
+
issues: CanRenderIssue[];
|
|
12
|
+
resolvedVideoCodec: WebRendererVideoCodec;
|
|
13
|
+
resolvedAudioCodec: WebRendererAudioCodec | null;
|
|
14
|
+
resolvedOutputTarget: WebRendererOutputTarget;
|
|
15
|
+
};
|
|
16
|
+
export type CanRenderMediaOnWebOptions = {
|
|
17
|
+
container?: WebRendererContainer;
|
|
18
|
+
videoCodec?: WebRendererVideoCodec;
|
|
19
|
+
audioCodec?: WebRendererAudioCodec | null;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
transparent?: boolean;
|
|
23
|
+
muted?: boolean;
|
|
24
|
+
videoBitrate?: number | WebRendererQuality;
|
|
25
|
+
audioBitrate?: number | WebRendererQuality;
|
|
26
|
+
outputTarget?: WebRendererOutputTarget | null;
|
|
27
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AudioSampleSource, type Quality } from 'mediabunny';
|
|
2
|
+
export declare const createAudioSampleSource: ({ muted, codec, bitrate, }: {
|
|
3
|
+
muted: boolean;
|
|
4
|
+
codec: "aac" | "alaw" | "flac" | "mp3" | "opus" | "pcm-f32" | "pcm-f32be" | "pcm-f64" | "pcm-f64be" | "pcm-s16" | "pcm-s16be" | "pcm-s24" | "pcm-s24be" | "pcm-s32" | "pcm-s32be" | "pcm-s8" | "pcm-u8" | "ulaw" | "vorbis" | null;
|
|
5
|
+
bitrate: number | Quality;
|
|
6
|
+
}) => {
|
|
7
|
+
audioSampleSource: AudioSampleSource;
|
|
8
|
+
[Symbol.dispose]: () => void;
|
|
9
|
+
} | null;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -36,6 +36,327 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
36
36
|
return next();
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
// src/can-render-media-on-web.ts
|
|
40
|
+
import { canEncodeVideo } from "mediabunny";
|
|
41
|
+
|
|
42
|
+
// src/can-use-webfs-target.ts
|
|
43
|
+
var canUseWebFsWriter = async () => {
|
|
44
|
+
if (!("storage" in navigator)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
if (!("getDirectory" in navigator.storage)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const directoryHandle = await navigator.storage.getDirectory();
|
|
52
|
+
const fileHandle = await directoryHandle.getFileHandle("remotion-probe-web-fs-support", {
|
|
53
|
+
create: true
|
|
54
|
+
});
|
|
55
|
+
const canUse = fileHandle.createWritable !== undefined;
|
|
56
|
+
return canUse;
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// src/check-webgl-support.ts
|
|
63
|
+
var checkWebGLSupport = () => {
|
|
64
|
+
try {
|
|
65
|
+
const canvas = new OffscreenCanvas(1, 1);
|
|
66
|
+
const gl = canvas.getContext("webgl2") || canvas.getContext("webgl");
|
|
67
|
+
if (!gl) {
|
|
68
|
+
return {
|
|
69
|
+
type: "webgl-unsupported",
|
|
70
|
+
message: "WebGL is not supported. 3D CSS transforms will fail.",
|
|
71
|
+
severity: "error"
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
} catch {
|
|
76
|
+
return {
|
|
77
|
+
type: "webgl-unsupported",
|
|
78
|
+
message: "WebGL is not supported. 3D CSS transforms will fail.",
|
|
79
|
+
severity: "error"
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/mediabunny-mappings.ts
|
|
85
|
+
import {
|
|
86
|
+
Mp4OutputFormat,
|
|
87
|
+
QUALITY_HIGH,
|
|
88
|
+
QUALITY_LOW,
|
|
89
|
+
QUALITY_MEDIUM,
|
|
90
|
+
QUALITY_VERY_HIGH,
|
|
91
|
+
QUALITY_VERY_LOW,
|
|
92
|
+
WebMOutputFormat
|
|
93
|
+
} from "mediabunny";
|
|
94
|
+
var codecToMediabunnyCodec = (codec) => {
|
|
95
|
+
switch (codec) {
|
|
96
|
+
case "h264":
|
|
97
|
+
return "avc";
|
|
98
|
+
case "h265":
|
|
99
|
+
return "hevc";
|
|
100
|
+
case "vp8":
|
|
101
|
+
return "vp8";
|
|
102
|
+
case "vp9":
|
|
103
|
+
return "vp9";
|
|
104
|
+
case "av1":
|
|
105
|
+
return "av1";
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported codec: ${codec}`);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
var containerToMediabunnyContainer = (container) => {
|
|
111
|
+
switch (container) {
|
|
112
|
+
case "mp4":
|
|
113
|
+
return new Mp4OutputFormat;
|
|
114
|
+
case "webm":
|
|
115
|
+
return new WebMOutputFormat;
|
|
116
|
+
default:
|
|
117
|
+
throw new Error(`Unsupported container: ${container}`);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
var getDefaultVideoCodecForContainer = (container) => {
|
|
121
|
+
switch (container) {
|
|
122
|
+
case "mp4":
|
|
123
|
+
return "h264";
|
|
124
|
+
case "webm":
|
|
125
|
+
return "vp8";
|
|
126
|
+
default:
|
|
127
|
+
throw new Error(`Unsupported container: ${container}`);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var getQualityForWebRendererQuality = (quality) => {
|
|
131
|
+
switch (quality) {
|
|
132
|
+
case "very-low":
|
|
133
|
+
return QUALITY_VERY_LOW;
|
|
134
|
+
case "low":
|
|
135
|
+
return QUALITY_LOW;
|
|
136
|
+
case "medium":
|
|
137
|
+
return QUALITY_MEDIUM;
|
|
138
|
+
case "high":
|
|
139
|
+
return QUALITY_HIGH;
|
|
140
|
+
case "very-high":
|
|
141
|
+
return QUALITY_VERY_HIGH;
|
|
142
|
+
default:
|
|
143
|
+
throw new Error(`Unsupported quality: ${quality}`);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
var getMimeType = (container) => {
|
|
147
|
+
switch (container) {
|
|
148
|
+
case "mp4":
|
|
149
|
+
return "video/mp4";
|
|
150
|
+
case "webm":
|
|
151
|
+
return "video/webm";
|
|
152
|
+
default:
|
|
153
|
+
throw new Error(`Unsupported container: ${container}`);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
var getDefaultAudioCodecForContainer = (container) => {
|
|
157
|
+
switch (container) {
|
|
158
|
+
case "mp4":
|
|
159
|
+
return "aac";
|
|
160
|
+
case "webm":
|
|
161
|
+
return "opus";
|
|
162
|
+
default:
|
|
163
|
+
throw new Error(`Unsupported container: ${container}`);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
var WEB_RENDERER_VIDEO_CODECS = [
|
|
167
|
+
"h264",
|
|
168
|
+
"h265",
|
|
169
|
+
"vp8",
|
|
170
|
+
"vp9",
|
|
171
|
+
"av1"
|
|
172
|
+
];
|
|
173
|
+
var getSupportedVideoCodecsForContainer = (container) => {
|
|
174
|
+
const format = containerToMediabunnyContainer(container);
|
|
175
|
+
const allSupported = format.getSupportedVideoCodecs();
|
|
176
|
+
return WEB_RENDERER_VIDEO_CODECS.filter((codec) => allSupported.includes(codecToMediabunnyCodec(codec)));
|
|
177
|
+
};
|
|
178
|
+
var WEB_RENDERER_AUDIO_CODECS = ["aac", "opus"];
|
|
179
|
+
var getSupportedAudioCodecsForContainer = (container) => {
|
|
180
|
+
const format = containerToMediabunnyContainer(container);
|
|
181
|
+
const allSupported = format.getSupportedAudioCodecs();
|
|
182
|
+
return WEB_RENDERER_AUDIO_CODECS.filter((codec) => allSupported.includes(codec));
|
|
183
|
+
};
|
|
184
|
+
var audioCodecToMediabunnyAudioCodec = (audioCodec) => {
|
|
185
|
+
return audioCodec;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/resolve-audio-codec.ts
|
|
189
|
+
import { canEncodeAudio } from "mediabunny";
|
|
190
|
+
var resolveAudioCodec = async (options) => {
|
|
191
|
+
const issues = [];
|
|
192
|
+
const { container, requestedCodec, userSpecifiedAudioCodec, bitrate } = options;
|
|
193
|
+
const audioCodec = requestedCodec ?? getDefaultAudioCodecForContainer(container);
|
|
194
|
+
const supportedAudioCodecs = getSupportedAudioCodecsForContainer(container);
|
|
195
|
+
if (!supportedAudioCodecs.includes(audioCodec)) {
|
|
196
|
+
issues.push({
|
|
197
|
+
type: "audio-codec-unsupported",
|
|
198
|
+
message: `Audio codec "${audioCodec}" is not supported for container "${container}". Supported: ${supportedAudioCodecs.join(", ")}`,
|
|
199
|
+
severity: "error"
|
|
200
|
+
});
|
|
201
|
+
return { codec: null, issues };
|
|
202
|
+
}
|
|
203
|
+
const mediabunnyAudioCodec = audioCodecToMediabunnyAudioCodec(audioCodec);
|
|
204
|
+
const canEncode = await canEncodeAudio(mediabunnyAudioCodec, { bitrate });
|
|
205
|
+
if (canEncode) {
|
|
206
|
+
return { codec: audioCodec, issues };
|
|
207
|
+
}
|
|
208
|
+
if (userSpecifiedAudioCodec) {
|
|
209
|
+
issues.push({
|
|
210
|
+
type: "audio-codec-unsupported",
|
|
211
|
+
message: `Audio codec "${audioCodec}" cannot be encoded by this browser. This is common for AAC on Firefox. Try using "opus" instead.`,
|
|
212
|
+
severity: "error"
|
|
213
|
+
});
|
|
214
|
+
return { codec: null, issues };
|
|
215
|
+
}
|
|
216
|
+
for (const fallbackCodec of supportedAudioCodecs) {
|
|
217
|
+
if (fallbackCodec !== audioCodec) {
|
|
218
|
+
const fallbackMediabunnyCodec = audioCodecToMediabunnyAudioCodec(fallbackCodec);
|
|
219
|
+
const canEncodeFallback = await canEncodeAudio(fallbackMediabunnyCodec, {
|
|
220
|
+
bitrate
|
|
221
|
+
});
|
|
222
|
+
if (canEncodeFallback) {
|
|
223
|
+
issues.push({
|
|
224
|
+
type: "audio-codec-unsupported",
|
|
225
|
+
message: `Falling back from audio codec "${audioCodec}" to "${fallbackCodec}" because the original codec cannot be encoded by this browser.`,
|
|
226
|
+
severity: "warning"
|
|
227
|
+
});
|
|
228
|
+
return { codec: fallbackCodec, issues };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
issues.push({
|
|
233
|
+
type: "audio-codec-unsupported",
|
|
234
|
+
message: `No audio codec can be encoded by this browser for container "${container}".`,
|
|
235
|
+
severity: "error"
|
|
236
|
+
});
|
|
237
|
+
return { codec: null, issues };
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// src/validate-dimensions.ts
|
|
241
|
+
var validateDimensions = (options) => {
|
|
242
|
+
const { width, height, codec } = options;
|
|
243
|
+
if (codec === "h264" || codec === "h265") {
|
|
244
|
+
if (width % 2 !== 0 || height % 2 !== 0) {
|
|
245
|
+
return {
|
|
246
|
+
type: "invalid-dimensions",
|
|
247
|
+
message: `${codec.toUpperCase()} codec requires width and height to be multiples of 2. Got ${width}x${height}`,
|
|
248
|
+
severity: "error"
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return null;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// src/can-render-media-on-web.ts
|
|
256
|
+
var canRenderMediaOnWeb = async (options) => {
|
|
257
|
+
const issues = [];
|
|
258
|
+
if (typeof VideoEncoder === "undefined") {
|
|
259
|
+
issues.push({
|
|
260
|
+
type: "webcodecs-unavailable",
|
|
261
|
+
message: "WebCodecs API is not available in this browser. A modern browser with WebCodecs support is required.",
|
|
262
|
+
severity: "error"
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
const container = options.container ?? "mp4";
|
|
266
|
+
const videoCodec = options.videoCodec ?? getDefaultVideoCodecForContainer(container);
|
|
267
|
+
const transparent = options.transparent ?? false;
|
|
268
|
+
const muted = options.muted ?? false;
|
|
269
|
+
const { width, height } = options;
|
|
270
|
+
const resolvedVideoBitrate = typeof options.videoBitrate === "number" ? options.videoBitrate : getQualityForWebRendererQuality(options.videoBitrate ?? "medium");
|
|
271
|
+
const resolvedAudioBitrate = typeof options.audioBitrate === "number" ? options.audioBitrate : getQualityForWebRendererQuality(options.audioBitrate ?? "medium");
|
|
272
|
+
const format = containerToMediabunnyContainer(container);
|
|
273
|
+
if (!format.getSupportedCodecs().includes(codecToMediabunnyCodec(videoCodec))) {
|
|
274
|
+
issues.push({
|
|
275
|
+
type: "container-codec-mismatch",
|
|
276
|
+
message: `Codec ${videoCodec} is not supported for container ${container}`,
|
|
277
|
+
severity: "error"
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
const dimensionIssue = validateDimensions({ width, height, codec: videoCodec });
|
|
281
|
+
if (dimensionIssue) {
|
|
282
|
+
issues.push(dimensionIssue);
|
|
283
|
+
}
|
|
284
|
+
const canEncodeVideoResult = await canEncodeVideo(codecToMediabunnyCodec(videoCodec), { bitrate: resolvedVideoBitrate });
|
|
285
|
+
if (!canEncodeVideoResult) {
|
|
286
|
+
issues.push({
|
|
287
|
+
type: "video-codec-unsupported",
|
|
288
|
+
message: `Video codec "${videoCodec}" cannot be encoded by this browser`,
|
|
289
|
+
severity: "error"
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (transparent && !["vp8", "vp9"].includes(videoCodec)) {
|
|
293
|
+
issues.push({
|
|
294
|
+
type: "transparent-video-unsupported",
|
|
295
|
+
message: `Transparent video requires VP8 or VP9 codec with WebM container. ${videoCodec} does not support alpha channel.`,
|
|
296
|
+
severity: "error"
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
let resolvedAudioCodec = null;
|
|
300
|
+
if (!muted) {
|
|
301
|
+
const audioResult = await resolveAudioCodec({
|
|
302
|
+
container,
|
|
303
|
+
requestedCodec: options.audioCodec,
|
|
304
|
+
userSpecifiedAudioCodec: options.audioCodec !== undefined && options.audioCodec !== null,
|
|
305
|
+
bitrate: resolvedAudioBitrate
|
|
306
|
+
});
|
|
307
|
+
resolvedAudioCodec = audioResult.codec;
|
|
308
|
+
issues.push(...audioResult.issues);
|
|
309
|
+
}
|
|
310
|
+
const webglIssue = checkWebGLSupport();
|
|
311
|
+
if (webglIssue) {
|
|
312
|
+
issues.push(webglIssue);
|
|
313
|
+
}
|
|
314
|
+
const canUseWebFs = await canUseWebFsWriter();
|
|
315
|
+
let resolvedOutputTarget;
|
|
316
|
+
if (options.outputTarget === "web-fs") {
|
|
317
|
+
if (!canUseWebFs) {
|
|
318
|
+
issues.push({
|
|
319
|
+
type: "output-target-unsupported",
|
|
320
|
+
message: 'The "web-fs" output target is not supported in this browser. The File System Access API is required.',
|
|
321
|
+
severity: "error"
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
resolvedOutputTarget = "web-fs";
|
|
325
|
+
} else if (options.outputTarget === "arraybuffer") {
|
|
326
|
+
resolvedOutputTarget = "arraybuffer";
|
|
327
|
+
} else {
|
|
328
|
+
resolvedOutputTarget = canUseWebFs ? "web-fs" : "arraybuffer";
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
canRender: issues.filter((i) => i.severity === "error").length === 0,
|
|
332
|
+
issues,
|
|
333
|
+
resolvedVideoCodec: videoCodec,
|
|
334
|
+
resolvedAudioCodec,
|
|
335
|
+
resolvedOutputTarget
|
|
336
|
+
};
|
|
337
|
+
};
|
|
338
|
+
// src/get-encodable-codecs.ts
|
|
339
|
+
import {
|
|
340
|
+
getEncodableAudioCodecs as mediabunnyGetEncodableAudioCodecs,
|
|
341
|
+
getEncodableVideoCodecs as mediabunnyGetEncodableVideoCodecs
|
|
342
|
+
} from "mediabunny";
|
|
343
|
+
var getEncodableVideoCodecs = async (container, options) => {
|
|
344
|
+
const supported = getSupportedVideoCodecsForContainer(container);
|
|
345
|
+
const mediabunnyCodecs = supported.map(codecToMediabunnyCodec);
|
|
346
|
+
const resolvedBitrate = options?.videoBitrate ? typeof options.videoBitrate === "number" ? options.videoBitrate : getQualityForWebRendererQuality(options.videoBitrate) : undefined;
|
|
347
|
+
const encodable = await mediabunnyGetEncodableVideoCodecs(mediabunnyCodecs, {
|
|
348
|
+
bitrate: resolvedBitrate
|
|
349
|
+
});
|
|
350
|
+
return supported.filter((c) => encodable.includes(codecToMediabunnyCodec(c)));
|
|
351
|
+
};
|
|
352
|
+
var getEncodableAudioCodecs = async (container, options) => {
|
|
353
|
+
const supported = getSupportedAudioCodecsForContainer(container);
|
|
354
|
+
const resolvedBitrate = options?.audioBitrate ? typeof options.audioBitrate === "number" ? options.audioBitrate : getQualityForWebRendererQuality(options.audioBitrate) : undefined;
|
|
355
|
+
const encodable = await mediabunnyGetEncodableAudioCodecs(supported, {
|
|
356
|
+
bitrate: resolvedBitrate
|
|
357
|
+
});
|
|
358
|
+
return supported.filter((c) => encodable.includes(c));
|
|
359
|
+
};
|
|
39
360
|
// src/render-media-on-web.tsx
|
|
40
361
|
import { BufferTarget, StreamTarget } from "mediabunny";
|
|
41
362
|
import { Internals as Internals7 } from "remotion";
|
|
@@ -167,24 +488,21 @@ var onlyInlineAudio = ({
|
|
|
167
488
|
});
|
|
168
489
|
};
|
|
169
490
|
|
|
170
|
-
// src/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
const directoryHandle = await navigator.storage.getDirectory();
|
|
180
|
-
const fileHandle = await directoryHandle.getFileHandle("remotion-probe-web-fs-support", {
|
|
181
|
-
create: true
|
|
182
|
-
});
|
|
183
|
-
const canUse = fileHandle.createWritable !== undefined;
|
|
184
|
-
return canUse;
|
|
185
|
-
} catch {
|
|
186
|
-
return false;
|
|
491
|
+
// src/create-audio-sample-source.ts
|
|
492
|
+
import { AudioSampleSource } from "mediabunny";
|
|
493
|
+
var createAudioSampleSource = ({
|
|
494
|
+
muted,
|
|
495
|
+
codec,
|
|
496
|
+
bitrate
|
|
497
|
+
}) => {
|
|
498
|
+
if (muted || codec === null) {
|
|
499
|
+
return null;
|
|
187
500
|
}
|
|
501
|
+
const audioSampleSource = new AudioSampleSource({
|
|
502
|
+
codec,
|
|
503
|
+
bitrate
|
|
504
|
+
});
|
|
505
|
+
return { audioSampleSource, [Symbol.dispose]: () => audioSampleSource.close() };
|
|
188
506
|
};
|
|
189
507
|
|
|
190
508
|
// src/create-scaffold.tsx
|
|
@@ -398,51 +716,6 @@ var getRealFrameRange = (durationInFrames, frameRange) => {
|
|
|
398
716
|
return frameRange;
|
|
399
717
|
};
|
|
400
718
|
|
|
401
|
-
// src/get-audio-sample-source.ts
|
|
402
|
-
import {
|
|
403
|
-
AudioSampleSource
|
|
404
|
-
} from "mediabunny";
|
|
405
|
-
|
|
406
|
-
// src/get-audio-encoding-config.ts
|
|
407
|
-
import {
|
|
408
|
-
canEncodeAudio,
|
|
409
|
-
QUALITY_MEDIUM
|
|
410
|
-
} from "mediabunny";
|
|
411
|
-
var getDefaultAudioEncodingConfig = async () => {
|
|
412
|
-
const preferredDefaultAudioEncodingConfig = {
|
|
413
|
-
codec: "aac",
|
|
414
|
-
bitrate: QUALITY_MEDIUM
|
|
415
|
-
};
|
|
416
|
-
if (await canEncodeAudio(preferredDefaultAudioEncodingConfig.codec, preferredDefaultAudioEncodingConfig)) {
|
|
417
|
-
return preferredDefaultAudioEncodingConfig;
|
|
418
|
-
}
|
|
419
|
-
const backupDefaultAudioEncodingConfig = {
|
|
420
|
-
codec: "opus",
|
|
421
|
-
bitrate: QUALITY_MEDIUM
|
|
422
|
-
};
|
|
423
|
-
if (await canEncodeAudio(backupDefaultAudioEncodingConfig.codec, backupDefaultAudioEncodingConfig)) {
|
|
424
|
-
return backupDefaultAudioEncodingConfig;
|
|
425
|
-
}
|
|
426
|
-
return null;
|
|
427
|
-
};
|
|
428
|
-
|
|
429
|
-
// src/get-audio-sample-source.ts
|
|
430
|
-
var addAudioSampleSource = async ({
|
|
431
|
-
muted,
|
|
432
|
-
output
|
|
433
|
-
}) => {
|
|
434
|
-
if (muted) {
|
|
435
|
-
return null;
|
|
436
|
-
}
|
|
437
|
-
const defaultAudioEncodingConfig = await getDefaultAudioEncodingConfig();
|
|
438
|
-
if (!defaultAudioEncodingConfig) {
|
|
439
|
-
throw new Error("No default audio encoding config found");
|
|
440
|
-
}
|
|
441
|
-
const audioSampleSource = new AudioSampleSource(defaultAudioEncodingConfig);
|
|
442
|
-
output.addAudioTrack(audioSampleSource);
|
|
443
|
-
return { audioSampleSource, [Symbol.dispose]: () => audioSampleSource.close() };
|
|
444
|
-
};
|
|
445
|
-
|
|
446
719
|
// src/internal-state.ts
|
|
447
720
|
var makeInternalState = () => {
|
|
448
721
|
let drawnPrecomposedPixels = 0;
|
|
@@ -513,79 +786,6 @@ var makeVideoSampleSourceCleanup = (encodingConfig) => {
|
|
|
513
786
|
};
|
|
514
787
|
};
|
|
515
788
|
|
|
516
|
-
// src/mediabunny-mappings.ts
|
|
517
|
-
import {
|
|
518
|
-
Mp4OutputFormat,
|
|
519
|
-
QUALITY_HIGH,
|
|
520
|
-
QUALITY_LOW,
|
|
521
|
-
QUALITY_MEDIUM as QUALITY_MEDIUM2,
|
|
522
|
-
QUALITY_VERY_HIGH,
|
|
523
|
-
QUALITY_VERY_LOW,
|
|
524
|
-
WebMOutputFormat
|
|
525
|
-
} from "mediabunny";
|
|
526
|
-
var codecToMediabunnyCodec = (codec) => {
|
|
527
|
-
switch (codec) {
|
|
528
|
-
case "h264":
|
|
529
|
-
return "avc";
|
|
530
|
-
case "h265":
|
|
531
|
-
return "hevc";
|
|
532
|
-
case "vp8":
|
|
533
|
-
return "vp8";
|
|
534
|
-
case "vp9":
|
|
535
|
-
return "vp9";
|
|
536
|
-
case "av1":
|
|
537
|
-
return "av1";
|
|
538
|
-
default:
|
|
539
|
-
throw new Error(`Unsupported codec: ${codec}`);
|
|
540
|
-
}
|
|
541
|
-
};
|
|
542
|
-
var containerToMediabunnyContainer = (container) => {
|
|
543
|
-
switch (container) {
|
|
544
|
-
case "mp4":
|
|
545
|
-
return new Mp4OutputFormat;
|
|
546
|
-
case "webm":
|
|
547
|
-
return new WebMOutputFormat;
|
|
548
|
-
default:
|
|
549
|
-
throw new Error(`Unsupported container: ${container}`);
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
var getDefaultVideoCodecForContainer = (container) => {
|
|
553
|
-
switch (container) {
|
|
554
|
-
case "mp4":
|
|
555
|
-
return "h264";
|
|
556
|
-
case "webm":
|
|
557
|
-
return "vp8";
|
|
558
|
-
default:
|
|
559
|
-
throw new Error(`Unsupported container: ${container}`);
|
|
560
|
-
}
|
|
561
|
-
};
|
|
562
|
-
var getQualityForWebRendererQuality = (quality) => {
|
|
563
|
-
switch (quality) {
|
|
564
|
-
case "very-low":
|
|
565
|
-
return QUALITY_VERY_LOW;
|
|
566
|
-
case "low":
|
|
567
|
-
return QUALITY_LOW;
|
|
568
|
-
case "medium":
|
|
569
|
-
return QUALITY_MEDIUM2;
|
|
570
|
-
case "high":
|
|
571
|
-
return QUALITY_HIGH;
|
|
572
|
-
case "very-high":
|
|
573
|
-
return QUALITY_VERY_HIGH;
|
|
574
|
-
default:
|
|
575
|
-
throw new Error(`Unsupported quality: ${quality}`);
|
|
576
|
-
}
|
|
577
|
-
};
|
|
578
|
-
var getMimeType = (container) => {
|
|
579
|
-
switch (container) {
|
|
580
|
-
case "mp4":
|
|
581
|
-
return "video/mp4";
|
|
582
|
-
case "webm":
|
|
583
|
-
return "video/webm";
|
|
584
|
-
default:
|
|
585
|
-
throw new Error(`Unsupported container: ${container}`);
|
|
586
|
-
}
|
|
587
|
-
};
|
|
588
|
-
|
|
589
789
|
// src/render-operations-queue.ts
|
|
590
790
|
var onlyOneRenderAtATimeQueue = {
|
|
591
791
|
ref: Promise.resolve()
|
|
@@ -3432,6 +3632,8 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3432
3632
|
mediaCacheSizeInBytes,
|
|
3433
3633
|
schema,
|
|
3434
3634
|
videoCodec: codec,
|
|
3635
|
+
audioCodec: unresolvedAudioCodec,
|
|
3636
|
+
audioBitrate,
|
|
3435
3637
|
container,
|
|
3436
3638
|
signal,
|
|
3437
3639
|
onProgress,
|
|
@@ -3456,6 +3658,23 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3456
3658
|
if (codec && !format.getSupportedCodecs().includes(codecToMediabunnyCodec(codec))) {
|
|
3457
3659
|
return Promise.reject(new Error(`Codec ${codec} is not supported for container ${container}`));
|
|
3458
3660
|
}
|
|
3661
|
+
const resolvedAudioBitrate = typeof audioBitrate === "number" ? audioBitrate : getQualityForWebRendererQuality(audioBitrate);
|
|
3662
|
+
let finalAudioCodec = null;
|
|
3663
|
+
if (!muted) {
|
|
3664
|
+
const audioResult = await resolveAudioCodec({
|
|
3665
|
+
container,
|
|
3666
|
+
requestedCodec: unresolvedAudioCodec,
|
|
3667
|
+
userSpecifiedAudioCodec: unresolvedAudioCodec !== undefined && unresolvedAudioCodec !== null,
|
|
3668
|
+
bitrate: resolvedAudioBitrate
|
|
3669
|
+
});
|
|
3670
|
+
for (const issue of audioResult.issues) {
|
|
3671
|
+
if (issue.severity === "error") {
|
|
3672
|
+
return Promise.reject(new Error(issue.message));
|
|
3673
|
+
}
|
|
3674
|
+
Internals7.Log.warn({ logLevel, tag: "@remotion/web-renderer" }, issue.message);
|
|
3675
|
+
}
|
|
3676
|
+
finalAudioCodec = audioResult.codec;
|
|
3677
|
+
}
|
|
3459
3678
|
const resolved = await Internals7.resolveVideoConfig({
|
|
3460
3679
|
calculateMetadata: composition.calculateMetadata ?? null,
|
|
3461
3680
|
signal: signal ?? new AbortController().signal,
|
|
@@ -3524,10 +3743,14 @@ var internalRenderMediaOnWeb = async ({
|
|
|
3524
3743
|
alpha: transparent ? "keep" : "discard"
|
|
3525
3744
|
}), 0);
|
|
3526
3745
|
outputWithCleanup.output.addVideoTrack(videoSampleSource.videoSampleSource);
|
|
3527
|
-
const audioSampleSource = __using(__stack,
|
|
3746
|
+
const audioSampleSource = __using(__stack, createAudioSampleSource({
|
|
3528
3747
|
muted,
|
|
3529
|
-
|
|
3748
|
+
codec: finalAudioCodec ? audioCodecToMediabunnyAudioCodec(finalAudioCodec) : null,
|
|
3749
|
+
bitrate: resolvedAudioBitrate
|
|
3530
3750
|
}), 0);
|
|
3751
|
+
if (audioSampleSource) {
|
|
3752
|
+
outputWithCleanup.output.addAudioTrack(audioSampleSource.audioSampleSource);
|
|
3753
|
+
}
|
|
3531
3754
|
await outputWithCleanup.output.start();
|
|
3532
3755
|
if (signal?.aborted) {
|
|
3533
3756
|
throw new Error("renderMediaOnWeb() was cancelled");
|
|
@@ -3680,6 +3903,8 @@ var renderMediaOnWeb = (options) => {
|
|
|
3680
3903
|
schema: options.schema ?? undefined,
|
|
3681
3904
|
mediaCacheSizeInBytes: options.mediaCacheSizeInBytes ?? null,
|
|
3682
3905
|
videoCodec: codec,
|
|
3906
|
+
audioCodec: options.audioCodec ?? null,
|
|
3907
|
+
audioBitrate: options.audioBitrate ?? "medium",
|
|
3683
3908
|
container,
|
|
3684
3909
|
signal: options.signal ?? null,
|
|
3685
3910
|
onProgress: options.onProgress ?? null,
|
|
@@ -3815,5 +4040,12 @@ var renderStillOnWeb = (options) => {
|
|
|
3815
4040
|
};
|
|
3816
4041
|
export {
|
|
3817
4042
|
renderStillOnWeb,
|
|
3818
|
-
renderMediaOnWeb
|
|
4043
|
+
renderMediaOnWeb,
|
|
4044
|
+
getSupportedVideoCodecsForContainer,
|
|
4045
|
+
getSupportedAudioCodecsForContainer,
|
|
4046
|
+
getEncodableVideoCodecs,
|
|
4047
|
+
getEncodableAudioCodecs,
|
|
4048
|
+
getDefaultVideoCodecForContainer,
|
|
4049
|
+
getDefaultAudioCodecForContainer,
|
|
4050
|
+
canRenderMediaOnWeb
|
|
3819
4051
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type WebRendererAudioCodec, type WebRendererContainer, type WebRendererQuality, type WebRendererVideoCodec } from './mediabunny-mappings';
|
|
2
|
+
export type GetEncodableVideoCodecsOptions = {
|
|
3
|
+
videoBitrate?: number | WebRendererQuality;
|
|
4
|
+
};
|
|
5
|
+
export type GetEncodableAudioCodecsOptions = {
|
|
6
|
+
audioBitrate?: number | WebRendererQuality;
|
|
7
|
+
};
|
|
8
|
+
export declare const getEncodableVideoCodecs: (container: WebRendererContainer, options?: GetEncodableVideoCodecsOptions | undefined) => Promise<WebRendererVideoCodec[]>;
|
|
9
|
+
export declare const getEncodableAudioCodecs: (container: WebRendererContainer, options?: GetEncodableAudioCodecsOptions | undefined) => Promise<WebRendererAudioCodec[]>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import './symbol-dispose';
|
|
2
2
|
export type { EmittedArtifact, WebRendererOnArtifact } from './artifact';
|
|
3
|
+
export { canRenderMediaOnWeb } from './can-render-media-on-web';
|
|
4
|
+
export type { CanRenderIssue, CanRenderMediaOnWebOptions, CanRenderMediaOnWebResult, } from './can-render-media-on-web';
|
|
3
5
|
export type { FrameRange } from './frame-range';
|
|
4
|
-
export
|
|
6
|
+
export { getEncodableAudioCodecs, getEncodableVideoCodecs, type GetEncodableAudioCodecsOptions, type GetEncodableVideoCodecsOptions, } from './get-encodable-codecs';
|
|
7
|
+
export { getDefaultAudioCodecForContainer, getDefaultVideoCodecForContainer, getSupportedAudioCodecsForContainer, getSupportedVideoCodecsForContainer, } from './mediabunny-mappings';
|
|
8
|
+
export type { WebRendererAudioCodec, WebRendererContainer, WebRendererQuality, WebRendererVideoCodec, } from './mediabunny-mappings';
|
|
5
9
|
export type { WebRendererOutputTarget } from './output-target';
|
|
6
10
|
export { renderMediaOnWeb } from './render-media-on-web';
|
|
7
11
|
export type { RenderMediaOnWebOptions, RenderMediaOnWebProgress, RenderMediaOnWebProgressCallback, RenderMediaOnWebResult, } from './render-media-on-web';
|
|
@@ -2,9 +2,14 @@ import type { Quality } from 'mediabunny';
|
|
|
2
2
|
import { type OutputFormat } from 'mediabunny';
|
|
3
3
|
export type WebRendererVideoCodec = 'h264' | 'h265' | 'vp8' | 'vp9' | 'av1';
|
|
4
4
|
export type WebRendererContainer = 'mp4' | 'webm';
|
|
5
|
+
export type WebRendererAudioCodec = 'aac' | 'opus';
|
|
5
6
|
export type WebRendererQuality = 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
6
7
|
export declare const codecToMediabunnyCodec: (codec: WebRendererVideoCodec) => "av1" | "avc" | "hevc" | "vp8" | "vp9";
|
|
7
8
|
export declare const containerToMediabunnyContainer: (container: WebRendererContainer) => OutputFormat;
|
|
8
9
|
export declare const getDefaultVideoCodecForContainer: (container: WebRendererContainer) => WebRendererVideoCodec;
|
|
9
10
|
export declare const getQualityForWebRendererQuality: (quality: WebRendererQuality) => Quality;
|
|
10
11
|
export declare const getMimeType: (container: WebRendererContainer) => string;
|
|
12
|
+
export declare const getDefaultAudioCodecForContainer: (container: WebRendererContainer) => WebRendererAudioCodec;
|
|
13
|
+
export declare const getSupportedVideoCodecsForContainer: (container: WebRendererContainer) => WebRendererVideoCodec[];
|
|
14
|
+
export declare const getSupportedAudioCodecsForContainer: (container: WebRendererContainer) => WebRendererAudioCodec[];
|
|
15
|
+
export declare const audioCodecToMediabunnyAudioCodec: (audioCodec: WebRendererAudioCodec) => "aac" | "alaw" | "flac" | "mp3" | "opus" | "pcm-f32" | "pcm-f32be" | "pcm-f64" | "pcm-f64be" | "pcm-s16" | "pcm-s16be" | "pcm-s24" | "pcm-s24be" | "pcm-s32" | "pcm-s32be" | "pcm-s8" | "pcm-u8" | "ulaw" | "vorbis";
|
|
@@ -3,7 +3,7 @@ import type { AnyZodObject, z } from 'zod';
|
|
|
3
3
|
import { type WebRendererOnArtifact } from './artifact';
|
|
4
4
|
import { type FrameRange } from './frame-range';
|
|
5
5
|
import type { InternalState } from './internal-state';
|
|
6
|
-
import type { WebRendererContainer, WebRendererQuality } from './mediabunny-mappings';
|
|
6
|
+
import type { WebRendererAudioCodec, WebRendererContainer, WebRendererQuality } from './mediabunny-mappings';
|
|
7
7
|
import { type WebRendererVideoCodec } from './mediabunny-mappings';
|
|
8
8
|
import type { WebRendererOutputTarget } from './output-target';
|
|
9
9
|
import type { CompositionCalculateMetadataOrExplicit } from './props-if-has-props';
|
|
@@ -35,6 +35,8 @@ type OptionalRenderMediaOnWebOptions<Schema extends AnyZodObject> = {
|
|
|
35
35
|
schema: Schema | undefined;
|
|
36
36
|
mediaCacheSizeInBytes: number | null;
|
|
37
37
|
videoCodec: WebRendererVideoCodec;
|
|
38
|
+
audioCodec: WebRendererAudioCodec | null;
|
|
39
|
+
audioBitrate: number | WebRendererQuality;
|
|
38
40
|
container: WebRendererContainer;
|
|
39
41
|
signal: AbortSignal | null;
|
|
40
42
|
onProgress: RenderMediaOnWebProgressCallback | null;
|
package/dist/renoun.d.ts
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/** Image format for encoded screenshot output. */
|
|
2
|
+
export type ImageFormat = 'png' | 'jpeg' | 'webp';
|
|
3
|
+
/** Options for rendering a screenshot to canvas. */
|
|
4
|
+
export interface RenderOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Canvas background color. Set to `null` (or omit) for a transparent canvas.
|
|
7
|
+
* When provided, the string is passed directly to `fillStyle`.
|
|
8
|
+
*/
|
|
9
|
+
backgroundColor?: string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Optional existing canvas to render into.
|
|
12
|
+
* When omitted, a new canvas element is created.
|
|
13
|
+
*/
|
|
14
|
+
canvas?: HTMLCanvasElement;
|
|
15
|
+
/**
|
|
16
|
+
* Rendering scale factor. Defaults to `window.devicePixelRatio` (or `1`).
|
|
17
|
+
*/
|
|
18
|
+
scale?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Crop origin X (CSS pixels) relative to the element's left edge.
|
|
21
|
+
* Defaults to the element's left edge.
|
|
22
|
+
*/
|
|
23
|
+
x?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Crop origin Y (CSS pixels) relative to the element's top edge.
|
|
26
|
+
* Defaults to the element's top edge.
|
|
27
|
+
*/
|
|
28
|
+
y?: number;
|
|
29
|
+
/**
|
|
30
|
+
* Output width in CSS pixels. Defaults to the element's width.
|
|
31
|
+
*/
|
|
32
|
+
width?: number;
|
|
33
|
+
/**
|
|
34
|
+
* Output height in CSS pixels. Defaults to the element's height.
|
|
35
|
+
*/
|
|
36
|
+
height?: number;
|
|
37
|
+
/**
|
|
38
|
+
* Controls how `position: fixed` elements outside the captured subtree are
|
|
39
|
+
* handled.
|
|
40
|
+
*
|
|
41
|
+
* - `none` – ignore all fixed elements outside `element`.
|
|
42
|
+
* - `intersecting` – include fixed elements whose bounding rect intersects the capture rect.
|
|
43
|
+
* - `all` – include all fixed elements that overlap the viewport.
|
|
44
|
+
*/
|
|
45
|
+
includeFixed?: 'none' | 'intersecting' | 'all';
|
|
46
|
+
}
|
|
47
|
+
/** Options for encoding a canvas to an image format. */
|
|
48
|
+
export interface EncodeOptions {
|
|
49
|
+
/**
|
|
50
|
+
* Image format to encode. Defaults to `'png'`.
|
|
51
|
+
*/
|
|
52
|
+
format?: ImageFormat;
|
|
53
|
+
/**
|
|
54
|
+
* Image quality for lossy formats (`jpeg`, `webp`). A number between `0` and `1`.
|
|
55
|
+
* Ignored for `png`. Defaults to `0.92`.
|
|
56
|
+
*/
|
|
57
|
+
quality?: number;
|
|
58
|
+
}
|
|
59
|
+
/** Combined options for one-shot screenshot methods that render and encode. */
|
|
60
|
+
export type ScreenshotOptions = RenderOptions & EncodeOptions;
|
|
61
|
+
/**
|
|
62
|
+
* A promise-like object representing a screenshot capture. The underlying
|
|
63
|
+
* render happens once; subsequent calls to `.canvas()`, `.blob()`, or `.url()`
|
|
64
|
+
* reuse the same rendered canvas.
|
|
65
|
+
*/
|
|
66
|
+
export interface ScreenshotTask extends Promise<HTMLCanvasElement> {
|
|
67
|
+
/** Returns the rendered canvas. */
|
|
68
|
+
canvas(): Promise<HTMLCanvasElement>;
|
|
69
|
+
/** Encodes the rendered canvas to a Blob. */
|
|
70
|
+
blob(options?: EncodeOptions): Promise<Blob>;
|
|
71
|
+
/**
|
|
72
|
+
* Encodes the rendered canvas to a Blob and creates an object URL.
|
|
73
|
+
* Remember to call `URL.revokeObjectURL(url)` when done to avoid memory leaks.
|
|
74
|
+
*/
|
|
75
|
+
url(options?: EncodeOptions): Promise<string>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Renders a DOM element into a canvas using modern browser features.
|
|
79
|
+
*
|
|
80
|
+
* Returns a `ScreenshotTask` that is both a Promise and provides methods
|
|
81
|
+
* to encode the rendered canvas. The underlying render happens once;
|
|
82
|
+
* subsequent calls to `.canvas()`, `.blob()`, or `.url()` reuse the same result.
|
|
83
|
+
*
|
|
84
|
+
* This implementation targets evergreen browsers only and assumes a real DOM +
|
|
85
|
+
* Canvas2D environment (not Node.js).
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* // Capture handle pattern - render once, encode multiple ways
|
|
89
|
+
* const shot = screenshot(element, { scale: 2 })
|
|
90
|
+
* const canvas = await shot.canvas()
|
|
91
|
+
* const pngBlob = await shot.blob({ format: 'png' })
|
|
92
|
+
* const webpUrl = await shot.url({ format: 'webp', quality: 0.9 })
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Direct await returns the canvas
|
|
96
|
+
* const canvas = await screenshot(element)
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* // One-shot convenience methods
|
|
100
|
+
* const canvas = await screenshot.canvas(element, { scale: 2 })
|
|
101
|
+
* const blob = await screenshot.blob(element, { format: 'jpeg', quality: 0.85 })
|
|
102
|
+
* const url = await screenshot.url(element, { format: 'png' })
|
|
103
|
+
*/
|
|
104
|
+
declare function screenshot(target: Element | string, options?: RenderOptions): ScreenshotTask;
|
|
105
|
+
declare namespace screenshot {
|
|
106
|
+
var canvas: (target: string | Element, options?: RenderOptions | undefined) => Promise<HTMLCanvasElement>;
|
|
107
|
+
}
|
|
108
|
+
declare namespace screenshot {
|
|
109
|
+
var blob: (target: string | Element, options?: ScreenshotOptions | undefined) => Promise<Blob>;
|
|
110
|
+
}
|
|
111
|
+
declare namespace screenshot {
|
|
112
|
+
var url: (target: string | Element, options?: ScreenshotOptions | undefined) => Promise<string>;
|
|
113
|
+
}
|
|
114
|
+
export { screenshot };
|
|
115
|
+
declare global {
|
|
116
|
+
interface CanvasRenderingContext2D {
|
|
117
|
+
_filterPolyfillValue?: string;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Quality } from 'mediabunny';
|
|
2
|
+
import type { CanRenderIssue } from './can-render-types';
|
|
3
|
+
import { type WebRendererAudioCodec, type WebRendererContainer } from './mediabunny-mappings';
|
|
4
|
+
export type ResolveAudioCodecResult = {
|
|
5
|
+
codec: WebRendererAudioCodec | null;
|
|
6
|
+
issues: CanRenderIssue[];
|
|
7
|
+
};
|
|
8
|
+
export declare const resolveAudioCodec: (options: {
|
|
9
|
+
container: WebRendererContainer;
|
|
10
|
+
requestedCodec: WebRendererAudioCodec | null | undefined;
|
|
11
|
+
userSpecifiedAudioCodec: boolean;
|
|
12
|
+
bitrate: number | Quality;
|
|
13
|
+
}) => Promise<ResolveAudioCodecResult>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CanRenderIssue } from './can-render-types';
|
|
2
|
+
import type { WebRendererVideoCodec } from './mediabunny-mappings';
|
|
3
|
+
export declare const validateDimensions: (options: {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
codec: WebRendererVideoCodec;
|
|
7
|
+
}) => CanRenderIssue | null;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/web-renderer"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/web-renderer",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.403",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"sideEffects": false,
|
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
"author": "Remotion <jonny@remotion.dev>",
|
|
19
19
|
"license": "UNLICENSED",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@remotion/licensing": "4.0.
|
|
22
|
-
"remotion": "4.0.
|
|
21
|
+
"@remotion/licensing": "4.0.403",
|
|
22
|
+
"remotion": "4.0.403",
|
|
23
23
|
"mediabunny": "1.27.3"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
27
|
-
"@remotion/player": "4.0.
|
|
28
|
-
"@remotion/media": "4.0.
|
|
26
|
+
"@remotion/eslint-config-internal": "4.0.403",
|
|
27
|
+
"@remotion/player": "4.0.403",
|
|
28
|
+
"@remotion/media": "4.0.403",
|
|
29
29
|
"@typescript/native-preview": "7.0.0-dev.20260105.1",
|
|
30
30
|
"@vitejs/plugin-react": "4.1.0",
|
|
31
31
|
"@vitest/browser-playwright": "4.0.9",
|