pixi-effects 0.47.5 → 0.48.0
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/CHANGELOG.md +8 -0
- package/README.md +8 -6
- package/ai/chat-template.html +3 -3
- package/dist/Controller.cjs +3 -0
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.js +3 -0
- package/dist/Controller.js.map +1 -1
- package/dist/{chunk-LHUIEFMH.js → chunk-GX2WQV4A.js} +43 -33
- package/dist/chunk-GX2WQV4A.js.map +1 -0
- package/dist/chunk-K3XOEC3C.js +53 -0
- package/dist/chunk-K3XOEC3C.js.map +1 -0
- package/dist/{chunk-2AT5WSSV.cjs → chunk-NGK4E536.cjs} +47 -37
- package/dist/chunk-NGK4E536.cjs.map +1 -0
- package/dist/chunk-VQXZ2NOI.cjs +56 -0
- package/dist/chunk-VQXZ2NOI.cjs.map +1 -0
- package/dist/index.cjs +30 -25
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +2 -1
- package/dist/loader.css +1 -1
- package/dist/present.cjs +2 -1
- package/dist/present.cjs.map +1 -1
- package/dist/present.js +2 -1
- package/dist/present.js.map +1 -1
- package/docs/api.md +15 -0
- package/llms-full.txt +16 -1
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/template.html +6 -6
- package/dist/chunk-2AT5WSSV.cjs.map +0 -1
- package/dist/chunk-LHUIEFMH.js.map +0 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/core/mediabunny.ts
|
|
2
|
+
var source = null;
|
|
3
|
+
var pending = null;
|
|
4
|
+
function useMediabunny(from) {
|
|
5
|
+
if (from == null || typeof from !== "string" && typeof from !== "function" && typeof from !== "object") {
|
|
6
|
+
throw new TypeError(`pixi-effects: useMediabunny() takes the mediabunny module, a URL or a function that returns the module; it got ${String(from)}`);
|
|
7
|
+
}
|
|
8
|
+
source = from;
|
|
9
|
+
pending = null;
|
|
10
|
+
}
|
|
11
|
+
function loadMediabunny() {
|
|
12
|
+
if (!pending) {
|
|
13
|
+
const from = source;
|
|
14
|
+
const p = fetchModule(from).then(
|
|
15
|
+
(mod) => {
|
|
16
|
+
if (!mod || typeof mod.Output !== "function") {
|
|
17
|
+
throw new Error(`pixi-effects: ${describe(from)} did not give the mediabunny module (no Output in it). ${HOW}`);
|
|
18
|
+
}
|
|
19
|
+
return mod;
|
|
20
|
+
},
|
|
21
|
+
(err) => {
|
|
22
|
+
const why = err instanceof Error ? err.message : String(err);
|
|
23
|
+
throw new Error(`pixi-effects: could not load mediabunny from ${describe(from)} (${why}). ${HOW}`, { cause: err });
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
pending = p;
|
|
27
|
+
p.catch(() => {
|
|
28
|
+
if (pending === p) pending = null;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return pending;
|
|
32
|
+
}
|
|
33
|
+
var HOW = 'mediabunny is needed to export (movie.render(), the download button) and for a video layer; playing needs nothing. Add it to the import map ("mediabunny": "https://cdn.jsdelivr.net/npm/mediabunny@1/+esm"), install it next to pixi-effects, or call useMediabunny(module | url | () => import(...)) before you export.';
|
|
34
|
+
function fetchModule(from) {
|
|
35
|
+
if (from === null) return import('mediabunny');
|
|
36
|
+
if (typeof from === "string") return import(
|
|
37
|
+
/* @vite-ignore */
|
|
38
|
+
/* webpackIgnore: true */
|
|
39
|
+
from
|
|
40
|
+
);
|
|
41
|
+
if (typeof from === "function") return Promise.resolve().then(from);
|
|
42
|
+
return Promise.resolve(from);
|
|
43
|
+
}
|
|
44
|
+
function describe(from) {
|
|
45
|
+
if (from === null) return "'mediabunny' (the bare name: an import map or a bundler resolves it)";
|
|
46
|
+
if (typeof from === "string") return from;
|
|
47
|
+
if (typeof from === "function") return "the function given to useMediabunny()";
|
|
48
|
+
return "the object given to useMediabunny()";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { loadMediabunny, useMediabunny };
|
|
52
|
+
//# sourceMappingURL=chunk-K3XOEC3C.js.map
|
|
53
|
+
//# sourceMappingURL=chunk-K3XOEC3C.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/mediabunny.ts"],"names":[],"mappings":";AAeA,IAAI,MAAA,GAAkC,IAAA;AACtC,IAAI,OAAA,GAA4C,IAAA;AAOzC,SAAS,cAAc,IAAA,EAA8B;AAC1D,EAAA,IAAI,IAAA,IAAQ,IAAA,IAAS,OAAO,IAAA,KAAS,QAAA,IAAY,OAAO,IAAA,KAAS,UAAA,IAAc,OAAO,IAAA,KAAS,QAAA,EAAW;AACxG,IAAA,MAAM,IAAI,SAAA,CAAU,CAAA,+GAAA,EAAkH,MAAA,CAAO,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EACtJ;AACA,EAAA,MAAA,GAAS,IAAA;AACT,EAAA,OAAA,GAAU,IAAA;AACZ;AAGO,SAAS,cAAA,GAA4C;AAC1D,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAA,GAAO,MAAA;AACb,IAAA,MAAM,CAAA,GAAI,WAAA,CAAY,IAAI,CAAA,CAAE,IAAA;AAAA,MAC1B,CAAC,GAAA,KAAQ;AACP,QAAA,IAAI,CAAC,GAAA,IAAO,OAAQ,GAAA,CAA6B,WAAW,UAAA,EAAY;AACtE,UAAA,MAAM,IAAI,MAAM,CAAA,cAAA,EAAiB,QAAA,CAAS,IAAI,CAAC,CAAA,uDAAA,EAA0D,GAAG,CAAA,CAAE,CAAA;AAAA,QAChH;AACA,QAAA,OAAO,GAAA;AAAA,MACT,CAAA;AAAA,MACA,CAAC,GAAA,KAAiB;AAChB,QAAA,MAAM,MAAM,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC3D,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6CAAA,EAAgD,QAAA,CAAS,IAAI,CAAC,CAAA,EAAA,EAAK,GAAG,CAAA,GAAA,EAAM,GAAG,CAAA,CAAA,EAAI,EAAE,KAAA,EAAO,KAAK,CAAA;AAAA,MACnH;AAAA,KACF;AACA,IAAA,OAAA,GAAU,CAAA;AACV,IAAA,CAAA,CAAE,MAAM,MAAM;AAAE,MAAA,IAAI,OAAA,KAAY,GAAG,OAAA,GAAU,IAAA;AAAA,IAAM,CAAC,CAAA;AAAA,EACtD;AACA,EAAA,OAAO,OAAA;AACT;AAEA,IAAM,GAAA,GAAM,2TAAA;AAIZ,SAAS,YAAY,IAAA,EAA0D;AAC7E,EAAA,IAAI,IAAA,KAAS,IAAA,EAAM,OAAO,OAAO,YAAY,CAAA;AAC7C,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO;AAAA;AAAA;AAAA,IAAoD;AAAA,GAAA;AACzF,EAAA,IAAI,OAAO,SAAS,UAAA,EAAY,OAAO,QAAQ,OAAA,EAAQ,CAAE,KAAK,IAAI,CAAA;AAClE,EAAA,OAAO,OAAA,CAAQ,QAAQ,IAAI,CAAA;AAC7B;AAEA,SAAS,SAAS,IAAA,EAAuC;AACvD,EAAA,IAAI,IAAA,KAAS,MAAM,OAAO,sEAAA;AAC1B,EAAA,IAAI,OAAO,IAAA,KAAS,QAAA,EAAU,OAAO,IAAA;AACrC,EAAA,IAAI,OAAO,IAAA,KAAS,UAAA,EAAY,OAAO,uCAAA;AACvC,EAAA,OAAO,qCAAA;AACT","file":"chunk-K3XOEC3C.js","sourcesContent":["// mediabunny (about 180 KB gzipped) is what writes a video file and decodes a `video` layer. A page that only plays never needs it, so it is\n// fetched the first time something asks for it: `movie.render()`, a video asset. Nothing imports it at the top of a module.\nimport type * as Mediabunny from 'mediabunny';\n\n/** The mediabunny module, as `import * as mb from 'mediabunny'` gives it. */\nexport type MediabunnyModule = typeof Mediabunny;\n\n/**\n * Where mediabunny comes from, for {@link useMediabunny}:\n * - the module itself (`import * as mb from 'mediabunny'`: it is ready, nothing is fetched),\n * - a URL to `import()` (a page with no import map entry for it),\n * - a function that returns the module (`() => import('mediabunny')`, your own copy, a bundler chunk).\n */\nexport type MediabunnySource = MediabunnyModule | string | (() => Promise<MediabunnyModule>);\n\nlet source: MediabunnySource | null = null;\nlet pending: Promise<MediabunnyModule> | null = null;\n\n/**\n * Says where mediabunny comes from. Without it, the bare name `'mediabunny'` is imported the first time it is needed, which your bundler or the\n * page's import map resolves. A page that only plays (no export, no `video` layer) needs neither this nor an import map entry for it.\n * Calling it again replaces the source for the next load; a module that was already loaded stays in use by what holds it.\n */\nexport function useMediabunny(from: MediabunnySource): void {\n if (from == null || (typeof from !== 'string' && typeof from !== 'function' && typeof from !== 'object')) {\n throw new TypeError(`pixi-effects: useMediabunny() takes the mediabunny module, a URL or a function that returns the module; it got ${String(from)}`);\n }\n source = from;\n pending = null;\n}\n\n/** The mediabunny module, fetched once (the first call starts it; later calls share it). A failed load is tried again on the next call. */\nexport function loadMediabunny(): Promise<MediabunnyModule> {\n if (!pending) {\n const from = source;\n const p = fetchModule(from).then(\n (mod) => {\n if (!mod || typeof (mod as { Output?: unknown }).Output !== 'function') {\n throw new Error(`pixi-effects: ${describe(from)} did not give the mediabunny module (no Output in it). ${HOW}`);\n }\n return mod;\n },\n (err: unknown) => {\n const why = err instanceof Error ? err.message : String(err);\n throw new Error(`pixi-effects: could not load mediabunny from ${describe(from)} (${why}). ${HOW}`, { cause: err });\n },\n );\n pending = p;\n p.catch(() => { if (pending === p) pending = null; }); // the next call tries again (a network blip, an import map added later)\n }\n return pending;\n}\n\nconst HOW = 'mediabunny is needed to export (movie.render(), the download button) and for a video layer; playing needs nothing. '\n + 'Add it to the import map (\"mediabunny\": \"https://cdn.jsdelivr.net/npm/mediabunny@1/+esm\"), install it next to pixi-effects, '\n + 'or call useMediabunny(module | url | () => import(...)) before you export.';\n\nfunction fetchModule(from: MediabunnySource | null): Promise<MediabunnyModule> {\n if (from === null) return import('mediabunny');\n if (typeof from === 'string') return import(/* @vite-ignore */ /* webpackIgnore: true */ from) as Promise<MediabunnyModule>;\n if (typeof from === 'function') return Promise.resolve().then(from);\n return Promise.resolve(from);\n}\n\nfunction describe(from: MediabunnySource | null): string {\n if (from === null) return \"'mediabunny' (the bare name: an import map or a bundler resolves it)\";\n if (typeof from === 'string') return from;\n if (typeof from === 'function') return 'the function given to useMediabunny()';\n return 'the object given to useMediabunny()';\n}\n"]}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var chunkOGLRSR6C_cjs = require('./chunk-OGLRSR6C.cjs');
|
|
4
|
+
var chunkVQXZ2NOI_cjs = require('./chunk-VQXZ2NOI.cjs');
|
|
4
5
|
var chunkECLBZV4N_cjs = require('./chunk-ECLBZV4N.cjs');
|
|
5
6
|
var chunkZAHCGFGC_cjs = require('./chunk-ZAHCGFGC.cjs');
|
|
6
7
|
var chunkWYR2AU4W_cjs = require('./chunk-WYR2AU4W.cjs');
|
|
7
8
|
var chunkNGJXVJB7_cjs = require('./chunk-NGJXVJB7.cjs');
|
|
8
9
|
var chunkDOLTCXCL_cjs = require('./chunk-DOLTCXCL.cjs');
|
|
9
10
|
var pixi_js = require('pixi.js');
|
|
10
|
-
var mediabunny = require('mediabunny');
|
|
11
11
|
|
|
12
12
|
// src/core/gpuShare.ts
|
|
13
13
|
function sharedGpuOf(renderer) {
|
|
@@ -43,8 +43,9 @@ function ensureLoadersRegistered(audioContext) {
|
|
|
43
43
|
extension: { type: pixi_js.ExtensionType.LoadParser, name: "pixi-effects-video", priority: 1 },
|
|
44
44
|
test: (url) => /\.(mp4|webm|mov|mkv)$/i.test(url),
|
|
45
45
|
async load(url) {
|
|
46
|
-
const blob = await fetch(url).then((r) => r.blob());
|
|
47
|
-
const
|
|
46
|
+
const [M, blob] = await Promise.all([chunkVQXZ2NOI_cjs.loadMediabunny(), fetch(url).then((r) => r.blob())]);
|
|
47
|
+
const { Input, BlobSource, ALL_FORMATS, Output, WavOutputFormat, BufferTarget, Conversion, VideoSampleSink } = M;
|
|
48
|
+
const input = new Input({ source: new BlobSource(blob), formats: ALL_FORMATS });
|
|
48
49
|
const videoTrack = await input.getPrimaryVideoTrack();
|
|
49
50
|
if (!videoTrack || !await videoTrack.canDecode()) {
|
|
50
51
|
throw new Error("pixi-effects: video track cannot be decoded");
|
|
@@ -55,8 +56,8 @@ function ensureLoadersRegistered(audioContext) {
|
|
|
55
56
|
let audioBuffer = null;
|
|
56
57
|
if (audioTrack) {
|
|
57
58
|
try {
|
|
58
|
-
const out = new
|
|
59
|
-
const conv = await
|
|
59
|
+
const out = new Output({ format: new WavOutputFormat(), target: new BufferTarget() });
|
|
60
|
+
const conv = await Conversion.init({ input, output: out, video: { discard: true } });
|
|
60
61
|
await conv.execute();
|
|
61
62
|
audioBuffer = await audioContext.decodeAudioData(out.target.buffer);
|
|
62
63
|
} catch (e) {
|
|
@@ -69,7 +70,7 @@ function ensureLoadersRegistered(audioContext) {
|
|
|
69
70
|
videoDuration,
|
|
70
71
|
audioDuration,
|
|
71
72
|
duration: Math.max(videoDuration, audioDuration),
|
|
72
|
-
sink: new
|
|
73
|
+
sink: new VideoSampleSink(videoTrack)
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
});
|
|
@@ -600,10 +601,10 @@ var AUDIO_PREFERENCE = {
|
|
|
600
601
|
mkv: ["opus", "vorbis", "aac", "flac", "mp3"],
|
|
601
602
|
ogg: ["opus", "vorbis", "flac"]
|
|
602
603
|
};
|
|
603
|
-
async function chooseAudioCodec(fmt, requested, container, audio, bitrate) {
|
|
604
|
+
async function chooseAudioCodec(M, fmt, requested, container, audio, bitrate) {
|
|
604
605
|
const supported = container.getSupportedAudioCodecs?.();
|
|
605
606
|
const preferred = AUDIO_PREFERENCE[fmt].filter((c) => !supported || supported.includes(c));
|
|
606
|
-
const canEncode = (list) =>
|
|
607
|
+
const canEncode = (list) => M.getFirstEncodableAudioCodec(list, { numberOfChannels: audio.numberOfChannels ?? 2, sampleRate: audio.sampleRate, bitrate });
|
|
607
608
|
if (requested) {
|
|
608
609
|
if (await canEncode([requested])) return requested;
|
|
609
610
|
const alt = await canEncode(preferred.filter((c) => c !== requested));
|
|
@@ -616,27 +617,34 @@ async function chooseAudioCodec(fmt, requested, container, audio, bitrate) {
|
|
|
616
617
|
}
|
|
617
618
|
return chosen;
|
|
618
619
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
620
|
+
function qualityOf(M, name) {
|
|
621
|
+
switch (name) {
|
|
622
|
+
case "very-low":
|
|
623
|
+
return M.QUALITY_VERY_LOW;
|
|
624
|
+
case "low":
|
|
625
|
+
return M.QUALITY_LOW;
|
|
626
|
+
case "medium":
|
|
627
|
+
return M.QUALITY_MEDIUM;
|
|
628
|
+
case "very-high":
|
|
629
|
+
return M.QUALITY_VERY_HIGH;
|
|
630
|
+
default:
|
|
631
|
+
return M.QUALITY_HIGH;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function bitrateOf(M, v) {
|
|
627
635
|
const b = parseBitrate(v);
|
|
628
|
-
return b.bps ?? (
|
|
636
|
+
return b.bps ?? qualityOf(M, b.quality ?? "high");
|
|
629
637
|
}
|
|
630
|
-
function makeOutputFormat(name) {
|
|
638
|
+
function makeOutputFormat(M, name) {
|
|
631
639
|
switch (name) {
|
|
632
640
|
case "mp4":
|
|
633
|
-
return new
|
|
641
|
+
return new M.Mp4OutputFormat({ fastStart: "in-memory" });
|
|
634
642
|
case "mov":
|
|
635
|
-
return new
|
|
643
|
+
return new M.MovOutputFormat({ fastStart: "in-memory" });
|
|
636
644
|
case "webm":
|
|
637
|
-
return new
|
|
645
|
+
return new M.WebMOutputFormat();
|
|
638
646
|
case "mkv":
|
|
639
|
-
return new
|
|
647
|
+
return new M.MkvOutputFormat();
|
|
640
648
|
}
|
|
641
649
|
}
|
|
642
650
|
function sliceAudio(buffer, fromSec, toSec, fadeIn, fadeOut) {
|
|
@@ -651,18 +659,19 @@ async function exportAudioOnly(movie, options, fmt, range2) {
|
|
|
651
659
|
throw new Error(`pixi-effects: render({ format: '${fmt}' }): this movie has no sound to export (add an audio layer, an sfx or a music score); for the picture use mp4, webm, mov or mkv`);
|
|
652
660
|
}
|
|
653
661
|
if (options.video) console.warn(`pixi-effects: render({ format: '${fmt}' }): video options are ignored, only the sound is written`);
|
|
662
|
+
const M = await chunkVQXZ2NOI_cjs.loadMediabunny();
|
|
654
663
|
const audio = range2.partial ? sliceAudio(movie.audioBuffer, range2.fromSec, range2.toSec, range2.fromFrame > 0, range2.toFrame < movie.totalFrames) : movie.audioBuffer;
|
|
655
|
-
const container = fmt === "wav" ? new
|
|
664
|
+
const container = fmt === "wav" ? new M.WavOutputFormat() : new M.OggOutputFormat();
|
|
656
665
|
let codec;
|
|
657
666
|
if (fmt === "wav") {
|
|
658
667
|
codec = options.audio?.codec ?? "pcm-s16";
|
|
659
668
|
const held = container.getSupportedAudioCodecs();
|
|
660
669
|
if (!held.includes(codec)) throw new Error(`pixi-effects: render({ format: 'wav', audio: { codec: "${codec}" } }): wav holds ${held.join(", ")} (the usual is pcm-s16)`);
|
|
661
670
|
} else {
|
|
662
|
-
codec = await chooseAudioCodec("ogg", options.audio?.codec, container, audio, bitrateOf(options.audio?.bitrate
|
|
671
|
+
codec = await chooseAudioCodec(M, "ogg", options.audio?.codec, container, audio, bitrateOf(M, options.audio?.bitrate));
|
|
663
672
|
}
|
|
664
|
-
const output = new
|
|
665
|
-
const source = new
|
|
673
|
+
const output = new M.Output({ format: container, target: new M.BufferTarget() });
|
|
674
|
+
const source = new M.AudioBufferSource({ codec, ...fmt === "wav" ? {} : { bitrate: bitrateOf(M, options.audio?.bitrate) } });
|
|
666
675
|
output.addAudioTrack(source);
|
|
667
676
|
movie.emit("progress", { progress: 0, frame: range2.fromFrame, totalFrames: movie.totalFrames });
|
|
668
677
|
await output.start();
|
|
@@ -680,21 +689,22 @@ async function exportFrames(movie, options = {}) {
|
|
|
680
689
|
if (!["mp4", "mov", "webm", "mkv"].includes(fmt)) throw new Error(`pixi-effects: render({ format: "${String(fmt)}" }): use mp4, mov, webm, mkv (a picture) or wav, ogg (only the sound)`);
|
|
681
690
|
chunkDOLTCXCL_cjs.warnUnknownOptions("movie.render({ video })", options.video, ["codec", "bitrate", "hardware", "keyFrameInterval"]);
|
|
682
691
|
chunkDOLTCXCL_cjs.warnUnknownOptions("movie.render({ audio })", options.audio, ["codec", "bitrate"]);
|
|
683
|
-
const
|
|
692
|
+
const M = await chunkVQXZ2NOI_cjs.loadMediabunny();
|
|
693
|
+
const videoBitrate = bitrateOf(M, eff.bitrate ?? "high");
|
|
684
694
|
const opts = {
|
|
685
695
|
format: fmt,
|
|
686
696
|
video: { codec: "", bitrate: videoBitrate },
|
|
687
697
|
audio: {
|
|
688
698
|
codec: options.audio?.codec ?? (fmt === "mp4" || fmt === "mov" ? "aac" : "opus"),
|
|
689
|
-
bitrate: bitrateOf(options.audio?.bitrate
|
|
699
|
+
bitrate: bitrateOf(M, options.audio?.bitrate)
|
|
690
700
|
}
|
|
691
701
|
};
|
|
692
|
-
const container = makeOutputFormat(opts.format);
|
|
702
|
+
const container = makeOutputFormat(M, opts.format);
|
|
693
703
|
const audio = movie.audioBuffer && range2.partial ? sliceAudio(movie.audioBuffer, range2.fromSec, range2.toSec, range2.fromFrame > 0, range2.toFrame < movie.totalFrames) : movie.audioBuffer;
|
|
694
|
-
if (audio) opts.audio.codec = await chooseAudioCodec(fmt, options.audio?.codec, container, audio, opts.audio.bitrate);
|
|
695
|
-
const output = new
|
|
704
|
+
if (audio) opts.audio.codec = await chooseAudioCodec(M, fmt, options.audio?.codec, container, audio, opts.audio.bitrate);
|
|
705
|
+
const output = new M.Output({
|
|
696
706
|
format: container,
|
|
697
|
-
target: new
|
|
707
|
+
target: new M.BufferTarget()
|
|
698
708
|
});
|
|
699
709
|
const mb = eff.motionBlur !== void 0 ? resolveMotionBlur(eff.motionBlur, "movie.render()") : movie.motionBlur ?? null;
|
|
700
710
|
const stage = movie.app.canvas;
|
|
@@ -706,7 +716,7 @@ async function exportFrames(movie, options = {}) {
|
|
|
706
716
|
fmt,
|
|
707
717
|
requested: options.video?.codec,
|
|
708
718
|
supported: container.getSupportedVideoCodecs(),
|
|
709
|
-
canEncode: (c) =>
|
|
719
|
+
canEncode: (c) => M.canEncodeVideo(c, { width: picture.width, height: picture.height, bitrate: opts.video.bitrate })
|
|
710
720
|
});
|
|
711
721
|
if (chosen.fellBackFrom) console.warn(`pixi-effects: this browser cannot encode ${chosen.fellBackFrom.toUpperCase()} video, so the ${fmt} carries ${chosen.codec.toUpperCase()} instead (name a codec with render({ video: { codec } }) to choose yourself).`);
|
|
712
722
|
opts.video.codec = chosen.codec;
|
|
@@ -714,14 +724,14 @@ async function exportFrames(movie, options = {}) {
|
|
|
714
724
|
if (hardware !== void 0 && !["no-preference", "prefer-hardware", "prefer-software"].includes(hardware)) {
|
|
715
725
|
throw new Error(`pixi-effects: render({ video: { hardware: "${String(hardware)}" } }): use 'prefer-hardware', 'prefer-software' or 'no-preference'`);
|
|
716
726
|
}
|
|
717
|
-
const canvasSource = new
|
|
727
|
+
const canvasSource = new M.CanvasSource(picture, {
|
|
718
728
|
codec: opts.video.codec,
|
|
719
729
|
bitrate: opts.video.bitrate,
|
|
720
730
|
...hardware ? { hardwareAcceleration: hardware } : {}
|
|
721
731
|
});
|
|
722
732
|
output.addVideoTrack(canvasSource, { frameRate: movie.frameRate });
|
|
723
733
|
if (audio) {
|
|
724
|
-
const audioSource = new
|
|
734
|
+
const audioSource = new M.AudioBufferSource({
|
|
725
735
|
codec: opts.audio.codec,
|
|
726
736
|
bitrate: opts.audio.bitrate
|
|
727
737
|
}, { startTimestamp: opts.audio.codec === "aac" ? -2112 / audio.sampleRate : 0 });
|
|
@@ -5038,5 +5048,5 @@ exports.splitText = splitText;
|
|
|
5038
5048
|
exports.stagger = stagger;
|
|
5039
5049
|
exports.wiggle = wiggle;
|
|
5040
5050
|
exports.withFade = withFade;
|
|
5041
|
-
//# sourceMappingURL=chunk-
|
|
5042
|
-
//# sourceMappingURL=chunk-
|
|
5051
|
+
//# sourceMappingURL=chunk-NGK4E536.cjs.map
|
|
5052
|
+
//# sourceMappingURL=chunk-NGK4E536.cjs.map
|