framefields 2.4.1 → 2.4.2
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/README.md +11 -33
- package/dist/audio/index.d.mts +1 -1
- package/dist/audio/index.mjs +1 -1
- package/dist/{audio-CPApYcWF.mjs → audio-Bb31xJuX.mjs} +2 -2
- package/dist/{audio-CPApYcWF.mjs.map → audio-Bb31xJuX.mjs.map} +1 -1
- package/dist/{dist-CrK3rmyN.mjs → dist-CxGfrigI.mjs} +43 -3
- package/dist/{dist-CrK3rmyN.mjs.map → dist-CxGfrigI.mjs.map} +1 -1
- package/dist/effects/index.mjs +1 -1
- package/dist/{effects-DxylPSuI.mjs → effects-BOk_2kzM.mjs} +2 -2
- package/dist/{effects-DxylPSuI.mjs.map → effects-BOk_2kzM.mjs.map} +1 -1
- package/dist/{index-C0o3lLyA.d.mts → index-B3-gwjK6.d.mts} +14 -2
- package/dist/index-B3-gwjK6.d.mts.map +1 -0
- package/dist/{index-BxARm93R.d.mts → index-BTPLbjt4.d.mts} +40 -11
- package/dist/index-BTPLbjt4.d.mts.map +1 -0
- package/dist/index.d.mts +7 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/dist/preview/index.d.mts +1 -1
- package/dist/preview/index.mjs +1 -1
- package/dist/{preview-D2dMmokw.mjs → preview-DyGw2b3_.mjs} +2 -2
- package/dist/{preview-D2dMmokw.mjs.map → preview-DyGw2b3_.mjs.map} +1 -1
- package/dist/preview-engine/audio.mjs +1 -1
- package/dist/preview-engine/{chunk-NTVDL3RS.mjs → chunk-AQNTIWTK.mjs} +1 -1
- package/dist/preview-engine/{chunk-5E5J4KT4.mjs → chunk-RHRMEBNK.mjs} +1 -1
- package/dist/preview-engine/chunk-VONDRBA2.mjs +1 -0
- package/dist/preview-engine/effects.mjs +1 -1
- package/dist/preview-engine/framefields.mjs +1 -1
- package/dist/preview-engine/player.mjs +1 -1
- package/dist/preview-engine/{renderers-U55KRIOV.mjs → renderers-EI6MQ2EL.mjs} +1 -1
- package/dist/preview-engine/signals.mjs +1 -1
- package/dist/renderer/index.d.mts +1 -1
- package/dist/renderer/index.mjs +1 -1
- package/dist/{renderer-Czxgaygb.mjs → renderer-BV48PFjX.mjs} +2 -2
- package/dist/{renderer-Czxgaygb.mjs.map → renderer-BV48PFjX.mjs.map} +1 -1
- package/dist/{renderer-CNb-DG00.mjs → renderer-CoWfz-9p.mjs} +373 -109
- package/dist/renderer-CoWfz-9p.mjs.map +1 -0
- package/dist/signals/index.mjs +1 -1
- package/package.json +57 -57
- package/dist/index-BxARm93R.d.mts.map +0 -1
- package/dist/index-C0o3lLyA.d.mts.map +0 -1
- package/dist/preview-engine/chunk-266DECPQ.mjs +0 -1
- package/dist/renderer-CNb-DG00.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -20,6 +20,16 @@
|
|
|
20
20
|
|
|
21
21
|
</div>
|
|
22
22
|
|
|
23
|
+
**Add to your agent**
|
|
24
|
+
|
|
25
|
+
Teach Claude Code, Cursor, Codex, Copilot, Hermes, and 70+ others how to author, animate, and render compositions:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx skills add gatewai-dev/framefields
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
23
33
|
Framefields is built for coding agents. It packs the capabilities usually split across three desktop creative suites—Photoshop-style compositing & VFX, After Effects-style typography & motion graphics, and Blender-style 3D scenes & cameras—into a single lightweight npm package.
|
|
24
34
|
|
|
25
35
|
- **Zero Headless-Browser Overhead** — No Chromium, no Puppeteer, no DOM reflows, and no screenshot pipeline. Renders directly on native GPU hardware via Dawn / WebGPU / Metal / Vulkan.
|
|
@@ -68,22 +78,6 @@ Every frame is rendered by framefields directly from TypeScript in [`examples/`]
|
|
|
68
78
|
|
|
69
79
|
---
|
|
70
80
|
|
|
71
|
-
## Agent Skills
|
|
72
|
-
|
|
73
|
-
Teach Claude Code, Cursor, Codex, Copilot, or Hermes how to author, animate, and render compositions:
|
|
74
|
-
|
|
75
|
-
**Claude Code**
|
|
76
|
-
```text
|
|
77
|
-
/plugin install framefields
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**Cursor, Codex, Hermes, Copilot & others**
|
|
81
|
-
```bash
|
|
82
|
-
npx skills add gatewai-dev/framefields
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
81
|
## Installation
|
|
88
82
|
|
|
89
83
|
```bash
|
|
@@ -167,23 +161,7 @@ process.exit(0);
|
|
|
167
161
|
|
|
168
162
|
## AI Gateway
|
|
169
163
|
|
|
170
|
-
Framefields
|
|
171
|
-
|
|
172
|
-
To get started, store your API key in `.env` and create a dedicated script (such as `src/generate.ts`) that calls `ai.subscribe()` to render media into `assets/`. Because AI generation is asynchronous and billed per execution, assets are generated once, saved locally, and tracked with Git LFS—ready to be loaded cleanly into `Layer.image()`, `Layer.video()`, or `Layer.audio()` inside your frame-accurate compositions without recurring cost or latency during previews and renders. Browse the full model catalog and schemas at [**framefields.dev/models**](https://framefields.dev/models).
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
import { ai } from "framefields";
|
|
176
|
-
|
|
177
|
-
// 1. Generate an image asset with Flux Schnell
|
|
178
|
-
const still = await ai.subscribe<{ images: { url: string }[] }>("flux/schnell", {
|
|
179
|
-
input: { prompt: "Cyberpunk alley in the rain, volumetric neon, 35mm", image_size: "landscape_16_9" },
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
// 2. Animate it into video with Kling or generate music & voiceovers
|
|
183
|
-
const clip = await ai.subscribe<{ video: { url: string } }>("kling-video/v2.1/standard/image-to-video", {
|
|
184
|
-
input: { prompt: "Slow forward tracking shot through neon rain", image_url: still.data.images[0].url, duration: "5" },
|
|
185
|
-
});
|
|
186
|
-
```
|
|
164
|
+
Framefields provides built-in access to the [**AI Gateway**](https://framefields.dev/models), allowing agents and developers to generate cinematic video, images, music, and voiceovers directly from code using hundreds of hosted models. Explore the full model catalog in the [**AI Gateway**](https://framefields.dev/models) or read the integration guide in the [**documentation**](https://framefields.dev/docs/guides/ai/).
|
|
187
165
|
|
|
188
166
|
---
|
|
189
167
|
|
package/dist/audio/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { N as WebGPUAudioProcessor } from "../index-DujpgUUq.mjs";
|
|
2
|
-
import { a as SfxTrigger, c as softLimit, d as _default$5, f as _default$4, g as mixAudioTracks, h as _default$2, i as SfxRenderContext, l as _default$7, m as _default$3, n as encodeStereoWav, o as mixSfxInto, p as _default, r as RenderedSfx, s as renderSfx, t as EncodeWavOptions, u as _default$6 } from "../index-
|
|
2
|
+
import { a as SfxTrigger, c as softLimit, d as _default$5, f as _default$4, g as mixAudioTracks, h as _default$2, i as SfxRenderContext, l as _default$7, m as _default$3, n as encodeStereoWav, o as mixSfxInto, p as _default, r as RenderedSfx, s as renderSfx, t as EncodeWavOptions, u as _default$6 } from "../index-B3-gwjK6.mjs";
|
|
3
3
|
import "../index-B1XcyMm8.mjs";
|
|
4
4
|
import { t as _default$1 } from "../renderer-CxqPeATd.mjs";
|
|
5
5
|
export { EncodeWavOptions, RenderedSfx, SfxRenderContext, SfxTrigger, WebGPUAudioProcessor, _default as audioFadeRenderer, _default$1 as audioSignalExtractorRenderer, _default$2 as compressorRenderer, _default$3 as delayRenderer, encodeStereoWav, mixAudioTracks, mixSfxInto, _default$4 as noiseGateRenderer, _default$5 as parametricEqRenderer, renderSfx, _default$6 as reverbRenderer, softLimit, _default$7 as stereoPanningRenderer };
|
package/dist/audio/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../chunk-GBe2k3y8.mjs";
|
|
2
2
|
import { g as WebGPUAudioProcessor } from "../dist-CspOG4V1.mjs";
|
|
3
3
|
import { t as renderers_default$1 } from "../renderers-CP8CFWDs-DzGXDs5p.mjs";
|
|
4
|
-
import { i as mixAudioTracks } from "../dist-
|
|
4
|
+
import { i as mixAudioTracks } from "../dist-CxGfrigI.mjs";
|
|
5
5
|
import { t as renderers_default$2 } from "../renderer-BMKFzfSQ.mjs";
|
|
6
6
|
import { t as renderers_default$3 } from "../renderer-D2-V9nQq.mjs";
|
|
7
7
|
import { t as renderers_default } from "../renderer-CzRqzp8P.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { xt as frameArraySignal } from "./dist-ClyC_d66.mjs";
|
|
2
2
|
import { A as ensureDevice, St as AudioSignalComputePipeline } from "./dist-CspOG4V1.mjs";
|
|
3
|
-
import { n as decodeAudioSource } from "./dist-
|
|
3
|
+
import { n as decodeAudioSource } from "./dist-CxGfrigI.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/signals/audio.ts
|
|
6
6
|
const AudioSignal = {
|
|
@@ -82,4 +82,4 @@ const AudioSignal = {
|
|
|
82
82
|
|
|
83
83
|
//#endregion
|
|
84
84
|
export { AudioSignal as t };
|
|
85
|
-
//# sourceMappingURL=audio-
|
|
85
|
+
//# sourceMappingURL=audio-Bb31xJuX.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-
|
|
1
|
+
{"version":3,"file":"audio-Bb31xJuX.mjs","names":[],"sources":["../src/signals/audio.ts"],"sourcesContent":["import { decodeAudioSource } from \"@framefields/compositions\";\nimport {\n\ttype FrameSignal,\n\tframeArraySignal,\n\ttype GPUTextureBinding,\n} from \"@framefields/core\";\nimport {\n\ttype AudioSignalComputeConfig,\n\tAudioSignalComputePipeline,\n\tensureDevice,\n} from \"@framefields/webgpu-renderers\";\n\nexport interface AudioSignalOptions extends AudioSignalComputeConfig {\n\tfps?: number;\n\ttargetWidth?: number;\n\tpreviewMode?: \"waveform\" | \"envelope\" | \"beat_markers\" | \"spectrum\";\n}\n\nexport interface ExtractedAudioSignalsBundle {\n\tprimary: FrameSignal<number>;\n\tbeat: FrameSignal<number>;\n\tbass: FrameSignal<number>;\n\tenergy: FrameSignal<number>;\n\tdurationSec: number;\n\tnumFrames: number;\n\tsampleRate: number;\n\ttextureView: unknown;\n\ttexture: unknown;\n\tprimaryBuffer: unknown;\n\tbeatBuffer: unknown;\n\tbassBuffer: unknown;\n\tenergyBuffer: unknown;\n\tseekFrame(frame: number): void;\n}\n\nexport const AudioSignal = {\n\tasync extractFromChannels(\n\t\tchannels: Float32Array[],\n\t\tsampleRate: number,\n\t\toptions: AudioSignalOptions = {},\n\t): Promise<ExtractedAudioSignalsBundle> {\n\t\tconst device = await ensureDevice();\n\t\tconst fps = options.fps ?? 24;\n\t\tconst targetWidth = options.targetWidth ?? 512;\n\n\t\tconst extracted = await AudioSignalComputePipeline.extractFeatures(\n\t\t\tdevice,\n\t\t\tchannels,\n\t\t\tsampleRate,\n\t\t\tfps,\n\t\t\toptions,\n\t\t\ttargetWidth,\n\t\t);\n\n\t\tconst samples = extracted.channelSamples ?? {\n\t\t\tprimary: new Float32Array(extracted.numFrames),\n\t\t\tbeat: new Float32Array(extracted.numFrames),\n\t\t\tbass: new Float32Array(extracted.numFrames),\n\t\t\tenergy: new Float32Array(extracted.numFrames),\n\t\t};\n\n\t\tconst primaryBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_primary\",\n\t\t\tchannel: \"primary\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.primaryBuffer,\n\t\t\tstats: extracted.stats.primary,\n\t\t};\n\t\tconst beatBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_beat\",\n\t\t\tchannel: \"beat\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.beatBuffer,\n\t\t\tstats: extracted.stats.beat,\n\t\t};\n\t\tconst bassBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_bass\",\n\t\t\tchannel: \"bass\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.bassBuffer,\n\t\t\tstats: extracted.stats.bass,\n\t\t};\n\t\tconst energyBinding: GPUTextureBinding = {\n\t\t\tnodeId: \"audio_energy\",\n\t\t\tchannel: \"energy\",\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tbuffer: extracted.energyBuffer,\n\t\t\tstats: extracted.stats.energy,\n\t\t};\n\n\t\tconst primary = frameArraySignal(samples.primary, fps, primaryBinding);\n\t\tconst beat = frameArraySignal(samples.beat, fps, beatBinding);\n\t\tconst bass = frameArraySignal(samples.bass, fps, bassBinding);\n\t\tconst energy = frameArraySignal(samples.energy, fps, energyBinding);\n\n\t\treturn {\n\t\t\tprimary,\n\t\t\tbeat,\n\t\t\tbass,\n\t\t\tenergy,\n\t\t\tdurationSec: extracted.durationSec,\n\t\t\tnumFrames: extracted.numFrames,\n\t\t\tsampleRate,\n\t\t\ttextureView: extracted.textureView,\n\t\t\ttexture: extracted.texture,\n\t\t\tprimaryBuffer: extracted.primaryBuffer,\n\t\t\tbeatBuffer: extracted.beatBuffer,\n\t\t\tbassBuffer: extracted.bassBuffer,\n\t\t\tenergyBuffer: extracted.energyBuffer,\n\t\t\tseekFrame(frame: number) {\n\t\t\t\tprimary.seekFrame?.(frame);\n\t\t\t\tbeat.seekFrame?.(frame);\n\t\t\t\tbass.seekFrame?.(frame);\n\t\t\t\tenergy.seekFrame?.(frame);\n\t\t\t},\n\t\t};\n\t},\n\n\tasync extract(\n\t\tsource: string,\n\t\toptions: AudioSignalOptions = {},\n\t): Promise<ExtractedAudioSignalsBundle> {\n\t\tconst decoded = await decodeAudioSource(source);\n\t\tif (!decoded || decoded.channels.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to decode audio source for feature extraction: ${source}`,\n\t\t\t);\n\t\t}\n\t\treturn AudioSignal.extractFromChannels(\n\t\t\tdecoded.channels,\n\t\t\tdecoded.sampleRate,\n\t\t\toptions,\n\t\t);\n\t},\n};\n"],"mappings":";;;;;AAmCA,MAAa,cAAc;CAC1B,MAAM,oBACL,UACA,YACA,UAA8B,EAAE,EACO;EACvC,MAAM,SAAS,MAAM,cAAc;EACnC,MAAM,MAAM,QAAQ,OAAO;EAC3B,MAAM,cAAc,QAAQ,eAAe;EAE3C,MAAM,YAAY,MAAM,2BAA2B,gBAClD,QACA,UACA,YACA,KACA,SACA,YACA;EAED,MAAM,UAAU,UAAU,kBAAkB;GAC3C,SAAS,IAAI,aAAa,UAAU,UAAU;GAC9C,MAAM,IAAI,aAAa,UAAU,UAAU;GAC3C,MAAM,IAAI,aAAa,UAAU,UAAU;GAC3C,QAAQ,IAAI,aAAa,UAAU,UAAU;GAC7C;EAED,MAAM,iBAAoC;GACzC,QAAQ;GACR,SAAS;GACT,aAAa,UAAU;GACvB,SAAS,UAAU;GACnB,QAAQ,UAAU;GAClB,OAAO,UAAU,MAAM;GACvB;EACD,MAAM,cAAiC;GACtC,QAAQ;GACR,SAAS;GACT,aAAa,UAAU;GACvB,SAAS,UAAU;GACnB,QAAQ,UAAU;GAClB,OAAO,UAAU,MAAM;GACvB;EACD,MAAM,cAAiC;GACtC,QAAQ;GACR,SAAS;GACT,aAAa,UAAU;GACvB,SAAS,UAAU;GACnB,QAAQ,UAAU;GAClB,OAAO,UAAU,MAAM;GACvB;EACD,MAAM,gBAAmC;GACxC,QAAQ;GACR,SAAS;GACT,aAAa,UAAU;GACvB,SAAS,UAAU;GACnB,QAAQ,UAAU;GAClB,OAAO,UAAU,MAAM;GACvB;EAED,MAAM,UAAU,iBAAiB,QAAQ,SAAS,KAAK,eAAe;EACtE,MAAM,OAAO,iBAAiB,QAAQ,MAAM,KAAK,YAAY;EAC7D,MAAM,OAAO,iBAAiB,QAAQ,MAAM,KAAK,YAAY;EAC7D,MAAM,SAAS,iBAAiB,QAAQ,QAAQ,KAAK,cAAc;AAEnE,SAAO;GACN;GACA;GACA;GACA;GACA,aAAa,UAAU;GACvB,WAAW,UAAU;GACrB;GACA,aAAa,UAAU;GACvB,SAAS,UAAU;GACnB,eAAe,UAAU;GACzB,YAAY,UAAU;GACtB,YAAY,UAAU;GACtB,cAAc,UAAU;GACxB,UAAU,OAAe;AACxB,YAAQ,YAAY,MAAM;AAC1B,SAAK,YAAY,MAAM;AACvB,SAAK,YAAY,MAAM;AACvB,WAAO,YAAY,MAAM;;GAE1B;;CAGF,MAAM,QACL,QACA,UAA8B,EAAE,EACO;EACvC,MAAM,UAAU,MAAM,kBAAkB,OAAO;AAC/C,MAAI,CAAC,WAAW,QAAQ,SAAS,WAAW,EAC3C,OAAM,IAAI,MACT,yDAAyD,SACzD;AAEF,SAAO,YAAY,oBAClB,QAAQ,UACR,QAAQ,YACR,QACA;;CAEF"}
|
|
@@ -1293,11 +1293,24 @@ var MixBus = class {
|
|
|
1293
1293
|
for (let c = 0; c < 2; c++) addInto(dest[c], src[c], start);
|
|
1294
1294
|
}
|
|
1295
1295
|
};
|
|
1296
|
+
/** A clip's file name for progress, without paths or signed-URL queries. */
|
|
1297
|
+
function sourceLabel(url) {
|
|
1298
|
+
if (url.startsWith("data:")) return "inline audio";
|
|
1299
|
+
const name = url.split(/[?#]/)[0].split(/[\\/]/).pop();
|
|
1300
|
+
return name ? decodeURIComponentSafe(name) : "audio";
|
|
1301
|
+
}
|
|
1302
|
+
function decodeURIComponentSafe(s) {
|
|
1303
|
+
try {
|
|
1304
|
+
return decodeURIComponent(s);
|
|
1305
|
+
} catch {
|
|
1306
|
+
return s;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1296
1309
|
/**
|
|
1297
1310
|
* Recursively parses the VirtualMediaData tree and mixes all active audio tracks
|
|
1298
1311
|
* into a single unified stereo PCM stream (Float32Array channels).
|
|
1299
1312
|
*/
|
|
1300
|
-
async function mixAudioTracks(virtualMedia, fps, targetSampleRate = 48e3, device, renderId) {
|
|
1313
|
+
async function mixAudioTracks(virtualMedia, fps, targetSampleRate = 48e3, device, renderId, options = {}) {
|
|
1301
1314
|
mediaLogger.debug(`[AudioExtractor] mixAudioTracks started. FPS: ${fps}, targetSampleRate: ${targetSampleRate}`);
|
|
1302
1315
|
await waitForDelayRender();
|
|
1303
1316
|
shaderStore.registerSignalsFromComposition(renderId, virtualMedia);
|
|
@@ -1414,6 +1427,14 @@ async function mixAudioTracks(virtualMedia, fps, targetSampleRate = 48e3, device
|
|
|
1414
1427
|
}
|
|
1415
1428
|
await yieldToMain();
|
|
1416
1429
|
}
|
|
1430
|
+
if (mediaType === "Audio" || mediaType === "Video") {
|
|
1431
|
+
clipsDone++;
|
|
1432
|
+
options.onProgress?.({
|
|
1433
|
+
done: clipsDone,
|
|
1434
|
+
total: clipsTotal,
|
|
1435
|
+
...params.sourceUrl && { source: sourceLabel(params.sourceUrl) }
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1417
1438
|
}
|
|
1418
1439
|
if (node.children) for (const child of node.children) {
|
|
1419
1440
|
const childChannels = await traverse(child, totalSeekSec, totalClockFrames, volume, speedMultiplier, actualDurationFrames);
|
|
@@ -1451,7 +1472,26 @@ async function mixAudioTracks(virtualMedia, fps, targetSampleRate = 48e3, device
|
|
|
1451
1472
|
} else await processSegment(null, 0);
|
|
1452
1473
|
return bus.channels;
|
|
1453
1474
|
}
|
|
1454
|
-
const
|
|
1475
|
+
const normalized = normalizeTimeline(virtualMedia, fps);
|
|
1476
|
+
let clipsTotal = 0;
|
|
1477
|
+
let clipsDone = 0;
|
|
1478
|
+
if (options.onProgress) {
|
|
1479
|
+
const count = (node) => {
|
|
1480
|
+
if (!node) return;
|
|
1481
|
+
const op = node.operation;
|
|
1482
|
+
if (op?.op === "source") {
|
|
1483
|
+
const mediaType = getMediaType(node);
|
|
1484
|
+
if (mediaType === "Audio" || mediaType === "Video") clipsTotal += Math.max(1, op.timeline?.segments?.length ?? 0);
|
|
1485
|
+
}
|
|
1486
|
+
for (const child of node.children ?? []) count(child);
|
|
1487
|
+
};
|
|
1488
|
+
count(normalized);
|
|
1489
|
+
options.onProgress({
|
|
1490
|
+
done: 0,
|
|
1491
|
+
total: clipsTotal
|
|
1492
|
+
});
|
|
1493
|
+
}
|
|
1494
|
+
const rootChannels = await traverse(normalized, 0, 0, 1, 1, null);
|
|
1455
1495
|
const mixedChannels = rootChannels?.every((ch) => ch.length === totalTargetSamples) && rootChannels[0] !== rootChannels[1] ? rootChannels : [new Float32Array(totalTargetSamples), new Float32Array(totalTargetSamples)];
|
|
1456
1496
|
const [outputLeft, outputRight] = mixedChannels;
|
|
1457
1497
|
if (rootChannels && mixedChannels !== rootChannels) for (let c = 0; c < 2; c++) {
|
|
@@ -1483,4 +1523,4 @@ async function mixAudioTracks(virtualMedia, fps, targetSampleRate = 48e3, device
|
|
|
1483
1523
|
|
|
1484
1524
|
//#endregion
|
|
1485
1525
|
export { spring as _, resolveLayerDuration as a, computeStrokeRect as c, measureSpring as d, measureText as f, requiresIsolation as g, preloadFont as h, mixAudioTracks as i, interpolate as l, preloadCompositionFonts as m, decodeAudioSource as n, Easing as o, measureTextAsync as p, drawCompositionTree as r, bezier as s, compositionStateStore as t, mapBlendModeToSkia as u, springCalculation as v };
|
|
1486
|
-
//# sourceMappingURL=dist-
|
|
1526
|
+
//# sourceMappingURL=dist-CxGfrigI.mjs.map
|