@pixerate/flair 0.28.0 → 0.29.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 +13 -0
- package/README.md +48 -6
- package/dist/catalog/index.d.ts +11 -6
- package/dist/catalog/index.js +1 -1
- package/dist/{chunk-4LKAPRFM.js → chunk-6GFOLHCT.js} +920 -34
- package/dist/chunk-6GFOLHCT.js.map +1 -0
- package/dist/{chunk-JL6TI6II.js → chunk-7KYQ4R76.js} +2 -2
- package/dist/chunk-7KYQ4R76.js.map +1 -0
- package/dist/{chunk-STKEKXCK.js → chunk-AUH3PEFW.js} +2 -2
- package/dist/{chunk-PFGGPIMT.js → chunk-DA4UUSDO.js} +58 -3
- package/dist/chunk-DA4UUSDO.js.map +1 -0
- package/dist/{chunk-RDU63CDO.js → chunk-HDYBY3PQ.js} +380 -1
- package/dist/chunk-HDYBY3PQ.js.map +1 -0
- package/dist/{chunk-VLQLRKGW.js → chunk-KZYZX3V5.js} +260 -33
- package/dist/chunk-KZYZX3V5.js.map +1 -0
- package/dist/{chunk-GXP4YLAP.js → chunk-MBKNTXQX.js} +9 -9
- package/dist/chunk-MBKNTXQX.js.map +1 -0
- package/dist/{chunk-H6VDFBIO.js → chunk-SMR2MJXB.js} +156 -5
- package/dist/chunk-SMR2MJXB.js.map +1 -0
- package/dist/{chunk-YBGRXVAE.js → chunk-X3C2VFTM.js} +3 -3
- package/dist/{chunk-CK6EV37I.js → chunk-ZULFHADW.js} +69 -6
- package/dist/chunk-ZULFHADW.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/editor/index.d.ts +3 -3
- package/dist/editor/index.js +3 -3
- package/dist/{effect-GGP66JI6.js → effect-YBWDNIYG.js} +10 -10
- package/dist/embed/index.d.ts +36 -8
- package/dist/embed/index.js +5 -5
- package/dist/{frames-VEcqa40g.d.ts → frames-CGJudAbu.d.ts} +11 -1
- package/dist/index.d.ts +69 -6
- package/dist/index.js +35 -7
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +4 -4
- package/dist/node.js +9 -9
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +7 -7
- package/dist/react/index.js.map +1 -1
- package/dist/{recorder-CDPPTJMG.js → recorder-TYMEZHOT.js} +3 -3
- package/dist/{renderer-teaa98RE.d.ts → renderer-tk1nbVkW.d.ts} +252 -2
- package/dist/svelte/index.d.ts +4 -4
- package/dist/svelte/index.js +7 -7
- package/dist/svelte/index.js.map +1 -1
- package/dist/{svg-BhRboN9q.d.ts → svg-DaKRPA9v.d.ts} +39 -7
- package/dist/{types-DUOMxZaq.d.ts → types-wh28fXW4.d.ts} +2 -2
- package/dist/vector/index.d.ts +2 -2
- package/dist/vector/index.js +5 -3
- package/package.json +1 -1
- package/dist/chunk-4LKAPRFM.js.map +0 -1
- package/dist/chunk-CK6EV37I.js.map +0 -1
- package/dist/chunk-GXP4YLAP.js.map +0 -1
- package/dist/chunk-H6VDFBIO.js.map +0 -1
- package/dist/chunk-JL6TI6II.js.map +0 -1
- package/dist/chunk-PFGGPIMT.js.map +0 -1
- package/dist/chunk-RDU63CDO.js.map +0 -1
- package/dist/chunk-VLQLRKGW.js.map +0 -1
- /package/dist/{chunk-STKEKXCK.js.map → chunk-AUH3PEFW.js.map} +0 -0
- /package/dist/{chunk-YBGRXVAE.js.map → chunk-X3C2VFTM.js.map} +0 -0
- /package/dist/{effect-GGP66JI6.js.map → effect-YBWDNIYG.js.map} +0 -0
- /package/dist/{recorder-CDPPTJMG.js.map → recorder-TYMEZHOT.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/export/mp4mux.ts","../src/export/webmmux.ts","../src/export/zip.ts","../src/embed/record.ts","../src/embed/index.ts"],"sourcesContent":["/**\n * A small MP4 (ISO BMFF) writer for one H.264 video track, and optionally\n * one AAC audio track, with no dependencies, for video encoded in the\n * browser (WebCodecs' `VideoEncoder` with `avc: { format: \"avc\" }`, and\n * `AudioEncoder` with `mp4a.40.2`).\n *\n * The file is \"faststart\": `ftyp`, then `moov` (the index), then one `mdat`\n * holding every video sample in a single chunk (then every audio sample in\n * another), so a page can start playing it before it has all arrived.\n * Samples are in presentation order (browser encoders make no B-frames), so\n * there is no `ctts`.\n */\n\n/** One encoded frame: its bytes (length-prefixed NAL units), when it shows, and whether it is a keyframe. */\nexport interface Mp4Sample {\n data: Uint8Array;\n /** Presentation time in microseconds (WebCodecs' `timestamp`). */\n timestamp: number;\n /** How long it shows, in microseconds (default: until the next sample, or the one before's). */\n duration?: number;\n key: boolean;\n}\n\nexport interface Mp4Options {\n width: number;\n height: number;\n /** The `avcC` record: the encoder's `decoderConfig.description`. */\n avcC: Uint8Array;\n samples: readonly Mp4Sample[];\n /** Ticks per second of the track's times (default 90000, as for broadcast video). */\n timescale?: number;\n /** An AAC sound track to go with the picture. */\n audio?: Mp4AudioTrack;\n}\n\n/** AAC audio for {@link muxMp4}: WebCodecs `AudioEncoder` output with codec `mp4a.40.2`. */\nexport interface Mp4AudioTrack {\n sampleRate: number;\n channels: number;\n /**\n * The AudioSpecificConfig: the encoder's `decoderConfig.description`\n * (default: AAC-LC at this rate and channel count).\n */\n config?: Uint8Array;\n /** Raw AAC frames; `key` is ignored (every AAC frame is a sync sample). */\n samples: readonly Mp4Sample[];\n}\n\nconst AAC_RATES = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];\n\n/** An AAC-LC AudioSpecificConfig: object type 2, the rate's index, the channel count. */\nexport function aacConfig(sampleRate: number, channels: number): Uint8Array {\n const index = AAC_RATES.indexOf(sampleRate);\n if (index < 0) throw new Error(`AAC has no standard rate of ${sampleRate} Hz; resample to 48000 or 44100.`);\n return Uint8Array.of((2 << 3) | (index >> 1), ((index & 1) << 7) | (channels << 3));\n}\n\nconst MOVIE_TIMESCALE = 1000;\nconst UINT32 = 0x1_0000_0000;\n\nconst ascii = (s: string) => Uint8Array.from(s, (c) => c.charCodeAt(0));\n\n/** Big-endian fields, written into a growing list of parts. */\nclass Writer {\n parts: Uint8Array[] = [];\n size = 0;\n bytes(b: Uint8Array) {\n this.parts.push(b);\n this.size += b.length;\n return this;\n }\n u8(n: number) {\n return this.bytes(Uint8Array.of(n & 0xff));\n }\n u16(n: number) {\n return this.bytes(Uint8Array.of((n >>> 8) & 0xff, n & 0xff));\n }\n u32(n: number) {\n const b = new Uint8Array(4);\n new DataView(b.buffer).setUint32(0, n >>> 0);\n return this.bytes(b);\n }\n u64(n: number) {\n return this.u32(Math.floor(n / UINT32)).u32(n % UINT32);\n }\n zeros(n: number) {\n return this.bytes(new Uint8Array(n));\n }\n done(): Uint8Array {\n const out = new Uint8Array(this.size);\n let at = 0;\n for (const p of this.parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n }\n}\n\n/** A box: size, type, then its fields and children. */\nfunction box(type: string, ...content: Uint8Array[]): Uint8Array {\n const w = new Writer();\n const size = 8 + content.reduce((n, c) => n + c.length, 0);\n w.u32(size).bytes(ascii(type));\n for (const c of content) w.bytes(c);\n return w.done();\n}\n\n/** A full box: a box whose fields start with a version and flags. */\nfunction fullBox(type: string, version: number, flags: number, ...content: Uint8Array[]): Uint8Array {\n return box(type, Uint8Array.of(version, (flags >> 16) & 0xff, (flags >> 8) & 0xff, flags & 0xff), ...content);\n}\n\nconst fields = (fill: (w: Writer) => unknown) => {\n const w = new Writer();\n fill(w);\n return w.done();\n};\n\n/** The identity transform, as `tkhd` and `mvhd` write it (16.16 and 2.30 fixed point). */\nconst MATRIX = fields((w) => [0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000].forEach((n) => w.u32(n)));\n\n/**\n * Each sample's duration in track ticks, from the gaps between timestamps\n * (the last keeps its own duration, or the gap before it).\n */\nfunction sampleTicks(samples: readonly Mp4Sample[], timescale: number): number[] {\n const tick = (us: number) => Math.round((us * timescale) / 1e6);\n return samples.map((s, i) => {\n const next = samples[i + 1];\n if (next) return Math.max(1, tick(next.timestamp) - tick(s.timestamp));\n if (s.duration) return Math.max(1, tick(s.duration));\n const prev = samples[i - 1];\n return prev ? Math.max(1, tick(s.timestamp) - tick(prev.timestamp)) : Math.max(1, tick(1e6 / 30));\n });\n}\n\n/** `stts`: the durations, run-length coded. */\nfunction stts(ticks: number[]): Uint8Array {\n const runs: [number, number][] = [];\n for (const t of ticks) {\n const last = runs[runs.length - 1];\n if (last && last[1] === t) last[0]++;\n else runs.push([1, t]);\n }\n return fullBox(\"stts\", 0, 0, fields((w) => {\n w.u32(runs.length);\n for (const [count, delta] of runs) w.u32(count).u32(delta);\n }));\n}\n\n/** A descriptor in an `esds`: tag, length (one byte will do here), body. */\nconst descriptor = (tag: number, ...content: Uint8Array[]) => {\n const body = fields((w) => content.forEach((c) => w.bytes(c)));\n if (body.length > 0x7f) throw new Error(\"An esds descriptor this long is not written here.\");\n return fields((w) => w.u8(tag).u8(body.length).bytes(body));\n};\n\n/** `stsz`, `stsc` and `stco`/`co64`: every sample in one chunk at `offset`. */\nfunction oneChunk(samples: readonly Mp4Sample[], offset: number, wide: boolean): Uint8Array[] {\n const stsz = fullBox(\"stsz\", 0, 0, fields((w) => {\n w.u32(0).u32(samples.length);\n for (const s of samples) w.u32(s.data.length);\n }));\n const stsc = fullBox(\"stsc\", 0, 0, fields((w) => (samples.length ? w.u32(1).u32(1).u32(samples.length).u32(1) : w.u32(0))));\n const stco = wide\n ? fullBox(\"co64\", 0, 0, fields((w) => w.u32(1).u64(offset)))\n : fullBox(\"stco\", 0, 0, fields((w) => w.u32(1).u32(offset)));\n return [stsz, stsc, stco];\n}\n\n/** The sound's `trak`: track 2, AAC in an `mp4a` entry. */\nfunction audioTrak(audio: Mp4AudioTrack, offset: number, wide: boolean): { trak: Uint8Array; movieTicks: number } {\n const timescale = audio.sampleRate;\n const ticks = sampleTicks(audio.samples, timescale);\n const trackTicks = ticks.reduce((a, b) => a + b, 0);\n const movieTicks = Math.round((trackTicks * MOVIE_TIMESCALE) / timescale);\n const tkhd = fullBox(\"tkhd\", 0, 3, fields((w) =>\n w.u32(0).u32(0).u32(2).u32(0).u32(movieTicks)\n .zeros(8).u16(0).u16(1).u16(0x0100).u16(0) // reserved, layer, alternate group, volume 1.0, reserved\n .bytes(MATRIX).u32(0).u32(0),\n ));\n const mdhd = fullBox(\"mdhd\", 0, 0, fields((w) => w.u32(0).u32(0).u32(timescale).u32(trackTicks).u16(0x55c4).u16(0)));\n const hdlr = fullBox(\"hdlr\", 0, 0, fields((w) => w.u32(0).bytes(ascii(\"soun\")).zeros(12).bytes(ascii(\"SoundHandler\\0\"))));\n const smhd = fullBox(\"smhd\", 0, 0, new Uint8Array(4));\n const dinf = box(\"dinf\", fullBox(\"dref\", 0, 0, fields((w) => w.u32(1)), fullBox(\"url \", 0, 1)));\n const bitrate = Math.round((audio.samples.reduce((n, s) => n + s.data.length, 0) * 8) / Math.max(1e-3, trackTicks / timescale));\n const esds = fullBox(\n \"esds\",\n 0,\n 0,\n descriptor(\n 0x03, // ES_Descriptor\n fields((w) => w.u16(2).u8(0)), // ES id, flags\n descriptor(\n 0x04, // DecoderConfigDescriptor\n fields((w) => w.u8(0x40).u8(0x15).u8(0).u16(0).u32(bitrate).u32(bitrate)), // MPEG-4 audio, audio stream, buffer size, bitrates\n descriptor(0x05, audio.config ?? aacConfig(audio.sampleRate, audio.channels)), // DecoderSpecificInfo\n ),\n descriptor(0x06, Uint8Array.of(0x02)), // SLConfigDescriptor\n ),\n );\n const mp4a = box(\n \"mp4a\",\n fields((w) => w.zeros(6).u16(1).zeros(8).u16(audio.channels).u16(16).u16(0).u16(0).u32(Math.min(audio.sampleRate, 0xffff) * 0x10000)),\n esds,\n );\n const stsd = fullBox(\"stsd\", 0, 0, fields((w) => w.u32(1)), mp4a);\n const stbl = box(\"stbl\", stsd, stts(ticks), ...oneChunk(audio.samples, offset, wide));\n const trak = box(\"trak\", tkhd, box(\"mdia\", mdhd, hdlr, box(\"minf\", smhd, dinf, stbl)));\n return { trak, movieTicks };\n}\n\nfunction moov(options: Mp4Options, ticks: number[], dataOffset: number, wide: boolean): Uint8Array {\n const { width, height, avcC, samples } = options;\n const timescale = options.timescale ?? 90000;\n const trackTicks = ticks.reduce((a, b) => a + b, 0);\n const videoTicks = Math.round((trackTicks * MOVIE_TIMESCALE) / timescale);\n const videoBytes = samples.reduce((n, s) => n + s.data.length, 0);\n const sound = options.audio?.samples.length ? audioTrak(options.audio, dataOffset + videoBytes, wide) : undefined;\n const movieTicks = Math.max(videoTicks, sound?.movieTicks ?? 0);\n\n const mvhd = fullBox(\"mvhd\", 0, 0, fields((w) =>\n w.u32(0).u32(0).u32(MOVIE_TIMESCALE).u32(movieTicks)\n .u32(0x00010000).u16(0x0100).zeros(10) // rate 1.0, volume 1.0, reserved\n .bytes(MATRIX).zeros(24).u32(sound ? 3 : 2), // pre_defined, next track id\n ));\n const tkhd = fullBox(\"tkhd\", 0, 3, fields((w) => // enabled, in the movie\n w.u32(0).u32(0).u32(1).u32(0).u32(videoTicks)\n .zeros(8).u16(0).u16(0).u16(0).u16(0) // reserved, layer, group, volume (none for video), reserved\n .bytes(MATRIX).u32(width * 0x10000).u32(height * 0x10000),\n ));\n const mdhd = fullBox(\"mdhd\", 0, 0, fields((w) => w.u32(0).u32(0).u32(timescale).u32(trackTicks).u16(0x55c4).u16(0))); // \"und\"\n const hdlr = fullBox(\"hdlr\", 0, 0, fields((w) => w.u32(0).bytes(ascii(\"vide\")).zeros(12).bytes(ascii(\"VideoHandler\\0\"))));\n const vmhd = fullBox(\"vmhd\", 0, 1, new Uint8Array(8));\n const dinf = box(\"dinf\", fullBox(\"dref\", 0, 0, fields((w) => w.u32(1)), fullBox(\"url \", 0, 1)));\n\n const avc1 = box(\n \"avc1\",\n fields((w) =>\n w.zeros(6).u16(1) // reserved, data reference index\n .zeros(16).u16(width).u16(height)\n .u32(0x00480000).u32(0x00480000).u32(0).u16(1) // 72 dpi, reserved, one frame per sample\n .zeros(32).u16(0x0018).u16(0xffff), // compressor name, depth, pre_defined\n ),\n box(\"avcC\", avcC),\n );\n const stsd = fullBox(\"stsd\", 0, 0, fields((w) => w.u32(1)), avc1);\n const keys = samples.flatMap((s, i) => (s.key ? [i + 1] : []));\n // Every sample a keyframe: leave stss out, which says so.\n const stss = keys.length === samples.length ? [] : [fullBox(\"stss\", 0, 0, fields((w) => {\n w.u32(keys.length);\n for (const k of keys) w.u32(k);\n }))];\n // One chunk with every sample, starting at the mdat's data.\n const stbl = box(\"stbl\", stsd, stts(ticks), ...stss, ...oneChunk(samples, dataOffset, wide));\n const minf = box(\"minf\", vmhd, dinf, stbl);\n const trak = box(\"trak\", tkhd, box(\"mdia\", mdhd, hdlr, minf));\n return box(\"moov\", mvhd, trak, ...(sound ? [sound.trak] : []));\n}\n\n/**\n * An MP4 file of one H.264 track (and an AAC one, with `audio`): `ftyp`,\n * `moov`, then the samples in one `mdat`, the video's then the sound's.\n * Throws when there are no samples or the first is not a keyframe.\n */\nexport function muxMp4(options: Mp4Options): Uint8Array {\n const { samples } = options;\n if (!samples.length) throw new Error(\"An MP4 needs at least one frame.\");\n if (!samples[0]!.key) throw new Error(\"An MP4's first frame must be a keyframe.\");\n const ftyp = box(\"ftyp\", ascii(\"isom\"), fields((w) => w.u32(0x200)), ascii(\"isomiso2avc1mp41\"));\n const ticks = sampleTicks(samples, options.timescale ?? 90000);\n const all = [...samples, ...(options.audio?.samples ?? [])];\n const payload = all.reduce((n, s) => n + s.data.length, 0);\n const large = payload + 8 >= UINT32;\n const mdatHeader = large ? 16 : 8;\n // The index's size does not depend on the offset it holds, so measure it once and write it again.\n const wide = ftyp.length + moov(options, ticks, 0, large).length + mdatHeader + payload >= UINT32;\n const index = moov(options, ticks, 0, wide);\n const dataOffset = ftyp.length + index.length + mdatHeader;\n const head = fields((w) => {\n w.bytes(ftyp).bytes(moov(options, ticks, dataOffset, wide));\n if (large) w.u32(1).bytes(ascii(\"mdat\")).u64(payload + 16);\n else w.u32(payload + 8).bytes(ascii(\"mdat\"));\n });\n const out = new Uint8Array(head.length + payload);\n out.set(head);\n let at = head.length;\n for (const s of all) {\n out.set(s.data, at);\n at += s.data.length;\n }\n return out;\n}\n","/**\n * A small WebM (Matroska) writer for one VP8 or VP9 video track, and\n * optionally one Opus audio track, with no dependencies, for video encoded\n * in the browser (WebCodecs' `VideoEncoder` and `AudioEncoder`).\n *\n * The file is an EBML header and one Segment of known size: `Info` (with the\n * duration), `Tracks`, then `Cluster`s of `SimpleBlock`s, a new cluster at\n * each keyframe. There are no `Cues`, so a player seeks by scanning, which\n * is quick for short clips. Frames with an alpha plane (VP9 or VP8 encoded\n * with `alpha: \"keep\"`) go in `BlockGroup`s with the alpha as a\n * `BlockAdditional` (id 1), and the track says `AlphaMode` 1, as Chrome's\n * own recordings do. Sound goes in track 2, its packets interleaved with\n * the frames in time order.\n */\n\n/** One encoded frame. */\nexport interface WebmFrame {\n data: Uint8Array;\n /** Presentation time in microseconds (WebCodecs' `timestamp`). */\n timestamp: number;\n key: boolean;\n /** The frame's alpha plane, encoded (WebCodecs' `metadata.alphaSideData`). */\n alpha?: Uint8Array;\n}\n\nexport interface WebmOptions {\n codec: \"vp8\" | \"vp9\";\n width: number;\n height: number;\n frames: readonly WebmFrame[];\n /** The length in microseconds (default: the last frame's time plus one frame). */\n duration?: number;\n /** Frames per second, written as the track's default frame duration. */\n fps?: number;\n /** `WritingApp` (default \"flair\"). */\n app?: string;\n /** An Opus sound track to go with the picture. */\n audio?: WebmAudioTrack;\n}\n\n/** Opus audio for {@link muxWebm}: WebCodecs `AudioEncoder` output with codec `opus`. */\nexport interface WebmAudioTrack {\n sampleRate: number;\n channels: number;\n /** The `OpusHead`: the encoder's `decoderConfig.description` (default one for this rate and channel count, pre-skip 312). */\n codecPrivate?: Uint8Array;\n packets: readonly { data: Uint8Array; timestamp: number }[];\n}\n\n/** An Opus identification header (\"OpusHead\", RFC 7845) for mapping family 0. */\nexport function opusHead(sampleRate: number, channels: number, preSkip = 312): Uint8Array {\n const b = new Uint8Array(19);\n b.set(new TextEncoder().encode(\"OpusHead\"));\n const v = new DataView(b.buffer);\n v.setUint8(8, 1);\n v.setUint8(9, channels);\n v.setUint16(10, preSkip, true);\n v.setUint32(12, sampleRate, true);\n return b;\n}\n\n/** Element ids (their own leading-bits coding is part of the id). */\nconst ID = {\n EBML: 0x1a45dfa3,\n EBMLVersion: 0x4286,\n EBMLReadVersion: 0x42f7,\n EBMLMaxIDLength: 0x42f2,\n EBMLMaxSizeLength: 0x42f3,\n DocType: 0x4282,\n DocTypeVersion: 0x4287,\n DocTypeReadVersion: 0x4285,\n Segment: 0x18538067,\n Info: 0x1549a966,\n TimestampScale: 0x2ad7b1,\n Duration: 0x4489,\n MuxingApp: 0x4d80,\n WritingApp: 0x5741,\n Tracks: 0x1654ae6b,\n TrackEntry: 0xae,\n TrackNumber: 0xd7,\n TrackUID: 0x73c5,\n TrackType: 0x83,\n FlagLacing: 0x9c,\n CodecID: 0x86,\n DefaultDuration: 0x23e383,\n CodecPrivate: 0x63a2,\n CodecDelay: 0x56aa,\n SeekPreRoll: 0x56bb,\n Audio: 0xe1,\n SamplingFrequency: 0xb5,\n Channels: 0x9f,\n MaxBlockAdditionID: 0x55ee,\n Video: 0xe0,\n PixelWidth: 0xb0,\n PixelHeight: 0xba,\n AlphaMode: 0x53c0,\n Cluster: 0x1f43b675,\n Timestamp: 0xe7,\n SimpleBlock: 0xa3,\n BlockGroup: 0xa0,\n Block: 0xa1,\n ReferenceBlock: 0xfb,\n BlockAdditions: 0x75a1,\n BlockMore: 0xa6,\n BlockAddID: 0xee,\n BlockAdditional: 0xa5,\n} as const;\n\n/** Timestamps count milliseconds (TimestampScale 1 000 000 ns). */\nconst SCALE_NS = 1_000_000;\n/** A block's time is a signed 16-bit offset from its cluster's. */\nconst MAX_OFFSET = 32767;\n\nconst concat = (parts: readonly Uint8Array[]) => {\n const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));\n let at = 0;\n for (const p of parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n};\n\n/** An element id's bytes (ids already carry their length marker). */\nfunction idBytes(id: number): Uint8Array {\n const out: number[] = [];\n for (let n = id; n > 0; n = Math.floor(n / 256)) out.unshift(n & 0xff);\n return Uint8Array.from(out);\n}\n\n/** A size as an EBML variable-length integer, in the fewest bytes (1–8). */\nexport function vint(n: number): Uint8Array {\n for (let len = 1; len <= 8; len++) {\n // All ones is reserved for \"unknown size\".\n if (n < 2 ** (7 * len) - 1) {\n const out = new Uint8Array(len);\n let v = n;\n for (let i = len - 1; i >= 0; i--) {\n out[i] = v % 256;\n v = Math.floor(v / 256);\n }\n out[0]! |= 1 << (8 - len);\n return out;\n }\n }\n throw new RangeError(`An EBML size cannot be ${n}.`);\n}\n\nconst el = (id: number, ...content: Uint8Array[]) => {\n const body = concat(content);\n return concat([idBytes(id), vint(body.length), body]);\n};\n\nconst uint = (id: number, n: number) => {\n const out: number[] = [];\n for (let v = n; v > 0 || out.length === 0; v = Math.floor(v / 256)) out.unshift(v % 256);\n return el(id, Uint8Array.from(out));\n};\n\nconst float = (id: number, n: number) => {\n const b = new Uint8Array(8);\n new DataView(b.buffer).setFloat64(0, n);\n return el(id, b);\n};\n\nconst str = (id: number, s: string) => el(id, new TextEncoder().encode(s));\n\n/** A block's header: its track (1 the picture, 2 the sound), its time from the cluster's, its flags. */\nfunction blockHeader(offset: number, flags: number, track = 1): Uint8Array {\n const b = new Uint8Array(4);\n b[0] = 0x80 | track;\n new DataView(b.buffer).setInt16(1, offset);\n b[3] = flags;\n return b;\n}\n\n/**\n * A WebM file of one VP8 or VP9 track (and an Opus one, with `audio`).\n * Throws when there are no frames or the first is not a keyframe.\n */\nexport function muxWebm(options: WebmOptions): Uint8Array {\n const { codec, width, height, frames, fps } = options;\n if (!frames.length) throw new Error(\"A WebM needs at least one frame.\");\n if (!frames[0]!.key) throw new Error(\"A WebM's first frame must be a keyframe.\");\n const alpha = frames.some((f) => f.alpha);\n const sound = options.audio?.packets.length ? options.audio : undefined;\n const ms = (us: number) => Math.round(us / 1000);\n const last = frames[frames.length - 1]!;\n const frameUs = fps ? 1e6 / fps : frames.length > 1 ? (last.timestamp - frames[0]!.timestamp) / (frames.length - 1) : 1e6 / 30;\n const durationUs = options.duration ?? last.timestamp + frameUs;\n\n const header = el(\n ID.EBML,\n uint(ID.EBMLVersion, 1),\n uint(ID.EBMLReadVersion, 1),\n uint(ID.EBMLMaxIDLength, 4),\n uint(ID.EBMLMaxSizeLength, 8),\n str(ID.DocType, \"webm\"),\n // BlockAdditions came in version 4.\n uint(ID.DocTypeVersion, alpha ? 4 : 2),\n uint(ID.DocTypeReadVersion, 2),\n );\n const info = el(\n ID.Info,\n uint(ID.TimestampScale, SCALE_NS),\n float(ID.Duration, durationUs / 1000),\n str(ID.MuxingApp, \"flair\"),\n str(ID.WritingApp, options.app ?? \"flair\"),\n );\n const tracks = el(\n ID.Tracks,\n el(\n ID.TrackEntry,\n uint(ID.TrackNumber, 1),\n uint(ID.TrackUID, 1),\n uint(ID.TrackType, 1), // video\n uint(ID.FlagLacing, 0),\n str(ID.CodecID, codec === \"vp9\" ? \"V_VP9\" : \"V_VP8\"),\n ...(fps ? [uint(ID.DefaultDuration, Math.round(1e9 / fps))] : []),\n ...(alpha ? [uint(ID.MaxBlockAdditionID, 1)] : []),\n el(ID.Video, uint(ID.PixelWidth, width), uint(ID.PixelHeight, height), ...(alpha ? [uint(ID.AlphaMode, 1)] : [])),\n ),\n ...(sound ? [soundTrack(sound)] : []),\n );\n\n const clusters: Uint8Array[] = [];\n let blocks: Uint8Array[] = [];\n let clusterMs = 0;\n let previousMs = 0;\n const close = () => {\n if (blocks.length) clusters.push(el(ID.Cluster, uint(ID.Timestamp, clusterMs), ...blocks));\n blocks = [];\n };\n // The picture's frames and the sound's packets in time order (a frame first at a tie); clusters start at keyframes.\n type Item = { frame: WebmFrame; packet?: undefined } | { frame?: undefined; packet: WebmAudioTrack[\"packets\"][number] };\n const items: Item[] = [...frames.map((frame) => ({ frame })), ...(sound?.packets ?? []).map((packet) => ({ packet }))];\n const timeOf = (item: Item) => (item.frame ?? item.packet)!.timestamp;\n items.sort((a, b) => timeOf(a) - timeOf(b) || (a.frame ? -1 : 0) - (b.frame ? -1 : 0));\n let started = false;\n for (const item of items) {\n const at = ms(timeOf(item));\n const frame = item.frame;\n if (!frame) {\n if (!started || at - clusterMs > MAX_OFFSET) {\n close();\n clusterMs = at;\n started = true;\n }\n blocks.push(el(ID.SimpleBlock, blockHeader(at - clusterMs, 0x80, 2), item.packet!.data));\n continue;\n }\n if (!started || frame.key || at - clusterMs > MAX_OFFSET) {\n close();\n clusterMs = at;\n started = true;\n }\n const offset = at - clusterMs;\n if (frame.alpha) {\n blocks.push(\n el(\n ID.BlockGroup,\n el(ID.Block, blockHeader(offset, 0), frame.data),\n el(ID.BlockAdditions, el(ID.BlockMore, uint(ID.BlockAddID, 1), el(ID.BlockAdditional, frame.alpha))),\n // A group without a reference is a keyframe; point delta frames at the one before.\n ...(frame.key ? [] : [el(ID.ReferenceBlock, signed(previousMs - at))]),\n ),\n );\n } else {\n blocks.push(el(ID.SimpleBlock, blockHeader(offset, frame.key ? 0x80 : 0), frame.data));\n }\n previousMs = at;\n }\n close();\n\n const segment = el(ID.Segment, info, tracks, ...clusters);\n return concat([header, segment]);\n}\n\n/** Track 2: Opus at its rate, with its header and the decoder's delay. */\nfunction soundTrack(sound: WebmAudioTrack): Uint8Array {\n const head = sound.codecPrivate?.length ? sound.codecPrivate : opusHead(sound.sampleRate, sound.channels);\n // Pre-skip is in 48 kHz samples, whatever the rate.\n const preSkip = head.length >= 12 ? head[10]! | (head[11]! << 8) : 312;\n return el(\n ID.TrackEntry,\n uint(ID.TrackNumber, 2),\n uint(ID.TrackUID, 2),\n uint(ID.TrackType, 2), // audio\n uint(ID.FlagLacing, 0),\n str(ID.CodecID, \"A_OPUS\"),\n el(ID.CodecPrivate, head),\n uint(ID.CodecDelay, Math.round((preSkip * 1e9) / 48000)),\n uint(ID.SeekPreRoll, 80_000_000),\n el(ID.Audio, float(ID.SamplingFrequency, sound.sampleRate), uint(ID.Channels, sound.channels)),\n );\n}\n\n/** A signed integer's bytes, big-endian, in the fewest bytes (ReferenceBlock is signed). */\nfunction signed(n: number): Uint8Array {\n for (let len = 1; len <= 8; len++) {\n if (n >= -(2 ** (8 * len - 1)) && n < 2 ** (8 * len - 1)) {\n const out = new Uint8Array(len);\n let v = n < 0 ? 2 ** (8 * len) + n : n;\n for (let i = len - 1; i >= 0; i--) {\n out[i] = v % 256;\n v = Math.floor(v / 256);\n }\n return out;\n }\n }\n throw new RangeError(`${n} is out of range.`);\n}\n","/**\n * A store-only ZIP writer (no compression, no dependencies), for handing\n * over many already-compressed files at once: a PNG sequence, say.\n */\n\nexport interface ZipEntry {\n name: string;\n data: Uint8Array;\n}\n\nlet table: Uint32Array | undefined;\n\n/** CRC-32 (IEEE), as ZIP wants it. */\nexport function crc32(data: Uint8Array): number {\n table ??= Uint32Array.from({ length: 256 }, (_, n) => {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n return c >>> 0;\n });\n let crc = 0xffffffff;\n for (let i = 0; i < data.length; i++) crc = table[(crc ^ data[i]!) & 0xff]! ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/** 1 January 1980, the earliest time a ZIP can hold, so the same frames make the same file. */\nconst DOS_DATE = (0 << 9) | (1 << 5) | 1;\n\n/**\n * A ZIP holding `entries` as they are (method 0, \"stored\"). Names are UTF-8.\n * Each file and the whole must stay under 4 GB (no ZIP64).\n */\nexport function zipStore(entries: readonly ZipEntry[]): Uint8Array {\n const encoder = new TextEncoder();\n const locals: Uint8Array[] = [];\n const centrals: Uint8Array[] = [];\n let offset = 0;\n for (const { name, data } of entries) {\n const nameBytes = encoder.encode(name);\n const crc = crc32(data);\n const local = new Uint8Array(30 + nameBytes.length);\n const l = new DataView(local.buffer);\n l.setUint32(0, 0x04034b50, true);\n l.setUint16(4, 20, true); // version needed: 2.0\n l.setUint16(6, 0x0800, true); // UTF-8 names\n l.setUint16(8, 0, true); // stored\n l.setUint16(10, 0, true); // time\n l.setUint16(12, DOS_DATE, true);\n l.setUint32(14, crc, true);\n l.setUint32(18, data.length, true);\n l.setUint32(22, data.length, true);\n l.setUint16(26, nameBytes.length, true);\n local.set(nameBytes, 30);\n\n const central = new Uint8Array(46 + nameBytes.length);\n const c = new DataView(central.buffer);\n c.setUint32(0, 0x02014b50, true);\n c.setUint16(4, 20, true); // made by\n c.setUint16(6, 20, true); // needed\n c.setUint16(8, 0x0800, true);\n c.setUint16(10, 0, true);\n c.setUint16(12, 0, true);\n c.setUint16(14, DOS_DATE, true);\n c.setUint32(16, crc, true);\n c.setUint32(20, data.length, true);\n c.setUint32(24, data.length, true);\n c.setUint16(28, nameBytes.length, true);\n c.setUint32(42, offset, true);\n central.set(nameBytes, 46);\n\n locals.push(local, data);\n centrals.push(central);\n offset += local.length + data.length;\n }\n const centralSize = centrals.reduce((n, c) => n + c.length, 0);\n const end = new Uint8Array(22);\n const e = new DataView(end.buffer);\n e.setUint32(0, 0x06054b50, true);\n e.setUint16(8, entries.length, true);\n e.setUint16(10, entries.length, true);\n e.setUint32(12, centralSize, true);\n e.setUint32(16, offset, true);\n\n const out = new Uint8Array(offset + centralSize + 22);\n let at = 0;\n for (const part of [...locals, ...centrals, end]) {\n out.set(part, at);\n at += part.length;\n }\n return out;\n}\n","// gifenc ships without types. The reference (not an import) brings them along when a host\n// type-checks these sources through the `workspace` condition.\n// eslint-disable-next-line @typescript-eslint/triple-slash-reference\n/// <reference path=\"../shader/gifenc.d.ts\" />\nimport { effectDefaults, effectInputs, getEffect, type EffectDefinition } from \"../catalog/index.js\";\nimport { renderVectorEffect } from \"../catalog/types.js\";\nimport { muxMp4 } from \"../export/mp4mux.js\";\nimport { muxWebm, type WebmFrame } from \"../export/webmmux.js\";\nimport { analyseAudioBuffer, type AudioBufferAnalysis } from \"../shader/audio.js\";\nimport { zipStore, type ZipEntry } from \"../export/zip.js\";\nimport { parseColor, type ControlValue } from \"../shader/controls.js\";\nimport { ShaderFrames, type RenderOptions } from \"../shader/frames.js\";\nimport { seekVideo, type LiveSource } from \"../shader/textures.js\";\nimport { svgDuration, svgView } from \"../vector/svg.js\";\nimport { subjectValues, type EffectSubject } from \"./index.js\";\n\n/** What {@link recordEffect} makes: a video (`mp4`, `webm`), an animated `gif`, or `png` frames in a ZIP. */\nexport type RecordFormat = \"mp4\" | \"webm\" | \"gif\" | \"png\";\n\n/** The pointer for one frame of a shader: `iPointer`, `iMouse`, and clicks and trail so far (times in seconds). */\nexport type RecordPointer = Pick<RenderOptions, \"pointer\" | \"mouse\" | \"clicks\" | \"trail\">;\n\nexport interface RecordOptions {\n /** What to apply the effect to (see {@link EffectSubject}); several fill several controls in order. */\n subject?: EffectSubject | readonly EffectSubject[];\n /** A preset by name, then these values, over the effect's defaults. */\n preset?: string;\n values?: Record<string, ControlValue>;\n /**\n * The file to make (default `mp4` where the browser encodes H.264, else\n * `webm`; `webm` when `alpha` is on).\n */\n format?: RecordFormat;\n /** Pixels (default 1280 × 720). Videos round them up to even numbers, as their encoders need. */\n width?: number;\n height?: number;\n /** Frames per second (default 30). GIF delays are whole hundredths of a second, so 10, 20, 25 and 50 play back exactly there. */\n fps?: number;\n /**\n * Seconds to record (default: a shader's `loop`, or a vector effect's\n * picture plus its `hold`, else 4).\n */\n duration?: number;\n /** The time of the first frame, in seconds (default 0). */\n start?: number;\n /** Bits per second for `mp4` and `webm` (default `width × height × fps × 0.15`). */\n bitrate?: number;\n /**\n * Keep transparency (default: the effect's `transparent`): `webm` (VP9\n * or VP8 with an alpha channel, which Chrome, Edge and Firefox play),\n * `png`, and `gif` (one see-through colour). `mp4` cannot, so it lays the\n * picture over `background` unless `alpha: true` was asked for. Without\n * it, transparent pixels are laid over `background`.\n */\n alpha?: boolean;\n /** A CSS colour under the picture when `alpha` is off (default black for shaders, white for vector effects). */\n background?: string;\n /**\n * The pointer, for shaders that answer it: the same every frame, or a\n * function of the frame's time in seconds. Without it, interactive\n * effects play their idle demos, as on a page nobody has touched.\n *\n * ```ts\n * pointer: { clicks: [{ x: 640, y: 360, time: 0.5 }] }\n * pointer: (t) => ({ pointer: [640 + 200 * Math.sin(t), 360, 1, 0] })\n * ```\n */\n pointer?: RecordPointer | ((time: number) => RecordPointer);\n /** A vector effect's step start times in ms, for pictures that change on steps (default none). */\n steps?: readonly number[];\n /**\n * Sound: a decoded `AudioBuffer`, or the URL of an audio file to fetch and\n * decode. An audio-reactive shader follows it frame for frame (each\n * frame's `iAudio`, `iSpectrum` and `iBeat` come from `analyseAudioBuffer`\n * at that frame's time, so the picture is the same on every machine), and\n * the stretch from `start` to `start + duration` is muxed into an `mp4`\n * (AAC) or `webm` (Opus) as its sound track, unless `audioTrack` is false.\n * `gif` and `png` have no sound, so there it only drives the picture.\n * Effects that don't hear sound just get the sound track.\n */\n audio?: AudioBuffer | string;\n /** Put `audio` in the video as its sound track (default true for `mp4` and `webm`). */\n audioTrack?: boolean;\n /**\n * Called before each frame is drawn, with its time in seconds: draw a\n * canvas subject for that time here. (A `<video>` subject is paused and\n * sought to each frame's time for you.)\n */\n beforeFrame?: (time: number, index: number) => void | Promise<void>;\n /** Called after each frame with the share done, 0–1. */\n onProgress?: (fraction: number) => void;\n /** Aborting rejects with an `AbortError` `DOMException`. */\n signal?: AbortSignal;\n}\n\n/** What a recording will be, worked out from the options before any frame is drawn (see {@link recordingPlan}). */\nexport interface RecordingPlan {\n effect: EffectDefinition;\n format: RecordFormat;\n width: number;\n height: number;\n fps: number;\n duration: number;\n start: number;\n frames: number;\n alpha: boolean;\n /** For `mp4` and `webm`: the encoder's settings. */\n encoder?: VideoEncoderConfig;\n /** For `mp4` and `webm` with `audio`: the sound's encoder settings (AAC or Opus, 48 kHz stereo). */\n audioEncoder?: AudioEncoderConfig;\n}\n\n/** The rate sound tracks are encoded at (Opus only takes 48 kHz; AAC is happy with it). */\nconst AUDIO_RATE = 48000;\n\n/** An AAC or Opus encoder config the browser takes, or undefined. */\nasync function audioConfig(format: \"mp4\" | \"webm\"): Promise<AudioEncoderConfig | undefined> {\n if (typeof AudioEncoder === \"undefined\" || typeof AudioData === \"undefined\") return undefined;\n const config: AudioEncoderConfig = { codec: format === \"mp4\" ? \"mp4a.40.2\" : \"opus\", sampleRate: AUDIO_RATE, numberOfChannels: 2, bitrate: 128_000 };\n try {\n return (await AudioEncoder.isConfigSupported(config)).supported ? config : undefined;\n } catch {\n return undefined;\n }\n}\n\nconst DEFAULT_SECONDS = 4;\n\n/** Lets the page repaint between frames so progress shows and Cancel works. */\nconst yieldToBrowser = () => new Promise<void>((resolve) => setTimeout(resolve, 0));\n\nconst formats = (list: RecordFormat[]) => list.map((f) => `\"${f}\"`).join(\", \").replace(/, ([^,]*)$/, \" or $1\");\n\n/** H.264 levels by the most macroblocks a frame and a second may hold, for the codec string. */\nconst AVC_LEVELS: [level: number, frame: number, second: number][] = [\n [0x1f, 3600, 108000], // 3.1\n [0x28, 8192, 245760], // 4.0\n [0x2a, 8704, 522240], // 4.2\n [0x32, 22080, 589824], // 5.0\n [0x33, 36864, 983040], // 5.1\n [0x34, 36864, 2073600], // 5.2\n [0x3c, 139264, 4177920], // 6.0\n];\n\n/** H.264 codec strings to try, High profile first, at the lowest level that holds the picture. */\nfunction avcCodecs(width: number, height: number, fps: number): string[] {\n const mbs = Math.ceil(width / 16) * Math.ceil(height / 16);\n const level = (AVC_LEVELS.find(([, f, s]) => mbs <= f && mbs * fps <= s) ?? AVC_LEVELS[AVC_LEVELS.length - 1]!)[0];\n const hex = level.toString(16).toUpperCase().padStart(2, \"0\");\n return [\"avc1.6400\", \"avc1.4D00\", \"avc1.42E0\"].map((p) => p + hex);\n}\n\n/** The first of `codecs` the browser encodes with these settings, as a config; undefined when none. */\nasync function supported(codecs: string[], base: Omit<VideoEncoderConfig, \"codec\">): Promise<VideoEncoderConfig | undefined> {\n for (const codec of codecs) {\n const config: VideoEncoderConfig = { ...base, codec };\n try {\n const answer = await VideoEncoder.isConfigSupported(config);\n if (answer.supported) return config;\n } catch {\n // A codec string the browser does not know: try the next.\n }\n }\n return undefined;\n}\n\nconst hasWebCodecs = () => typeof VideoEncoder !== \"undefined\" && typeof VideoFrame !== \"undefined\";\n\n/** A video's encoder config, or undefined when the browser cannot encode it. */\nasync function videoConfig(format: \"mp4\" | \"webm\", width: number, height: number, fps: number, bitrate: number) {\n const base: Omit<VideoEncoderConfig, \"codec\"> = {\n width,\n height,\n bitrate,\n framerate: fps,\n latencyMode: \"quality\",\n ...(format === \"mp4\" ? { avc: { format: \"avc\" as const } } : {}),\n };\n return supported(format === \"mp4\" ? avcCodecs(width, height, fps) : [\"vp09.00.10.08\", \"vp8\"], base);\n}\n\nconst resolveEffect = (effect: EffectDefinition | string) => {\n const def = typeof effect === \"string\" ? getEffect(effect) : effect;\n if (!def) throw new Error(`There is no effect \"${String(effect)}\" in the catalog; findEffects() lists them.`);\n return def;\n};\n\n/** A positive number option, or a sentence saying what it should be. */\nfunction positive(name: string, value: number | undefined, fallback: number): number {\n const n = value ?? fallback;\n if (!Number.isFinite(n) || n <= 0) throw new Error(`${name} must be a number above 0 (it was ${String(value)}).`);\n return n;\n}\n\nconst even = (n: number) => Math.max(2, Math.ceil(n / 2) * 2);\n\n/**\n * What {@link recordEffect} would make of these options, without drawing a\n * frame: the format (after falling back where the browser cannot encode\n * one), size, length, frame count, whether it keeps transparency, and the\n * encoder settings. Rejects with a sentence when the effect is unknown, an\n * option is out of range, or the browser cannot make the format asked for.\n */\nexport async function recordingPlan(effect: EffectDefinition | string, options: RecordOptions = {}): Promise<RecordingPlan> {\n const def = resolveEffect(effect);\n if (options.preset && !def.presets?.some((p) => p.name === options.preset)) {\n const names = def.presets?.map((p) => `\"${p.name}\"`).join(\", \");\n throw new Error(`\"${def.id}\" has no preset \"${options.preset}\"${names ? `; it has ${names}` : \"\"}.`);\n }\n const fps = positive(\"fps\", options.fps, 30);\n const start = options.start ?? 0;\n if (!Number.isFinite(start) || start < 0) throw new Error(`start must be 0 or more seconds (it was ${String(options.start)}).`);\n const duration = positive(\"duration\", options.duration, defaultDuration(def, options));\n let width = Math.round(positive(\"width\", options.width, 1280));\n let height = Math.round(positive(\"height\", options.height, 720));\n const explicitAlpha = options.alpha === true;\n let alpha = options.alpha ?? (def.kind === \"shader\" && Boolean(def.transparent));\n let format = options.format;\n if (format && ![\"mp4\", \"webm\", \"gif\", \"png\"].includes(format)) throw new Error(`format is one of \"mp4\", \"webm\", \"gif\" or \"png\" (it was \"${format}\").`);\n if (format === \"mp4\" && alpha) {\n if (explicitAlpha) throw new Error(`An mp4 (H.264) cannot keep transparency; record ${formats([\"webm\", \"png\", \"gif\"])} to keep it, or pass alpha: false.`);\n alpha = false;\n }\n\n let encoder: VideoEncoderConfig | undefined;\n if (format !== \"gif\" && format !== \"png\") {\n if (!hasWebCodecs())\n throw new Error(`This browser cannot encode video (it has no WebCodecs VideoEncoder), so it cannot record ${format ?? \"a video\"}; record ${formats([\"gif\", \"png\"])} instead.`);\n const w = even(width);\n const h = even(height);\n const bitrate = Math.round(positive(\"bitrate\", options.bitrate, w * h * fps * 0.15));\n const tryFormat = (f: \"mp4\" | \"webm\") => videoConfig(f, w, h, fps, bitrate);\n // Transparency needs webm; mp4 is the first choice otherwise, as it plays everywhere.\n const choices: (\"mp4\" | \"webm\")[] = format ? [format] : alpha ? [\"webm\"] : [\"mp4\", \"webm\"];\n for (const f of choices) {\n encoder = await tryFormat(f);\n if (encoder) {\n format = f;\n break;\n }\n }\n if (!encoder && !format && alpha && !explicitAlpha) {\n // Transparency was only the effect's default: an opaque mp4 will do.\n encoder = await tryFormat(\"mp4\");\n if (encoder) {\n format = \"mp4\";\n alpha = false;\n }\n }\n if (!encoder) {\n const asked = format ?? (alpha ? \"webm\" : \"mp4\");\n const other = asked === \"mp4\" ? \"webm\" : \"mp4\";\n if (alpha && asked === \"webm\") throw new Error(`This browser cannot encode VP8 or VP9, so it cannot record a webm with transparency; record ${formats([\"png\", \"gif\"])} to keep it, or pass alpha: false.`);\n const otherWorks = format && (await tryFormat(other));\n const codec = asked === \"mp4\" ? \"H.264\" : \"VP8 or VP9\";\n throw new Error(\n format\n ? `This browser cannot encode ${codec} at ${w} × ${h}, so it cannot record ${asked}; record ${formats(otherWorks ? [other, \"gif\", \"png\"] : [\"gif\", \"png\"])} instead.`\n : `This browser cannot encode H.264, VP8 or VP9 at ${w} × ${h}; record ${formats([\"gif\", \"png\"])} instead.`,\n );\n }\n width = w;\n height = h;\n }\n let audioEncoder: AudioEncoderConfig | undefined;\n if (options.audio !== undefined && options.audioTrack !== false && (format === \"mp4\" || format === \"webm\")) {\n audioEncoder = await audioConfig(format);\n if (!audioEncoder && format === \"mp4\" && !options.format) {\n // No AAC here: a webm (Opus) keeps the sound.\n const webm = await videoConfig(\"webm\", width, height, fps, encoder!.bitrate ?? Math.round(width * height * fps * 0.15));\n const opus = webm && (await audioConfig(\"webm\"));\n if (webm && opus) {\n format = \"webm\";\n encoder = webm;\n audioEncoder = opus;\n }\n }\n if (!audioEncoder) {\n const codec = format === \"mp4\" ? \"AAC\" : \"Opus\";\n throw new Error(`This browser cannot encode ${codec} audio, so it cannot put the sound in ${format === \"mp4\" ? \"an mp4\" : \"a webm\"}; ${format === \"mp4\" ? 'record \"webm\" (Opus), or ' : \"\"}pass audioTrack: false to record the picture alone (the sound still drives it).`);\n }\n }\n return { effect: def, format: format!, width, height, fps, duration, start, frames: Math.max(1, Math.round(duration * fps)), alpha, ...(encoder ? { encoder } : {}), ...(audioEncoder ? { audioEncoder } : {}) };\n}\n\n/** A shader's loop, or a vector effect's picture plus its hold, else 4 seconds. */\nfunction defaultDuration(def: EffectDefinition, options: RecordOptions): number {\n if (def.kind === \"shader\") return def.loop ?? DEFAULT_SECONDS;\n const motion = renderVectorEffect(def, effectValues(def, options).values);\n return (svgDuration(motion, options.steps ?? []) + (def.hold ?? 600)) / 1000;\n}\n\nfunction effectValues(def: EffectDefinition, options: RecordOptions) {\n const values = effectDefaults(def, { ...(options.preset ? { preset: options.preset } : {}), ...(options.values ? { values: options.values } : {}) });\n if (!options.subject) return { values, live: {} as Record<string, LiveSource> };\n const s = subjectValues(def, options.subject);\n return { values: { ...values, ...s.values }, live: s.live };\n}\n\n/** RGBA bytes of one frame. */\ntype Pixels = Uint8ClampedArray<ArrayBuffer>;\n\n/** Draws frames as straight (not premultiplied) RGBA, rows top down. */\ninterface FrameSource {\n frame(time: number, index: number, out: Pixels): Promise<void>;\n dispose(): void;\n}\n\nfunction shaderSource(plan: RecordingPlan, values: Record<string, ControlValue>, live: Record<string, LiveSource>, options: RecordOptions, sound?: AudioBufferAnalysis): FrameSource {\n const def = plan.effect as Extract<EffectDefinition, { kind: \"shader\" }>;\n // A transparent effect is drawn with its alpha even when it is not kept, to be laid over the background.\n const frames = new ShaderFrames({ source: def.source, values, width: plan.width, height: plan.height, alpha: plan.alpha || Boolean(def.transparent) });\n const videos: { video: HTMLVideoElement; time: number; paused: boolean }[] = [];\n for (const [name, source] of Object.entries(live)) {\n frames.setLiveSource(name, source);\n if (typeof HTMLVideoElement !== \"undefined\" && source instanceof HTMLVideoElement) {\n videos.push({ video: source, time: source.currentTime, paused: source.paused });\n source.pause();\n }\n }\n const script = options.pointer;\n return {\n async frame(time, index, out) {\n for (const { video } of videos) await seekVideo(video, time);\n await options.beforeFrame?.(time, index);\n await frames.ready();\n const pointer = typeof script === \"function\" ? script(time) : script;\n frames.render(time, { frame: index, delta: 1 / plan.fps, ...pointer, ...(sound ? { audio: sound.at(time) } : {}) });\n frames.readPixels(out);\n },\n dispose() {\n frames.dispose();\n for (const { video, time, paused } of videos) {\n video.currentTime = time;\n if (!paused) void video.play().catch(() => undefined);\n }\n },\n };\n}\n\nfunction vectorSource(plan: RecordingPlan, values: Record<string, ControlValue>, options: RecordOptions): FrameSource {\n const def = plan.effect as Extract<EffectDefinition, { kind: \"vector\" }>;\n const view = svgView(renderVectorEffect(def, values));\n // In the page (out of sight) so its fonts, sizes and colours resolve as they would on screen.\n const host = document.createElement(\"div\");\n host.setAttribute(\"aria-hidden\", \"true\");\n host.style.cssText = `position:fixed;left:-100000px;top:0;width:${plan.width}px;height:${plan.height}px;pointer-events:none;`;\n host.appendChild(view.element);\n document.body.appendChild(host);\n const steps = options.steps ?? [];\n return {\n async frame(time, index, out) {\n await options.beforeFrame?.(time, index);\n view.draw(time * 1000, steps);\n const canvas = await view.capture({ width: plan.width, height: plan.height });\n if (!canvas) throw new Error(`\"${def.id}\" has no picture to record: its SVG does not parse.`);\n out.set(canvas.getContext(\"2d\")!.getImageData(0, 0, plan.width, plan.height).data);\n },\n dispose: () => host.remove(),\n };\n}\n\n/** Lays straight-alpha pixels over an opaque colour, in place. */\nfunction flatten(rgba: Pixels, background: [number, number, number]) {\n const [br, bg, bb] = background;\n for (let i = 0; i < rgba.length; i += 4) {\n const a = rgba[i + 3]!;\n if (a === 255) continue;\n const k = a / 255;\n rgba[i] = rgba[i]! * k + br * (1 - k);\n rgba[i + 1] = rgba[i + 1]! * k + bg * (1 - k);\n rgba[i + 2] = rgba[i + 2]! * k + bb * (1 - k);\n rgba[i + 3] = 255;\n }\n}\n\n/** Turns frames into a file, one at a time. */\ninterface Encoder {\n add(rgba: Pixels, index: number): Promise<void>;\n finish(): Promise<Blob>;\n close(): void;\n}\n\nasync function gifEncoder(plan: RecordingPlan): Promise<Encoder> {\n const { GIFEncoder, quantize, applyPalette } = await import(\"gifenc\");\n const gif = GIFEncoder();\n const delay = 1000 / plan.fps;\n return {\n async add(rgba, i) {\n const repeat = i === 0 ? { repeat: 0 } : {};\n if (!plan.alpha) {\n const palette = quantize(rgba, 256);\n gif.writeFrame(applyPalette(rgba, palette), plan.width, plan.height, { palette, delay, ...repeat });\n return;\n }\n // One colour is see-through: pixels at most half covered. Each frame replaces the last (dispose 2).\n const palette = quantize(rgba, 256, { format: \"rgba4444\", oneBitAlpha: true });\n const transparentIndex = palette.findIndex((c) => c[3] === 0);\n gif.writeFrame(applyPalette(rgba, palette, \"rgba4444\"), plan.width, plan.height, {\n palette,\n delay,\n dispose: 2,\n ...(transparentIndex >= 0 ? { transparent: true, transparentIndex } : {}),\n ...repeat,\n });\n },\n async finish() {\n gif.finish();\n return new Blob([gif.bytes()], { type: \"image/gif\" });\n },\n close() {},\n };\n}\n\nfunction pngEncoder(plan: RecordingPlan): Encoder {\n const canvas = document.createElement(\"canvas\");\n canvas.width = plan.width;\n canvas.height = plan.height;\n const context = canvas.getContext(\"2d\");\n if (!context) throw new Error(\"This browser cannot draw on a canvas, so it cannot make PNG frames.\");\n const entries: ZipEntry[] = [];\n const digits = Math.max(4, String(plan.frames).length);\n return {\n async add(rgba, i) {\n context.putImageData(new ImageData(rgba, plan.width, plan.height), 0, 0);\n const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, \"image/png\"));\n if (!blob) throw new Error(\"The browser could not encode a PNG frame.\");\n entries.push({ name: `frame-${String(i + 1).padStart(digits, \"0\")}.png`, data: new Uint8Array(await blob.arrayBuffer()) });\n },\n async finish() {\n return new Blob([zipStore(entries) as Uint8Array<ArrayBuffer>], { type: \"application/zip\" });\n },\n close() {},\n };\n}\n\nconst bytesOf = (source: AllowSharedBufferSource) =>\n source instanceof ArrayBuffer || (typeof SharedArrayBuffer !== \"undefined\" && source instanceof SharedArrayBuffer)\n ? new Uint8Array(source.slice(0))\n : new Uint8Array((source as ArrayBufferView).buffer.slice((source as ArrayBufferView).byteOffset, (source as ArrayBufferView).byteOffset + (source as ArrayBufferView).byteLength));\n\n/** A WebCodecs encoder whose chunks are collected, with the first decoder description it gives. */\nfunction collector(config: VideoEncoderConfig, fail: (e: Error) => void) {\n const chunks: { data: Uint8Array; timestamp: number; duration?: number; key: boolean }[] = [];\n const out = { chunks, description: undefined as Uint8Array | undefined, encoder: undefined as unknown as VideoEncoder };\n out.encoder = new VideoEncoder({\n output(chunk, metadata) {\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n const desc = metadata?.decoderConfig?.description;\n if (desc && !out.description) out.description = bytesOf(desc);\n chunks.push({ data, timestamp: chunk.timestamp, ...(chunk.duration ? { duration: chunk.duration } : {}), key: chunk.type === \"key\" });\n },\n error: (e) => fail(new Error(`The video encoder failed: ${e.message}`, { cause: e })),\n });\n out.encoder.configure(config);\n return out;\n}\n\n/** Fetches and decodes an audio file at {@link AUDIO_RATE}. */\nasync function decodeAudio(url: string): Promise<AudioBuffer> {\n if (typeof OfflineAudioContext === \"undefined\") throw new Error(\"This browser has no Web Audio (OfflineAudioContext), so it cannot decode the audio.\");\n let bytes: ArrayBuffer;\n try {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n bytes = await response.arrayBuffer();\n } catch (e) {\n throw new Error(`The audio at ${url} could not be loaded (${(e as Error).message}); a file from another site needs CORS.`, { cause: e });\n }\n try {\n return await new OfflineAudioContext(2, 1, AUDIO_RATE).decodeAudioData(bytes);\n } catch (e) {\n throw new Error(`The audio at ${url} could not be decoded; give it an mp3, AAC, Ogg, Opus, FLAC or WAV file the browser plays.`, { cause: e });\n }\n}\n\n/** Encoded sound, ready to mux. */\ninterface EncodedSound {\n codec: \"aac\" | \"opus\";\n sampleRate: number;\n channels: number;\n description?: Uint8Array;\n chunks: { data: Uint8Array; timestamp: number; duration?: number; key: boolean }[];\n}\n\n/**\n * The stretch of `buffer` a recording covers, at 48 kHz stereo (rendered by\n * an `OfflineAudioContext`, which resamples and mixes), encoded with\n * WebCodecs.\n */\nasync function encodeSound(buffer: AudioBuffer, plan: RecordingPlan): Promise<EncodedSound> {\n const config = plan.audioEncoder!;\n const channels = config.numberOfChannels;\n const length = Math.max(1, Math.round(plan.duration * AUDIO_RATE));\n const offline = new OfflineAudioContext(channels, length, AUDIO_RATE);\n const node = offline.createBufferSource();\n node.buffer = buffer;\n node.connect(offline.destination);\n node.start(0, Math.min(plan.start, buffer.duration));\n const rendered = await offline.startRendering();\n const out: EncodedSound = { codec: config.codec === \"opus\" ? \"opus\" : \"aac\", sampleRate: AUDIO_RATE, channels, chunks: [] };\n let failure: Error | undefined;\n const encoder = new AudioEncoder({\n output(chunk, metadata) {\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n const desc = metadata?.decoderConfig?.description;\n if (desc && !out.description) out.description = bytesOf(desc);\n out.chunks.push({ data, timestamp: chunk.timestamp, ...(chunk.duration ? { duration: chunk.duration } : {}), key: true });\n },\n error: (e) => (failure ??= new Error(`The audio encoder failed: ${e.message}`, { cause: e })),\n });\n encoder.configure(config);\n const block = 4800;\n for (let at = 0; at < length; at += block) {\n const n = Math.min(block, length - at);\n const planes = new Float32Array(n * channels);\n for (let c = 0; c < channels; c++) planes.set(rendered.getChannelData(c).subarray(at, at + n), c * n);\n const data = new AudioData({ format: \"f32-planar\", sampleRate: AUDIO_RATE, numberOfFrames: n, numberOfChannels: channels, timestamp: Math.round((at * 1e6) / AUDIO_RATE), data: planes });\n try {\n encoder.encode(data);\n } finally {\n data.close();\n }\n }\n await encoder.flush();\n encoder.close();\n if (failure) throw failure;\n out.chunks.sort((a, b) => a.timestamp - b.timestamp);\n return out;\n}\n\n/**\n * Encodes with WebCodecs and muxes into mp4 or webm. With `alpha`, a second\n * encoder (same codec) takes the alpha as a greyscale picture, and each\n * frame's alpha goes beside it in the webm, as Chrome's own recordings do:\n * browsers' encoders do not keep alpha themselves.\n */\nfunction videoEncoder(plan: RecordingPlan, sound?: Promise<EncodedSound>): Encoder {\n const config = plan.encoder!;\n let failure: Error | undefined;\n const fail = (e: Error) => (failure ??= e);\n const color = collector(config, fail);\n const alpha = plan.alpha ? collector(config, fail) : undefined;\n const encoders = [color.encoder, ...(alpha ? [alpha.encoder] : [])];\n const frameUs = 1e6 / plan.fps;\n // A keyframe every two seconds, so players can seek.\n const keyEvery = Math.max(1, Math.round(plan.fps * 2));\n const { width, height } = plan;\n // I420: the alpha as luma, with neutral chroma.\n const plane = alpha ? new Uint8Array(width * height * 1.5).fill(128) : undefined;\n const check = () => {\n if (failure) throw failure;\n };\n const encode = (encoder: VideoEncoder, frame: VideoFrame, key: boolean) => {\n try {\n encoder.encode(frame, { keyFrame: key });\n } finally {\n frame.close();\n }\n };\n return {\n async add(rgba, i) {\n check();\n const timing = { codedWidth: width, codedHeight: height, timestamp: Math.round(i * frameUs), duration: Math.round(frameUs) };\n const key = i % keyEvery === 0;\n encode(color.encoder, new VideoFrame(rgba, { format: \"RGBX\", ...timing }), key);\n if (alpha && plane) {\n for (let p = 0, q = 3; p < width * height; p++, q += 4) plane[p] = rgba[q]!;\n encode(alpha.encoder, new VideoFrame(plane, { format: \"I420\", ...timing }), key);\n }\n // Hold back while an encoder is behind, so frames don't pile up in memory.\n while (encoders.some((e) => e.encodeQueueSize > 4) && !failure) await new Promise((resolve) => setTimeout(resolve, 1));\n },\n async finish() {\n await Promise.all(encoders.map((e) => e.flush()));\n check();\n for (const e of encoders) e.close();\n const byTime = (a: { timestamp: number }, b: { timestamp: number }) => a.timestamp - b.timestamp;\n const chunks = color.chunks.sort(byTime);\n const audio = await sound;\n if (plan.format === \"mp4\") {\n if (!color.description) throw new Error(\"The H.264 encoder gave no decoder configuration (avcC), so the mp4 cannot be written.\");\n const file = muxMp4({\n width,\n height,\n avcC: color.description,\n samples: chunks,\n ...(audio ? { audio: { sampleRate: audio.sampleRate, channels: audio.channels, ...(audio.description ? { config: audio.description } : {}), samples: audio.chunks } } : {}),\n });\n return new Blob([file as Uint8Array<ArrayBuffer>], { type: \"video/mp4\" });\n }\n const alphas = new Map(alpha?.chunks.map((c) => [c.timestamp, c.data]));\n const frames: WebmFrame[] = chunks.map((c) => {\n const a = alphas.get(c.timestamp);\n if (alpha && !a) throw new Error(`The alpha encoder dropped the frame at ${c.timestamp / 1e6} s, so the webm cannot keep transparency; record \"png\" or \"gif\" instead.`);\n return { ...c, ...(a ? { alpha: a } : {}) };\n });\n const codec = config.codec.startsWith(\"vp8\") ? \"vp8\" : \"vp9\";\n const file = muxWebm({\n codec,\n width,\n height,\n frames,\n duration: plan.frames * frameUs,\n fps: plan.fps,\n ...(audio ? { audio: { sampleRate: audio.sampleRate, channels: audio.channels, ...(audio.description ? { codecPrivate: audio.description } : {}), packets: audio.chunks } } : {}),\n });\n return new Blob([file as Uint8Array<ArrayBuffer>], { type: \"video/webm\" });\n },\n close() {\n for (const e of encoders) if (e.state !== \"closed\") e.close();\n },\n };\n}\n\n/**\n * Records a catalog effect (by id or definition), applied to `subject`, to a\n * file in the browser: an `mp4` or `webm` video (WebCodecs, muxed here with\n * no dependencies), an animated `gif`, or `png` frames.\n *\n * Frames are drawn off screen at exact times (`start + i / fps`), so the\n * result is smooth whatever the page's frame rate, and the same on every\n * machine. Shaders render with `ShaderFrames` (a `<video>` subject is paused\n * and sought to each frame, and put back after); vector effects are drawn\n * with `svgView` and rasterised. Shaders that answer the pointer play their\n * idle demos unless `pointer` scripts it. With `audio`, audio-reactive\n * shaders follow the sound frame for frame, and videos carry it as their\n * sound track.\n *\n * `png` resolves to a ZIP of numbered frames (`frame-0001.png`, …), so every\n * format is one `Blob` to save or upload.\n *\n * Rejects with a sentence when the effect is unknown, takes no such\n * subject, or the browser cannot make the format (naming the formats that\n * would work); with a `ShaderCompileError` or `ImageLoadError` as\n * `ShaderFrames` does; and with an `AbortError` when `signal` aborts.\n *\n * ```ts\n * const mp4 = await recordEffect(\"image-duotone\", { subject: { image: \"/team.jpg\" }, preset: \"Spotify\" });\n * const gif = await recordEffect(\"typewriter\", { subject: { text: \"Hello\" }, format: \"gif\", width: 640, height: 360, fps: 25 });\n * const webm = await recordEffect(\"click-ripple\", { format: \"webm\", alpha: true, pointer: { clicks: [{ x: 640, y: 360, time: 0.2 }] } });\n * const music = await recordEffect(\"spectrum-bars\", { audio: \"/song.mp3\", duration: 10 });\n * ```\n */\nexport async function recordEffect(effect: EffectDefinition | string, options: RecordOptions = {}): Promise<Blob> {\n const plan = await recordingPlan(effect, options);\n const { signal, onProgress } = options;\n const { values, live } = effectValues(plan.effect, options);\n const background = (parseColor(options.background ?? (plan.effect.kind === \"shader\" ? \"#000000\" : \"#ffffff\")) ?? [0, 0, 0]).map((c) => Math.round(c * 255)) as [number, number, number];\n\n const buffer = options.audio === undefined ? undefined : typeof options.audio === \"string\" ? await decodeAudio(options.audio) : options.audio;\n const sound = buffer && plan.effect.kind === \"shader\" && effectInputs(plan.effect).accepts.includes(\"audio\") ? analyseAudioBuffer(buffer) : undefined;\n // The sound track encodes alongside the frames.\n const track = buffer && plan.audioEncoder ? encodeSound(buffer, plan) : undefined;\n track?.catch(() => undefined);\n const source = plan.effect.kind === \"shader\" ? shaderSource(plan, values, live, options, sound) : vectorSource(plan, values, options);\n let encoder: Encoder | undefined;\n try {\n encoder = plan.format === \"gif\" ? await gifEncoder(plan) : plan.format === \"png\" ? pngEncoder(plan) : videoEncoder(plan, track);\n const rgba = new Uint8ClampedArray(plan.width * plan.height * 4);\n for (let i = 0; i < plan.frames; i++) {\n if (signal?.aborted) throw new DOMException(\"Cancelled\", \"AbortError\");\n await source.frame(plan.start + i / plan.fps, i, rgba);\n if (!plan.alpha) flatten(rgba, background);\n await encoder.add(rgba, i);\n onProgress?.((i + 1) / plan.frames);\n if (i % 2 === 1) await yieldToBrowser();\n }\n if (signal?.aborted) throw new DOMException(\"Cancelled\", \"AbortError\");\n return await encoder.finish();\n } finally {\n encoder?.close();\n source.dispose();\n }\n}\n","/**\n * Catalog effects on a page in one call: pick an effect, give it what it\n * takes (a picture, a video, an SVG, words or a path) and get it running.\n *\n * - Pairing: `subjectValues` turns a subject into the control values (and\n * live sources) an effect needs, using `effectInputs`.\n * - Embedding: `mountEffect` runs a shader effect (`ShaderRenderer`) or a\n * vector effect (`SvgPlayer`) in an element, with its subject.\n *\n * @packageDocumentation\n */\n\nimport { effectDefaults, effectInputs, getEffect, textImage, type EffectDefinition, type ImageSlot, type TextSlot } from \"../catalog/index.js\";\nimport { renderVectorEffect } from \"../catalog/types.js\";\nimport type { AudioSource } from \"../shader/audio.js\";\nimport type { ControlValue } from \"../shader/controls.js\";\nimport { ShaderRenderer } from \"../shader/renderer.js\";\nimport type { LiveSource } from \"../shader/textures.js\";\nimport { SvgPlayer } from \"../vector/svg.js\";\n\nexport { recordEffect, recordingPlan, type RecordFormat, type RecordOptions, type RecordPointer, type RecordingPlan } from \"./record.js\";\n\n/**\n * What an effect is applied to:\n * - `{ image }`: a picture's URL (or `data:` URL).\n * - `{ video }`: a playing `<video>` (or a canvas), shown live.\n * - `{ svg }`: an SVG, as markup (`\"<svg …>\"`) or a URL; drawn as a picture, keeping its transparency.\n * - `{ text }`: words, for a vector effect's text, or drawn with `textImage` for a shader's text or mask.\n * - `{ path }`: SVG path data (`d`), for a shape control.\n * - `{ audio }`: sound for an audio-reactive shader (`iAudio`, `iSpectrum`,\n * `iBeat`): a playing `<audio>` or `<video>` (still heard), a microphone's\n * `MediaStream` (not played back) or a Web Audio node. See\n * `ShaderRenderer.setAudioSource`; to record, pass `audio` to `recordEffect`.\n */\nexport type EffectSubject =\n | { image: string }\n | { video: LiveSource }\n | { svg: string }\n | { text: string; font?: string; weight?: number | string }\n | { path: string }\n | { audio: AudioSource };\n\n/** What a subject becomes for an effect: control values, live sources by image control, and the sound it hears. */\nexport interface SubjectValues {\n values: Record<string, ControlValue>;\n live: Record<string, LiveSource>;\n /** The sound, from an `{ audio }` subject. */\n audio?: AudioSource;\n}\n\nconst kindOf = (subject: EffectSubject) => Object.keys(subject).find((k) => k !== \"font\" && k !== \"weight\") as \"image\" | \"video\" | \"svg\" | \"text\" | \"path\" | \"audio\";\n\n/** An SVG as a URL: markup becomes a UTF-8 `data:` URL; a URL stays as it is. */\nfunction svgUrl(svg: string): string {\n const markup = svg.trim();\n if (!markup.startsWith(\"<\")) return svg;\n const withNs = /\\sxmlns\\s*=/.test(markup.slice(0, markup.indexOf(\">\") + 1)) ? markup : markup.replace(/^<svg/i, '<svg xmlns=\"http://www.w3.org/2000/svg\"');\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(withNs)}`;\n}\n\nfunction pick<T extends { name: string }>(slots: T[], wanted: (s: T) => boolean, name: string | undefined, effect: EffectDefinition, what: string): T {\n const slot = name ? slots.find((s) => s.name === name) : slots.find(wanted);\n if (!slot) {\n const names = slots.map((s) => s.name).join(\", \");\n throw new Error(\n name\n ? `\"${effect.id}\" has no control \"${name}\" for ${what}${names ? `; it has ${names}` : \"\"}.`\n : `\"${effect.id}\" takes no ${what}; see effectInputs(effect).accepts, or findEffects({ accepts: [...] }) for effects that do.`,\n );\n }\n return slot;\n}\n\n/**\n * The control values (and live sources) that put `subject` in `effect`,\n * into the control named `slot` or the first that suits it: a picture or\n * SVG into an image control, a video into a picture control as a live\n * source, words into a vector effect's text or (drawn by `textImage`) a\n * shader's text or mask control, path data into a shape control. Several\n * subjects fill several controls in order (a transition's from and to).\n * Throws a sentence when the effect takes no such thing.\n */\nexport function subjectValues(effect: EffectDefinition, subject: EffectSubject | readonly EffectSubject[], slot?: string): SubjectValues {\n const out: SubjectValues = { values: {}, live: {} };\n const inputs = effectInputs(effect);\n const used = new Set<string>();\n for (const s of Array.isArray(subject) ? subject : [subject as EffectSubject]) {\n const kind = kindOf(s);\n const free = <T extends { name: string }>(slots: T[]) => slots.filter((x) => !used.has(x.name));\n if (kind === \"audio\") {\n if (!inputs.accepts.includes(\"audio\"))\n throw new Error(`\"${effect.id}\" does not react to sound; findEffects({ accepts: [\"audio\"] }) lists the effects that do.`);\n out.audio = (s as { audio: AudioSource }).audio;\n continue;\n }\n if (kind === \"path\" || (kind === \"text\" && effect.kind === \"vector\")) {\n const holds = kind === \"path\" ? \"path\" : \"copy\";\n const text = pick<TextSlot>(free(inputs.texts), (t) => t.holds === holds, slot, effect, kind === \"path\" ? \"path data\" : \"text\");\n out.values[text.name] = kind === \"path\" ? (s as { path: string }).path : (s as { text: string }).text;\n used.add(text.name);\n continue;\n }\n if (effect.kind === \"vector\")\n throw new Error(`\"${effect.id}\" is a vector effect: it draws its own picture and takes words or path data (${inputs.accepts.join(\", \") || \"nothing\"}), not ${{ svg: \"an SVG\", image: \"an image\", video: \"a video\" }[kind as \"svg\" | \"image\" | \"video\"]}.`);\n const wanted = (x: ImageSlot) =>\n kind === \"text\" ? x.wants !== \"picture\" : kind === \"video\" ? x.wants === \"picture\" : true;\n const image = pick<ImageSlot>(free(inputs.images), wanted, slot, effect, kind === \"text\" ? \"text\" : `${kind === \"svg\" ? \"SVG\" : kind}`);\n used.add(image.name);\n if (kind === \"video\") {\n if (!inputs.accepts.includes(\"video\")) throw new Error(`\"${effect.id}\" is not made for video (video: \"${inputs.video}\"); give it a picture.`);\n out.live[image.name] = (s as { video: LiveSource }).video;\n } else if (kind === \"text\") {\n const t = s as { text: string; font?: string; weight?: number | string };\n out.values[image.name] = textImage(t.text, { ...(t.font ? { font: t.font } : {}), ...(t.weight !== undefined ? { weight: t.weight } : {}) });\n } else out.values[image.name] = kind === \"svg\" ? svgUrl((s as { svg: string }).svg) : (s as { image: string }).image;\n }\n return out;\n}\n\nexport interface MountOptions {\n /** What to apply the effect to (see {@link EffectSubject}); several fill several controls in order. */\n subject?: EffectSubject | readonly EffectSubject[];\n /** A preset by name, then these values, over the effect's defaults. */\n preset?: string;\n values?: Record<string, ControlValue>;\n /** Start playing at once (default true). */\n autoplay?: boolean;\n /** Class for the canvas (shaders) or the player's element (vector effects). */\n className?: string;\n /** Pause while scrolled out of view (default true). */\n pauseWhenHidden?: boolean;\n}\n\n/** A running effect, from {@link mountEffect}. */\nexport interface MountedEffect {\n readonly effect: EffectDefinition;\n /** What it draws into: the shader's canvas, or the vector player's element. */\n readonly element: HTMLElement;\n /** The shader renderer, for a shader effect. */\n readonly renderer?: ShaderRenderer;\n /** The vector player, for a vector effect (replaced when values change). */\n readonly player?: SvgPlayer;\n /** Applies it to something else. */\n setSubject(subject: EffectSubject | readonly EffectSubject[]): void;\n /** Changes control values (merged over the current ones). */\n setValues(values: Record<string, ControlValue>): void;\n play(): void;\n pause(): void;\n /** Stops it and removes what it drew. */\n dispose(): void;\n}\n\n/**\n * Runs a catalog effect (by id or definition) in `host`, applied to\n * `subject`: a shader on a canvas (transparent for overlays, so it lays over\n * the page), or a vector effect in an SVG player that answers its trigger\n * (hover, press, click, scroll). Shaders that read `iScroll` follow the\n * page's scrolling, and audio-reactive shaders hear an `{ audio }` subject.\n * Throws a sentence when the effect is unknown or takes no such subject.\n *\n * ```ts\n * mountEffect(el, \"image-duotone\", { subject: { image: \"/team.jpg\" }, preset: \"Spotify\" });\n * mountEffect(el, \"crt\", { subject: { video: videoElement } });\n * mountEffect(el, \"typewriter\", { subject: { text: \"Hello there\" } });\n * mountEffect(el, \"neon-outline\", { subject: { svg: logoMarkup } });\n * mountEffect(el, \"spectrum-bars\", { subject: { audio: audioElement } });\n * ```\n */\nexport function mountEffect(host: HTMLElement, effect: EffectDefinition | string, options: MountOptions = {}): MountedEffect {\n const def = typeof effect === \"string\" ? getEffect(effect) : effect;\n if (!def) throw new Error(`There is no effect \"${String(effect)}\" in the catalog; findEffects() lists them.`);\n let values: Record<string, ControlValue> = { ...effectDefaults(def, { ...(options.preset ? { preset: options.preset } : {}), ...(options.values ? { values: options.values } : {}) }) };\n let live: Record<string, LiveSource> = {};\n let audio: AudioSource | undefined;\n const apply = (subject: EffectSubject | readonly EffectSubject[] | undefined) => {\n if (!subject) return;\n const s = subjectValues(def, subject);\n values = { ...values, ...s.values };\n live = s.live;\n audio = s.audio;\n };\n apply(options.subject);\n\n if (def.kind === \"shader\") {\n const renderer = new ShaderRenderer(host, {\n alpha: Boolean(def.transparent),\n autoplay: options.autoplay ?? true,\n pauseWhenHidden: options.pauseWhenHidden ?? true,\n ...(options.className ? { className: options.className } : {}),\n });\n renderer.setSource(def.source);\n renderer.setValues(values);\n const setLive = (previous: Record<string, LiveSource>) => {\n for (const name of Object.keys(previous)) if (!(name in live)) renderer.setLiveSource(name, null);\n for (const [name, source] of Object.entries(live)) renderer.setLiveSource(name, source);\n };\n setLive({});\n if (audio) renderer.setAudioSource(audio);\n return {\n effect: def,\n element: renderer.canvas,\n renderer,\n setSubject(subject) {\n const before = live;\n const heard = audio;\n apply(subject);\n renderer.setValues(values);\n setLive(before);\n if (audio !== heard) renderer.setAudioSource(audio ?? null);\n },\n setValues(next) {\n values = { ...values, ...next };\n renderer.setValues(values);\n },\n play: () => renderer.play(),\n pause: () => renderer.pause(),\n dispose: () => renderer.dispose(),\n };\n }\n\n let player: SvgPlayer;\n const build = () => {\n player?.dispose();\n player = new SvgPlayer(host, renderVectorEffect(def, values), {\n hold: def.hold,\n ...(def.trigger ? { trigger: def.trigger } : {}),\n autoplay: options.autoplay ?? true,\n pauseWhenHidden: options.pauseWhenHidden ?? true,\n });\n if (options.className) player.view.element.className = options.className;\n };\n build();\n return {\n effect: def,\n get element() {\n return player.view.element;\n },\n get player() {\n return player;\n },\n setSubject(subject) {\n apply(subject);\n build();\n },\n setValues(next) {\n values = { ...values, ...next };\n build();\n },\n play: () => player.play(),\n pause: () => player.pause(),\n dispose: () => player.dispose(),\n };\n}\n"],"mappings":"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","names":["palette","file"]}
|
|
@@ -5,20 +5,20 @@ import {
|
|
|
5
5
|
pageControls,
|
|
6
6
|
planOutput,
|
|
7
7
|
runRender
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7KYQ4R76.js";
|
|
9
9
|
import {
|
|
10
10
|
svgAnimatedMarkup
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-X3C2VFTM.js";
|
|
12
12
|
import {
|
|
13
13
|
svgFrameMarkup,
|
|
14
14
|
svgViewBox
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-AUH3PEFW.js";
|
|
16
16
|
import {
|
|
17
17
|
subjectValues
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-KZYZX3V5.js";
|
|
19
19
|
import {
|
|
20
20
|
wrapSource
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-HDYBY3PQ.js";
|
|
22
22
|
import {
|
|
23
23
|
EFFECT_CATEGORIES,
|
|
24
24
|
EFFECT_INPUTS,
|
|
@@ -28,14 +28,14 @@ import {
|
|
|
28
28
|
effectInputs,
|
|
29
29
|
getEffect,
|
|
30
30
|
renderVectorEffect
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6GFOLHCT.js";
|
|
32
32
|
import {
|
|
33
33
|
checkControlValue,
|
|
34
34
|
parseColor
|
|
35
35
|
} from "./chunk-VYOMXE6I.js";
|
|
36
36
|
import {
|
|
37
37
|
svgDuration
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-DA4UUSDO.js";
|
|
39
39
|
|
|
40
40
|
// src/export/effect.ts
|
|
41
41
|
import { spawn } from "child_process";
|
|
@@ -110,7 +110,7 @@ var REST = 300;
|
|
|
110
110
|
function vectorTimeline(effect, motion) {
|
|
111
111
|
const hold = effect.hold ?? 600;
|
|
112
112
|
const d = svgDuration(motion);
|
|
113
|
-
if (effect.trigger === "hover" || effect.trigger === "press") {
|
|
113
|
+
if (effect.trigger === "hover" || effect.trigger === "press" || effect.trigger === "scroll") {
|
|
114
114
|
const length2 = REST + d + hold + d;
|
|
115
115
|
return {
|
|
116
116
|
length: length2,
|
|
@@ -411,4 +411,4 @@ export {
|
|
|
411
411
|
effectQueryFromFlags,
|
|
412
412
|
describeEffect
|
|
413
413
|
};
|
|
414
|
-
//# sourceMappingURL=chunk-
|
|
414
|
+
//# sourceMappingURL=chunk-MBKNTXQX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/export/effect.ts"],"sourcesContent":["/**\n * Renders a catalog effect, applied to a subject, to a file in Node: video\n * (MP4, WebM, MOV), GIF, PNG frames, or (vector effects) an animated SVG.\n */\n\nimport { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport {\n EFFECT_CATEGORIES,\n EFFECT_INPUTS,\n EFFECT_INTERACTIONS,\n effectControls,\n effectDefaults,\n effectInputs,\n getEffect,\n renderVectorEffect,\n type EffectCategory,\n type EffectDefinition,\n type EffectInput,\n type EffectInteraction,\n type VectorEffect,\n} from '../catalog/index.js';\nimport { subjectValues, type EffectSubject } from '../embed/index.js';\nimport { checkControlValue, parseColor, type ControlDef, type ControlValue } from '../shader/controls.js';\nimport { wrapSource } from '../shader/program.js';\nimport { svgAnimatedMarkup } from '../vector/animated.js';\nimport type { SvgMotion } from '../vector/motion.js';\nimport { svgFrameMarkup, svgViewBox } from '../vector/static.js';\nimport { svgDuration } from '../vector/svg.js';\nimport {\n ffmpegPath,\n frameStates,\n imageDataUrl,\n pageControls,\n planOutput,\n runRender,\n type FrameState,\n type PointerMode,\n} from './recorder.js';\n\n/**\n * What an effect is applied to, in Node:\n * - `{ image }`: a picture's file path or URL (or a `data:` URL).\n * - `{ svg }`: an SVG's file path, URL, or markup (`\"<svg …>\"`).\n * - `{ text }`: words, for a vector effect's text, or drawn with `textImage` for a shader's text or mask.\n * - `{ path }`: SVG path data (`d`), for a shape control.\n * - `{ video }`: a video file's path, decoded to frames with ffmpeg and shown one per frame.\n */\nexport type NodeSubject =\n | { image: string }\n | { svg: string }\n | { text: string; font?: string; weight?: number | string }\n | { path: string }\n | { video: string };\n\nexport interface EffectExportOptions {\n /** What to apply it to; several fill several controls in order (a transition's from and to). */\n subject?: NodeSubject | readonly NodeSubject[];\n /** A preset by name, under `values`. */\n preset?: string;\n /** Control values over the defaults (and the subject). An image control also takes a file path. */\n values?: Record<string, ControlValue>;\n /** .mp4, .webm, .mov, .gif, .svg (vector effects), or PNG frames (a folder, or `out_%04d.png`). */\n outputPath: string;\n /** Pixels (default: 1280 × 720 for effects that show a picture, 720 × 720 for other shaders, a vector's own shape 720 px on its long edge). */\n width?: number;\n height?: number;\n fps?: number;\n /**\n * Seconds. Default: a shader's loop (when it loops in 12 s or less), a\n * video subject's length (up to 10 s), else 3; a vector effect's one\n * play-through (with its trigger acted out).\n */\n duration?: number;\n /** Keep transparency (WebM, MOV, GIF, PNG and SVG; MP4 is always opaque). */\n alpha?: boolean;\n /** CSS colour under transparent pixels without `alpha` (default black for shaders, white for vector effects). */\n background?: string;\n /**\n * The pointer, for effects that answer it: `auto` (the default for them),\n * a scripted pointer that hovers, wanders and clicks; `none` leaves it\n * still. Vector effects with a trigger have it acted out (clicked through\n * their steps, or hovered and let go).\n */\n pointer?: PointerMode;\n onProgress?: (frame: number, total: number) => void;\n}\n\nconst isUrl = (s: string) => /^(https?|data):/i.test(s);\n\n/** An SVG subject as markup: given markup stays, a URL is fetched, a path read. */\nasync function svgMarkup(svg: string): Promise<string> {\n const text = svg.trim();\n if (text.startsWith('<')) return text;\n if (/^data:image\\/svg\\+xml/i.test(text)) {\n const comma = text.indexOf(',');\n const meta = text.slice(0, comma);\n const body = text.slice(comma + 1);\n return /;base64/i.test(meta) ? Buffer.from(body, 'base64').toString('utf8') : decodeURIComponent(body);\n }\n if (/^https?:/i.test(text)) {\n const res = await fetch(text);\n if (!res.ok) throw new Error(`Could not download the SVG at ${text} (HTTP ${res.status}).`);\n return res.text();\n }\n const file = path.resolve(text);\n if (!fs.existsSync(file)) throw new Error(`There is no SVG at ${file}; give a file path, a URL, or markup starting with \"<svg\".`);\n return fs.readFileSync(file, 'utf8');\n}\n\n/** What a Node subject becomes: control values, and video files by image control. */\nexport interface NodeSubjectValues {\n values: Record<string, ControlValue>;\n /** Image control → video file. */\n video: Record<string, string>;\n}\n\n/**\n * The control values that put Node subjects in `effect` (see\n * `subjectValues` in `@pixerate/flair/embed`, which picks the controls):\n * image files and URLs become `data:` URLs, SVG files and URLs are read as\n * markup, and a video is kept as its file for its control, to be decoded to\n * frames. Throws a sentence when the effect takes no such thing.\n */\nexport async function nodeSubjectValues(effect: EffectDefinition, subject: NodeSubject | readonly NodeSubject[]): Promise<NodeSubjectValues> {\n const list = (Array.isArray(subject) ? subject : [subject]) as readonly NodeSubject[];\n const browser: EffectSubject[] = [];\n const videoFiles: string[] = [];\n for (const s of list) {\n if ('image' in s) browser.push({ image: await imageDataUrl(s.image) });\n else if ('svg' in s) browser.push({ svg: await svgMarkup(s.svg) });\n else if ('video' in s) {\n const file = path.resolve(s.video);\n if (!isUrl(s.video) && !fs.existsSync(file)) throw new Error(`There is no video at ${file}.`);\n videoFiles.push(isUrl(s.video) ? s.video : file);\n // A stand-in: subjectValues only needs to know it is a video to pick its control.\n browser.push({ video: { readyState: 0, currentTime: 0 } as unknown as HTMLVideoElement });\n } else browser.push(s);\n }\n const { values, live } = subjectValues(effect, browser);\n const video: Record<string, string> = {};\n Object.keys(live).forEach((name, i) => (video[name] = videoFiles[i]!));\n return { values, video };\n}\n\n/** The effect for an id (or the definition itself); a sentence when there is none. */\nexport function resolveEffect(effect: string | EffectDefinition): EffectDefinition {\n if (typeof effect !== 'string') return effect;\n const def = getEffect(effect);\n if (!def) throw new Error(`There is no effect \"${effect}\" in the catalog; \"flair effects\" (or findEffects()) lists them.`);\n return def;\n}\n\n/**\n * Checks control values against an effect's controls: unknown names, and\n * values a control cannot take, are sentences. Image controls take file\n * paths too (read into `data:` URLs).\n */\nexport async function checkEffectValues(effect: EffectDefinition, values: Record<string, ControlValue>): Promise<Record<string, ControlValue>> {\n const controls = new Map(effectControls(effect).map((c) => [c.name, c]));\n const out: Record<string, ControlValue> = {};\n for (const [name, raw] of Object.entries(values)) {\n const control = controls.get(name);\n if (!control) throw new Error(`\"${effect.id}\" has no control \"${name}\"; it has ${[...controls.keys()].join(', ') || 'none'}.`);\n if (control.type === 'sampler2D' && typeof raw === 'string') {\n out[name] = await imageDataUrl(raw);\n continue;\n }\n if (effect.kind === 'vector' && control.color && typeof raw === 'string' && raw.trim().toLowerCase() === 'currentcolor') {\n out[name] = raw;\n continue;\n }\n const check = checkControlValue(control, raw);\n if (!check.ok) throw new Error(check.message);\n out[name] = check.value;\n }\n return out;\n}\n\n/** How a vector effect plays over time in a recording: the frame at each ms, and its loop. */\nexport interface VectorTimeline {\n /** One play-through, ms. */\n length: number;\n /** Step start times (ms) for the whole loop, for an animated SVG. */\n steps: number[];\n /** The picture's time and steps at `ms` into the recording. */\n at(ms: number): { time: number; steps: number[] };\n}\n\n/** Ms an effect rests before its trigger is acted out. */\nconst REST = 300;\n\n/**\n * A vector effect's timeline: a loop plays and rests `hold` ms; a hover, press or\n * scroll trigger plays to the end, rests, and plays back (a scroll down and up); a click trigger is\n * clicked through each of its steps (or, with none, clicked again after\n * each play-through).\n */\nexport function vectorTimeline(effect: Pick<VectorEffect, 'hold' | 'trigger'>, motion: SvgMotion): VectorTimeline {\n const hold = effect.hold ?? 600;\n const d = svgDuration(motion);\n if (effect.trigger === 'hover' || effect.trigger === 'press' || effect.trigger === 'scroll') {\n const length = REST + d + hold + d;\n return {\n length,\n steps: [],\n at(ms) {\n const p = ms % length;\n const time = p < REST ? 0 : p < REST + d ? p - REST : p < REST + d + hold ? d : Math.max(0, d - (p - REST - d - hold));\n return { time, steps: [] };\n },\n };\n }\n if (effect.trigger === 'click') {\n const anims = motion.animate ?? [];\n const last = anims.reduce((n, a) => Math.max(n, a.step ?? 0), 0);\n if (last === 0) {\n const length = REST + d + hold;\n return { length, steps: [], at: (ms) => ({ time: Math.max(0, (ms % length) - REST), steps: [] }) };\n }\n // One click per step, each when the step before has played and rested.\n const clicks: number[] = [];\n let at = REST;\n for (let step = 1; step <= last; step++) {\n clicks.push(at);\n const ends = anims.filter((a) => (a.step ?? 0) === step).map((a) => (a.delay ?? 0) + (a.ms ?? 800));\n at += Math.max(0, ...ends) + hold;\n }\n const length = at;\n return {\n length,\n steps: clicks,\n at(ms) {\n const p = ms % length;\n return { time: p, steps: clicks.filter((c) => c <= p) };\n },\n };\n }\n const length = d + hold;\n return { length, steps: [], at: (ms) => ({ time: ms % length, steps: [] }) };\n}\n\nconst even = (n: number) => Math.max(2, Math.round(n / 2) * 2);\n\n/** Default pixel size for an effect (see {@link EffectExportOptions.width}). */\nexport function defaultSize(effect: EffectDefinition, motion?: SvgMotion): { width: number; height: number } {\n if (effect.kind === 'vector') {\n const box = svgViewBox((motion ?? effect.motion).svg);\n const aspect = box && box[2] > 0 && box[3] > 0 ? box[2] / box[3] : 1;\n return aspect >= 1 ? { width: 720, height: even(720 / aspect) } : { width: even(720 * aspect), height: 720 };\n }\n return effectInputs(effect).images.length ? { width: 1280, height: 720 } : { width: 720, height: 720 };\n}\n\nfunction run(bin: string, args: string[]): Promise<{ code: number; stderr: string }> {\n return new Promise((resolve, reject) => {\n const proc = spawn(bin, args, { stdio: ['ignore', 'ignore', 'pipe'] });\n let stderr = '';\n proc.stderr!.on('data', (d) => (stderr += d.toString()));\n proc.on('error', (err: NodeJS.ErrnoException) =>\n reject(err.code === 'ENOENT' ? new Error('A video subject needs ffmpeg to decode it, and it is not installed (or not on the PATH); install it, or set FFMPEG_PATH.') : err),\n );\n proc.on('close', (code) => resolve({ code: code ?? 1, stderr }));\n });\n}\n\n/** A video's length in seconds, from ffmpeg's report (undefined when it does not say). */\nexport async function videoSeconds(file: string): Promise<number | undefined> {\n const { stderr } = await run(ffmpegPath(), ['-hide_banner', '-i', file]);\n const m = /Duration:\\s*(\\d+):(\\d+):(\\d+(?:\\.\\d+)?)/.exec(stderr);\n return m ? Number(m[1]) * 3600 + Number(m[2]) * 60 + Number(m[3]) : undefined;\n}\n\n/**\n * Decodes `frames` frames of a video at `fps` into PNGs in `dir` (looping a\n * short video), at most 2048 px on the long edge. Returns their paths.\n */\nexport async function extractVideoFrames(file: string, fps: number, frames: number, dir: string): Promise<string[]> {\n fs.mkdirSync(dir, { recursive: true });\n const { code, stderr } = await run(ffmpegPath(), [\n '-hide_banner', '-loglevel', 'error', '-y',\n '-stream_loop', '-1', '-i', file,\n '-vf', `fps=${fps},scale='if(gte(iw,ih),min(2048,iw),-2)':'if(gte(iw,ih),-2,min(2048,ih))'`,\n '-frames:v', String(frames), '-start_number', '0',\n path.join(dir, '%06d.png'),\n ]);\n const files = fs.readdirSync(dir).filter((f) => f.endsWith('.png')).sort().map((f) => path.join(dir, f));\n if (code !== 0 || !files.length) throw new Error(`ffmpeg could not decode the video at ${file}: ${stderr.trim() || `exit ${code}`}`);\n return files;\n}\n\n/**\n * Renders a catalog effect (by id or definition), applied to `subject`, to\n * a file: a shader through WebGL2 in headless Chrome, a vector effect by\n * drawing each frame's SVG there, or (to `.svg`) a vector effect as one\n * animated SVG with no browser at all. MP4, WebM, MOV and video subjects\n * need ffmpeg. Throws a sentence when the effect is unknown, takes no such\n * subject, or cannot be written in that format.\n *\n * ```ts\n * await exportEffect(\"image-duotone\", { subject: { image: \"team.jpg\" }, preset: \"Spotify\", outputPath: \"team.mp4\" });\n * await exportEffect(\"click-ripple\", { alpha: true, outputPath: \"ripple.webm\" });\n * await exportEffect(\"typewriter\", { subject: { text: \"Hello\" }, outputPath: \"hello.gif\" });\n * await exportEffect(\"toggle-switch\", { outputPath: \"toggle.svg\" });\n * ```\n */\nexport async function exportEffect(effect: string | EffectDefinition, options: EffectExportOptions): Promise<string> {\n const def = resolveEffect(effect);\n if (options.preset && !def.presets?.some((p) => p.name === options.preset)) {\n const names = def.presets?.map((p) => `\"${p.name}\"`).join(', ');\n throw new Error(`\"${def.id}\" has no preset \"${options.preset}\"; ${names ? `its presets are ${names}` : 'it has no presets'}.`);\n }\n const fromSubject = options.subject ? await nodeSubjectValues(def, options.subject) : { values: {}, video: {} };\n const explicit = await checkEffectValues(def, options.values ?? {});\n const values = { ...effectDefaults(def, options.preset ? { preset: options.preset } : {}), ...fromSubject.values, ...explicit };\n const fps = options.fps ?? 30;\n const background = options.background ?? (def.kind === 'vector' ? '#ffffff' : '#000000');\n\n if (def.kind === 'vector') {\n const motion = renderVectorEffect(def, values);\n const timeline = vectorTimeline(def, motion);\n const duration = options.duration ?? timeline.length / 1000;\n const frames = Math.max(1, Math.round(duration * fps));\n const plan = planOutput(options.outputPath, { alpha: options.alpha, frames });\n if (plan.format === 'svg') {\n const markup = svgAnimatedMarkup(motion, {\n ...(def.hold !== undefined ? { hold: def.hold } : {}),\n ...(timeline.steps.length ? { steps: timeline.steps, duration: timeline.length } : {}),\n ...(options.duration !== undefined ? { duration: options.duration * 1000 } : {}),\n fps,\n });\n if (!markup) throw new Error(`\"${def.id}\" has no <svg> to write.`);\n // A file gets a size of its own (it fills its container otherwise); a background only when asked for.\n const size = defaultSize(def, motion);\n const w = Math.round(options.width ?? size.width);\n const h = Math.round(options.height ?? (options.width ? (options.width * size.height) / size.width : size.height));\n const style = !plan.alpha && options.background ? ` style=\"background:${options.background.replace(/[\"<>&]/g, '')}\"` : '';\n const out = markup.replace(/^<svg\\b[^>]*>/, (open) =>\n open.replace(/\\swidth=\"100%\"/, ` width=\"${w}\"`).replace(/\\sheight=\"100%\"/, ` height=\"${h}\"`).replace(/>$/, `${style}>`),\n );\n fs.mkdirSync(path.dirname(plan.path), { recursive: true });\n fs.writeFileSync(plan.path, out, 'utf8');\n options.onProgress?.(1, 1);\n return plan.path;\n }\n const size = defaultSize(def, motion);\n const width = Math.max(1, Math.round(options.width ?? size.width));\n const height = Math.max(1, Math.round(options.height ?? (options.width ? (options.width * size.height) / size.width : size.height)));\n const base = frameStates(frames, fps, width, height, 'none');\n const pointer = options.pointer ?? 'auto';\n const state = (i: number): FrameState => {\n const ms = (i / fps) * 1000;\n const { time, steps } = pointer === 'none' && def.trigger ? { time: 0, steps: [] } : timeline.at(ms);\n return { ...base[i]!, svg: svgFrameMarkup(motion, { at: time, steps })! };\n };\n return runRender({\n page: { width, height, frames, alpha: plan.alpha, background, send: plan.format === 'gif' ? 'rgba' : 'png' },\n state,\n plan,\n fps,\n ...(options.onProgress ? { onProgress: options.onProgress } : {}),\n });\n }\n\n // A shader.\n const videoEntries = Object.entries(fromSubject.video);\n let duration = options.duration;\n if (duration === undefined && videoEntries.length) {\n const seconds = await videoSeconds(videoEntries[0]![1]);\n duration = seconds ? Math.min(10, seconds) : undefined;\n }\n duration ??= def.loop && def.loop <= 12 ? def.loop : 3;\n const frames = Math.max(1, Math.round(duration * fps));\n const plan = planOutput(options.outputPath, { alpha: options.alpha, frames });\n if (plan.format === 'svg') {\n throw new Error(`\"${def.id}\" is a shader effect, which draws pixels; write .mp4, .webm, .mov, .gif or .png frames (only vector effects become SVG).`);\n }\n const size = defaultSize(def);\n const width = Math.max(1, Math.round(options.width ?? size.width));\n const height = Math.max(1, Math.round(options.height ?? (options.width ? (options.width * size.height) / size.width : size.height)));\n const interactive = effectInputs(def).interactions.length > 0;\n const states = frameStates(frames, fps, width, height, options.pointer ?? (interactive ? 'auto' : 'none'));\n\n const tmp = videoEntries.length ? fs.mkdtempSync(path.join(os.tmpdir(), 'flair-video-')) : undefined;\n try {\n const videoFrames: Record<string, string[]> = {};\n for (const [name, file] of videoEntries) videoFrames[name] = await extractVideoFrames(file, fps, frames, path.join(tmp!, name));\n const state = (i: number): FrameState => {\n if (!videoEntries.length) return states[i]!;\n const video = Object.fromEntries(Object.entries(videoFrames).map(([name, files]) => [name, files[Math.min(i, files.length - 1)]!]));\n return { ...states[i]!, video };\n };\n return await runRender({\n page: {\n width,\n height,\n frames,\n alpha: plan.alpha,\n background,\n send: plan.format === 'gif' ? 'rgba' : 'png',\n shader: {\n fragment: wrapSource(def.source),\n controls: await pageControls(def.source, values),\n opaque: !plan.alpha && !def.transparent,\n },\n },\n state,\n plan,\n fps,\n ...(options.onProgress ? { onProgress: options.onProgress } : {}),\n });\n } finally {\n if (tmp) fs.rmSync(tmp, { recursive: true, force: true });\n }\n}\n\n// ==========================================\n// Command-line helpers\n// ==========================================\n\n/** `\"1280x720\"` → `{ width: 1280, height: 720 }`; a sentence for anything else. */\nexport function parseSize(size: string): { width: number; height: number } {\n const m = /^\\s*(\\d+)\\s*[x×X]\\s*(\\d+)\\s*$/.exec(size);\n if (!m || Number(m[1]) < 1 || Number(m[2]) < 1) throw new Error(`--size takes width x height in pixels, like 1280x720, not \"${size}\".`);\n return { width: Number(m[1]), height: Number(m[2]) };\n}\n\n/**\n * A `--set` value read for its control: numbers for `float` and `int`,\n * `true`/`false` (or 1/0) for `bool`, a colour (`#77C16A`, `rgb(…)`) or\n * numbers separated by commas or spaces for vectors, and the text itself\n * for images (a path or URL) and text.\n */\nexport function parseSetValue(control: ControlDef, raw: string): ControlValue {\n const text = raw.trim();\n switch (control.type) {\n case 'float':\n case 'int': {\n const n = Number(text);\n if (text === '' || !Number.isFinite(n)) throw new Error(`${control.name} takes a number, not \"${raw}\".`);\n return n;\n }\n case 'bool': {\n if (/^(true|1|yes|on)$/i.test(text)) return true;\n if (/^(false|0|no|off)$/i.test(text)) return false;\n throw new Error(`${control.name} takes true or false, not \"${raw}\".`);\n }\n case 'sampler2D':\n case 'text':\n return raw;\n default: {\n if (control.color && (parseColor(text) || /^currentcolor$/i.test(text)) && !/^[-\\d.]+([\\s,]+[-\\d.]+)*$/.test(text)) return text;\n const parts = text.split(/[\\s,]+/).filter(Boolean).map(Number);\n if (!parts.length || parts.some((n) => !Number.isFinite(n))) {\n throw new Error(`${control.name} takes ${control.type === 'vec2' ? 2 : control.type === 'vec3' ? 3 : 4} numbers separated by commas${control.color ? ', or a colour like \"#77C16A\"' : ''}, not \"${raw}\".`);\n }\n return parts;\n }\n }\n}\n\n/** `--set name=value` flags as control values for an effect; sentences for unknown names and bad values. */\nexport function parseSets(effect: EffectDefinition, sets: readonly string[]): Record<string, ControlValue> {\n const controls = new Map(effectControls(effect).map((c) => [c.name, c]));\n const out: Record<string, ControlValue> = {};\n for (const set of sets) {\n const eq = set.indexOf('=');\n if (eq <= 0) throw new Error(`--set takes name=value, like --set uSpeed=2, not \"${set}\".`);\n const name = set.slice(0, eq).trim();\n const control = controls.get(name);\n if (!control) throw new Error(`\"${effect.id}\" has no control \"${name}\"; it has ${[...controls.keys()].join(', ') || 'none'}.`);\n out[name] = parseSetValue(control, set.slice(eq + 1));\n }\n return out;\n}\n\n/** The render command's subject flags. */\nexport interface SubjectFlags {\n image?: readonly string[];\n svg?: readonly string[];\n text?: readonly string[];\n path?: readonly string[];\n video?: readonly string[];\n font?: string;\n weight?: string;\n}\n\n/** Subjects from the render command's flags, in the order images, SVGs, videos, texts, paths. */\nexport function subjectsFromFlags(flags: SubjectFlags): NodeSubject[] {\n const weight = flags.weight === undefined ? undefined : /^\\d+$/.test(flags.weight) ? Number(flags.weight) : flags.weight;\n return [\n ...(flags.image ?? []).map((image) => ({ image })),\n ...(flags.svg ?? []).map((svg) => ({ svg })),\n ...(flags.video ?? []).map((video) => ({ video })),\n ...(flags.text ?? []).map((text) => ({ text, ...(flags.font ? { font: flags.font } : {}), ...(weight !== undefined ? { weight } : {}) })),\n ...(flags.path ?? []).map((p) => ({ path: p })),\n ];\n}\n\n/** Comma-separated (or repeated) flag values checked against a list; a sentence for the rest. */\nexport function parseChoices<T extends string>(flag: string, values: readonly string[] | undefined, allowed: readonly T[]): T[] | undefined {\n if (!values?.length) return undefined;\n const list = values.flatMap((v) => v.split(',')).map((v) => v.trim()).filter(Boolean);\n const bad = list.filter((v) => !(allowed as readonly string[]).includes(v));\n if (bad.length) throw new Error(`${flag} takes ${allowed.join(', ')}; not ${bad.map((b) => `\"${b}\"`).join(', ')}.`);\n return list as T[];\n}\n\n/** The effects command's filters, checked. */\nexport function effectQueryFromFlags(flags: { accepts?: readonly string[]; interaction?: readonly string[]; category?: string; kind?: string; search?: string; transparent?: boolean }) {\n const accepts = parseChoices<EffectInput>('--accepts', flags.accepts, EFFECT_INPUTS);\n const interaction = parseChoices<EffectInteraction>('--interaction', flags.interaction, EFFECT_INTERACTIONS);\n if (flags.category && !(EFFECT_CATEGORIES as readonly string[]).includes(flags.category)) {\n throw new Error(`--category takes one of ${EFFECT_CATEGORIES.join(', ')}; not \"${flags.category}\".`);\n }\n if (flags.kind && flags.kind !== 'shader' && flags.kind !== 'vector') throw new Error(`--kind takes shader or vector; not \"${flags.kind}\".`);\n return {\n ...(accepts ? { accepts } : {}),\n ...(interaction ? { interaction } : {}),\n ...(flags.category ? { category: flags.category as EffectCategory } : {}),\n ...(flags.kind ? { kind: flags.kind as 'shader' | 'vector' } : {}),\n ...(flags.search ? { text: flags.search } : {}),\n ...(flags.transparent !== undefined ? { transparent: flags.transparent } : {}),\n };\n}\n\n/** One line about an effect for the effects command: id, kind, category, and what it takes. */\nexport function describeEffect(effect: EffectDefinition): string {\n const inputs = effectInputs(effect);\n const parts = [\n `${effect.kind}/${effect.category}`,\n `takes ${inputs.accepts.join(', ') || 'nothing'}`,\n ...(inputs.video ? [`video: ${inputs.video}`] : []),\n ...(inputs.interactions.length ? [`answers ${inputs.interactions.join(', ')}`] : []),\n ...(inputs.transparent ? ['overlay'] : []),\n ...(effect.presets?.length ? [`presets: ${effect.presets.map((p) => p.name).join(', ')}`] : []),\n ];\n return `${effect.id.padEnd(24)} ${parts.join(' · ')}`;\n}\n"],"mappings":"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","names":["length","duration","frames","plan","size","width","height"]}
|