@video-editor/renderer 0.0.1-beta.33 → 0.0.1-beta.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +168 -0
- package/dist/index.js +1626 -948
- package/dist/index.js.map +1 -1
- package/package.json +3 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/2d/index.ts","../src/layout.ts","../src/helpers.ts","../src/audio-manager.ts","../src/text.ts","../src/renderer-core.ts","../src/concat.ts","../src/protocol-clip.ts","../src/compose.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport type { ApplicationOptions } from 'pixi.js'\nimport { Application } from 'pixi.js'\n\ndeclare global {\n\n // eslint-disable-next-line vars-on-top\n var __PIXI_APP__: Application\n}\n\nexport async function createApp(opts?: Partial<ApplicationOptions>) {\n const app = new Application()\n\n await app.init({ resizeTo: window, backgroundAlpha: 0, ...opts })\n\n if (import.meta.env.DEV) {\n globalThis.__PIXI_APP__ = app\n }\n\n return app\n}\n","import type { IFillMode, SegmentUnion } from '@video-editor/shared'\n\nexport interface SegmentLayout {\n width: number\n height: number\n centerX: number\n centerY: number\n rotationRad: number\n}\n\nexport function resolveFillSize(\n mode: IFillMode | undefined,\n sourceWidth: number,\n sourceHeight: number,\n stageWidth: number,\n stageHeight: number,\n) {\n const safeSourceWidth = sourceWidth || stageWidth\n const safeSourceHeight = sourceHeight || stageHeight\n if (!safeSourceWidth || !safeSourceHeight)\n return { width: stageWidth, height: stageHeight }\n\n const sourceRatio = safeSourceWidth / safeSourceHeight\n const stageRatio = stageWidth / stageHeight\n\n switch (mode) {\n case 'none':\n return { width: safeSourceWidth, height: safeSourceHeight }\n case 'cover':\n if (sourceRatio > stageRatio)\n return { width: stageHeight * sourceRatio, height: stageHeight }\n return { width: stageWidth, height: stageWidth / sourceRatio }\n case 'stretch':\n return { width: stageWidth, height: stageHeight }\n case 'contain':\n default:\n if (sourceRatio > stageRatio)\n return { width: stageWidth, height: stageWidth / sourceRatio }\n return { width: stageHeight * sourceRatio, height: stageHeight }\n }\n}\n\nexport function computeSegmentLayout(\n segment: SegmentUnion,\n stageWidth: number,\n stageHeight: number,\n sourceWidth: number,\n sourceHeight: number,\n): SegmentLayout {\n const fillMode = 'fillMode' in segment ? segment.fillMode : undefined\n const { width, height } = resolveFillSize(\n fillMode,\n sourceWidth,\n sourceHeight,\n stageWidth,\n stageHeight,\n )\n\n const transform = 'transform' in segment ? segment.transform : undefined\n const [px, py] = transform?.position ?? [0, 0]\n const [sx, sy] = transform?.scale ?? [1, 1]\n const rotation = transform?.rotation?.[2] ?? 0\n\n const finalWidth = width * sx\n const finalHeight = height * sy\n const centerX = stageWidth / 2 + (px * stageWidth) / 2\n const centerY = stageHeight / 2 - (py * stageHeight) / 2\n\n return {\n width: finalWidth,\n height: finalHeight,\n centerX,\n centerY,\n rotationRad: (rotation / 180) * Math.PI,\n }\n}\n","import type { IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { TrackTypeMapTrack } from '@video-editor/shared'\nimport type { PixiDisplayObject } from './types'\nimport { toRaw } from '@vue/reactivity'\nimport { Graphics, Sprite, Texture } from 'pixi.js'\nimport { computeSegmentLayout } from './layout'\n\nexport function collectResourceUrls(protocol: IVideoProtocol) {\n const urls = new Set<string>()\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (segment.url)\n urls.add(segment.url)\n }\n }\n return urls\n}\n\nexport function collectActiveSegments(protocol: IVideoProtocol, at: number) {\n const active: { segment: SegmentUnion, trackIndex: number, childIndex: number }[] = []\n protocol.tracks.forEach((track, trackIndex) => {\n track.children.forEach((segment, childIndex) => {\n if (segment.startTime <= at && at < segment.endTime)\n active.push({ segment, trackIndex, childIndex })\n })\n })\n\n return active.sort((a, b) => {\n const aTrack = protocol.tracks[a.trackIndex]\n const bTrack = protocol.tracks[b.trackIndex]\n const aIsMain = aTrack?.trackType === 'frames' && (aTrack as TrackTypeMapTrack['frames']).isMain\n const bIsMain = bTrack?.trackType === 'frames' && (bTrack as TrackTypeMapTrack['frames']).isMain\n const total = protocol.tracks.length\n const aOrder = aIsMain ? 0 : total - a.trackIndex\n const bOrder = bIsMain ? 0 : total - b.trackIndex\n if (aOrder !== bOrder)\n return aOrder - bOrder\n if (a.trackIndex === b.trackIndex)\n return a.childIndex - b.childIndex\n return a.trackIndex - b.trackIndex\n })\n}\n\nexport function applyDisplayProps(display: PixiDisplayObject, segment: SegmentUnion, width: number, height: number) {\n const opacity = readOpacity(segment)\n const sourceWidth = display instanceof Sprite ? display.texture.width || width : width\n const sourceHeight = display instanceof Sprite ? display.texture.height || height : height\n const layout = computeSegmentLayout(segment, width, height, sourceWidth, sourceHeight)\n\n if (display instanceof Sprite) {\n display.anchor.set(0.5)\n display.width = layout.width\n display.height = layout.height\n display.position.set(layout.centerX, layout.centerY)\n display.rotation = layout.rotationRad\n const src = display.texture.source as { addEventListener?: (type: string, cb: () => void, opts?: AddEventListenerOptions) => void } | undefined\n src?.addEventListener?.('error', () => {\n // fallback to a colored rect if texture failed\n display.texture = Texture.from(placeholderTexture(width, height))\n }, { once: true })\n }\n else if (display instanceof Graphics) {\n display.clear()\n display\n .rect(0, 0, layout.width, layout.height)\n .fill({ color: stringToColor('url' in segment && typeof segment.url === 'string' ? segment.url : segment.segmentType), alpha: hasOpacity(segment) ? opacity : 0.35 })\n display.pivot.set(layout.width / 2, layout.height / 2)\n display.position.set(layout.centerX, layout.centerY)\n display.rotation = layout.rotationRad\n }\n\n display.alpha = opacity\n}\n\nexport function placeholder(key: string, url?: string) {\n const g = new Graphics()\n g.rect(0, 0, 10, 10).fill({ color: stringToColor(url ?? key), alpha: 1 })\n return g\n}\n\nexport function placeholderTexture(width: number, height: number, color?: string) {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"><rect width=\"100%\" height=\"100%\" fill=\"${color ?? '#0f172a'}\" fill-opacity=\"0.8\"/></svg>`\n return `data:image/svg+xml;base64,${btoa(svg)}`\n}\n\nexport function stringToColor(key: string) {\n let hash = 0\n for (let i = 0; i < key.length; i++)\n hash = key.charCodeAt(i) + ((hash << 5) - hash)\n return hash & 0x00FFFFFF\n}\n\nexport function computeDuration(protocol: IVideoProtocol) {\n const endTimes = protocol.tracks.flatMap(track => track.children.map(seg => seg.endTime))\n return endTimes.length ? Math.max(...endTimes) : 0\n}\n\nexport function clamp(num: number, min: number, max: number) {\n return Math.min(Math.max(num, min), max)\n}\n\nexport function cloneProtocol(protocol: IVideoProtocol) {\n const raw = toRaw(protocol) as IVideoProtocol\n // use JSON clone to avoid structuredClone errors on proxies (e.g., Vue reactive)\n return JSON.parse(JSON.stringify(raw)) as IVideoProtocol\n}\n\nfunction hasOpacity(segment: SegmentUnion): segment is SegmentUnion & { opacity?: number } {\n return 'opacity' in segment\n}\n\nfunction readOpacity(segment: SegmentUnion) {\n if (hasOpacity(segment) && typeof segment.opacity === 'number')\n return segment.opacity\n return 1\n}\n","import type { IAudioSegment, IVideoProtocol } from '@video-editor/shared'\nimport type { MP4Clip, AudioClip } from '@webav/av-cliper'\nimport { collectActiveSegments } from './helpers'\nimport { AudioClip as WebAVAudioClip } from '@webav/av-cliper'\n\ninterface ClipEntry {\n clip: AudioClip\n ready: Promise<unknown>\n}\n\ninterface LoopState {\n stop: () => void\n sources: AudioBufferSourceNode[]\n isStopped: () => boolean\n}\n\ninterface AudioLoopContext {\n segment: IAudioSegment\n startedAt: number // ctx.currentTime when loop started\n segmentRelativeMs: number // position in segment when loop started\n}\n\ninterface Mp4State {\n loop: LoopState\n startUs: number\n startCtxTime: number\n fps: number\n nextStartAt?: number\n}\n\ninterface AudioElementState {\n segmentId: string\n url: string\n el: HTMLAudioElement\n pendingPlay?: Promise<void>\n lastTimelineMs?: number\n lastSourceSec?: number\n lastSeekTimelineMs?: number\n}\n\nexport class AudioManager {\n private protocol: IVideoProtocol\n private clips = new Map<string, ClipEntry>()\n private loadingClips = new Map<string, Promise<ClipEntry | undefined>>()\n private audioLoops = new Map<string, LoopState>()\n private audioLoopContexts = new Map<string, AudioLoopContext>()\n private mp4Loops = new Map<string, LoopState>()\n private mp4States = new Map<string, Mp4State>()\n private audioGains = new Map<string, GainNode>()\n private mp4Gains = new Map<string, GainNode>()\n private audioElements = new Map<string, AudioElementState>()\n private readonly useMediaElementForAudio = true\n private ctx: AudioContext\n private lastTime = 0\n\n constructor(protocol: IVideoProtocol) {\n this.protocol = protocol\n this.ctx = new (window.AudioContext || (window as any).webkitAudioContext)()\n }\n\n public setProtocol(protocol: IVideoProtocol) {\n this.protocol = protocol\n }\n\n public async sync(currentTime: number, isPlaying: boolean) {\n if (!isPlaying) {\n // Always stop all audio when paused\n this.stopAll()\n this.lastTime = currentTime\n return\n }\n\n if (this.ctx.state === 'suspended')\n await this.ctx.resume().catch(() => {})\n\n if (Math.abs(currentTime - this.lastTime) > 1000)\n this.stopAll()\n this.lastTime = currentTime\n\n const activeSegments = collectActiveSegments(this.protocol, currentTime)\n const activeAudioKeys = new Set<string>()\n const activeVideoKeys = new Set<string>()\n\n for (const { segment } of activeSegments) {\n if (segment.segmentType === 'audio') {\n const key = this.audioKey(segment.id)\n activeAudioKeys.add(key)\n if (this.useMediaElementForAudio)\n this.syncAudioElement(segment as IAudioSegment, currentTime)\n else\n this.ensureAudioLoop(segment as IAudioSegment, currentTime)\n }\n else if (segment.segmentType === 'frames' && 'type' in segment && segment.type === 'video') {\n const key = this.videoKey(segment.id)\n activeVideoKeys.add(key)\n }\n }\n\n for (const [key, loop] of this.audioLoops) {\n if (!activeAudioKeys.has(key)) {\n loop.stop()\n // Stop all audio buffer sources\n for (const source of loop.sources) {\n try {\n source.stop()\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n this.audioLoops.delete(key)\n this.audioLoopContexts.delete(key)\n this.audioGains.delete(key)\n }\n }\n\n for (const [key, state] of this.audioElements) {\n if (activeAudioKeys.has(key))\n continue\n try {\n state.el.pause()\n state.pendingPlay = undefined\n state.lastTimelineMs = undefined\n state.lastSourceSec = undefined\n state.lastSeekTimelineMs = undefined\n }\n catch (e) {\n // Ignore media element pause failures.\n }\n if (!this.findSegmentInProtocol(state.segmentId)) {\n this.destroyAudioElement(state.el)\n this.audioElements.delete(key)\n }\n }\n\n for (const [key, loop] of this.mp4Loops) {\n if (!activeVideoKeys.has(key)) {\n loop.stop()\n // Stop all audio buffer sources\n for (const source of loop.sources) {\n try {\n source.stop()\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n this.mp4Loops.delete(key)\n this.mp4States.delete(key)\n this.mp4Gains.delete(key)\n }\n }\n\n // Also clean up mp4States that don't have active loops (direct playback mode)\n for (const key of this.mp4States.keys()) {\n if (!activeVideoKeys.has(key) && !this.mp4Loops.has(key)) {\n this.mp4States.delete(key)\n this.mp4Gains.delete(key)\n }\n }\n }\n\n /**\n * Play audio frames from MP4 video directly.\n * Called by renderer after it gets audio data from clip.tick()\n */\n public playMp4AudioFrames(id: string, audio: Float32Array[] | undefined, sampleRate: number) {\n if (!audio || audio.length === 0 || !audio[0]?.length)\n return\n\n const key = this.videoKey(id)\n const volume = this.getSegmentVolume(id)\n const gainNode = this.getOrCreateGain(this.mp4Gains, key, volume)\n\n if (this.ctx.state === 'suspended')\n this.ctx.resume().catch(() => {})\n\n // Get or initialize the playback state for this video\n let state = this.mp4States.get(key)\n if (!state) {\n state = {\n loop: { stop: () => {}, sources: [], isStopped: () => false },\n startUs: 0,\n startCtxTime: this.ctx.currentTime,\n fps: 30,\n nextStartAt: 0,\n }\n this.mp4States.set(key, state)\n }\n\n // Play the audio frames\n state.nextStartAt = this.playFrames(audio, sampleRate, state.nextStartAt ?? 0, gainNode, state.loop.sources)\n }\n\n /**\n * Reset MP4 audio playback state (call when seeking or pausing)\n */\n public resetMp4Audio(id: string) {\n const key = this.videoKey(id)\n const state = this.mp4States.get(key)\n if (state) {\n state.nextStartAt = 0\n }\n }\n\n /**\n * Stop and clean up MP4 audio for a video segment\n */\n public stopMp4Audio(id: string) {\n const key = this.videoKey(id)\n const state = this.mp4States.get(key)\n if (state) {\n state.loop.stop()\n // Stop all audio buffer sources\n for (const source of state.loop.sources) {\n try {\n source.stop()\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n this.mp4Loops.delete(key)\n this.mp4States.delete(key)\n this.mp4Gains.delete(key)\n }\n }\n\n /**\n * @deprecated Use playMp4AudioFrames instead\n */\n public ensureMp4Audio(id: string, clip: MP4Clip, startUs: number, fps: number) {\n // Legacy method - kept for compatibility but should not be used\n // The new approach is to pass audio data directly via playMp4AudioFrames\n const key = this.videoKey(id)\n const volume = this.getSegmentVolume(id)\n const gainNode = this.getOrCreateGain(this.mp4Gains, key, volume)\n const existing = this.mp4States.get(key)\n if (existing) {\n gainNode.gain.value = Math.max(0, volume)\n const elapsedUs = (this.ctx.currentTime - existing.startCtxTime) * 1e6\n const expectedUs = existing.startUs + elapsedUs\n if (Math.abs(expectedUs - startUs) < 150000 && existing.fps === fps)\n return\n existing.loop.stop()\n // Stop all audio buffer sources\n for (const source of existing.loop.sources) {\n try {\n source.stop()\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n this.mp4Loops.delete(key)\n this.mp4States.delete(key)\n }\n if (this.ctx.state === 'suspended')\n this.ctx.resume().catch(() => {})\n const loop = this.startMp4Loop(clip, startUs, fps, gainNode)\n this.mp4Loops.set(key, loop)\n this.mp4States.set(key, {\n loop,\n startUs,\n startCtxTime: this.ctx.currentTime,\n fps,\n })\n }\n\n public destroy() {\n this.stopAll()\n for (const entry of this.clips.values())\n entry.clip.destroy()\n this.clips.clear()\n for (const state of this.audioElements.values())\n this.destroyAudioElement(state.el)\n this.audioElements.clear()\n }\n\n private stopAll() {\n for (const state of this.audioElements.values()) {\n try {\n state.el.pause()\n state.pendingPlay = undefined\n state.lastTimelineMs = undefined\n state.lastSourceSec = undefined\n state.lastSeekTimelineMs = undefined\n }\n catch (e) {\n // Ignore media element pause failures.\n }\n }\n\n for (const loop of this.audioLoops.values()) {\n loop.stop()\n // Stop all audio buffer sources immediately\n for (const source of loop.sources) {\n try {\n source.stop(0)\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n loop.sources.length = 0\n }\n for (const loop of this.mp4Loops.values()) {\n loop.stop()\n // Stop all audio buffer sources immediately\n for (const source of loop.sources) {\n try {\n source.stop(0)\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n loop.sources.length = 0\n }\n // Disconnect all gain nodes to completely silence audio\n for (const gain of this.audioGains.values()) {\n try {\n gain.disconnect()\n }\n catch (e) {\n // Gain may already be disconnected\n }\n }\n for (const gain of this.mp4Gains.values()) {\n try {\n gain.disconnect()\n }\n catch (e) {\n // Gain may already be disconnected\n }\n }\n this.audioLoops.clear()\n this.audioLoopContexts.clear()\n this.audioGains.clear()\n this.mp4Loops.clear()\n this.mp4States.clear()\n this.mp4Gains.clear()\n }\n\n private async ensureAudioLoop(segment: IAudioSegment, currentTime: number) {\n const key = this.audioKey(segment.id)\n const entry = await this.loadClip(segment)\n if (!entry)\n return\n const offset = segment.fromTime ?? 0\n const playRate = this.normalizePlayRate(segment.playRate)\n // relativeMs is position within segment timeline (not source audio)\n const relativeMs = currentTime - segment.startTime\n // sourceOffsetMs is where we are in the source audio (accounting for fromTime and playRate)\n const sourceOffsetMs = offset + relativeMs * playRate\n const gainNode = this.getOrCreateGain(this.audioGains, key, segment.volume)\n\n // Apply fade in/out to gain\n this.applyFadeToGain(segment, relativeMs, gainNode)\n\n const existingLoop = this.audioLoops.get(key)\n if (existingLoop && !existingLoop.isStopped()) {\n // Loop is still running, just update volume with fade\n return\n }\n // Clean up stopped loop if exists\n if (existingLoop) {\n this.audioLoops.delete(key)\n this.audioLoopContexts.delete(key)\n }\n // Calculate segment duration in microseconds\n const segmentDurationMs = segment.endTime - segment.startTime\n const sourceDurationMs = segmentDurationMs * playRate\n const maxSourceOffsetMs = offset + sourceDurationMs\n\n const loop = this.startAudioLoop(entry.clip, Math.max(0, sourceOffsetMs) * 1000, gainNode, playRate, maxSourceOffsetMs * 1000)\n this.audioLoops.set(key, loop)\n this.audioLoopContexts.set(key, {\n segment,\n startedAt: this.ctx.currentTime,\n segmentRelativeMs: relativeMs,\n })\n }\n\n private syncAudioElement(segment: IAudioSegment, currentTime: number) {\n const key = this.audioKey(segment.id)\n const state = this.getOrCreateAudioElementState(key, segment)\n const relativeMs = currentTime - segment.startTime\n const playRate = this.normalizePlayRate(segment.playRate)\n const offset = segment.fromTime ?? 0\n const sourceOffsetMs = offset + relativeMs * playRate\n const segmentDurationMs = Math.max(0, segment.endTime - segment.startTime)\n const sourceDurationMs = segmentDurationMs * playRate\n const maxSourceOffsetMs = offset + sourceDurationMs\n const segmentMaxSourceSec = Math.max(0, maxSourceOffsetMs) / 1000\n const mediaDurationSec = Number.isFinite(state.el.duration) ? Math.max(0, state.el.duration) : undefined\n const effectiveMaxSourceSec = mediaDurationSec === undefined\n ? segmentMaxSourceSec\n : Math.min(segmentMaxSourceSec, mediaDurationSec)\n const targetSourceSec = Math.max(0, Math.min(sourceOffsetMs / 1000, effectiveMaxSourceSec))\n const isSourceExhausted = sourceOffsetMs / 1000 >= (effectiveMaxSourceSec - 0.01)\n\n if (Math.abs(state.el.playbackRate - playRate) > 0.001)\n state.el.playbackRate = playRate\n\n const targetVolume = this.computeSegmentVolume(segment, relativeMs)\n if (Math.abs(state.el.volume - targetVolume) > 0.001)\n state.el.volume = targetVolume\n\n // Avoid per-frame seeking (causes pops/crackles). Only resync on\n // activation, large timeline jumps, or accumulated drift.\n const seekDriftThresholdSec = 0.24\n const seekCooldownMs = 500\n const largeJumpMs = 300\n const rewindMs = -40\n const lastTimelineMs = state.lastTimelineMs\n const lastSourceSec = state.lastSourceSec\n const deltaTimelineMs = lastTimelineMs === undefined ? 0 : (currentTime - lastTimelineMs)\n\n let shouldSeek = false\n if (lastTimelineMs === undefined) {\n shouldSeek = true\n }\n else if (deltaTimelineMs < rewindMs || deltaTimelineMs > largeJumpMs) {\n shouldSeek = true\n }\n else if (lastSourceSec !== undefined) {\n const predictedSourceSec = lastSourceSec + (deltaTimelineMs * playRate / 1000)\n const driftSec = Math.abs(predictedSourceSec - targetSourceSec)\n const cooldownPassed = state.lastSeekTimelineMs === undefined || (currentTime - state.lastSeekTimelineMs) >= seekCooldownMs\n if (driftSec > seekDriftThresholdSec && cooldownPassed)\n shouldSeek = true\n }\n\n if (shouldSeek && Math.abs(state.el.currentTime - targetSourceSec) > 0.06) {\n try {\n state.el.currentTime = targetSourceSec\n state.lastSeekTimelineMs = currentTime\n }\n catch (e) {\n // Ignore seek failures while metadata is not ready.\n }\n }\n\n state.lastTimelineMs = currentTime\n state.lastSourceSec = targetSourceSec\n\n if (isSourceExhausted) {\n if (!state.el.paused) {\n try {\n state.el.pause()\n }\n catch (e) {\n // Ignore media element pause failures.\n }\n }\n state.pendingPlay = undefined\n return\n }\n\n if (state.el.paused && !state.pendingPlay) {\n const maybePromise = state.el.play()\n if (maybePromise && typeof maybePromise.then === 'function') {\n state.pendingPlay = maybePromise\n .catch(() => {})\n .finally(() => {\n state.pendingPlay = undefined\n })\n }\n }\n }\n\n private applyFadeToGain(segment: IAudioSegment, relativeMs: number, gainNode: GainNode) {\n gainNode.gain.value = this.computeSegmentVolume(segment, relativeMs)\n }\n\n private startMp4Loop(clip: MP4Clip, startUs: number, fps: number, gainNode: GainNode): LoopState {\n let stopped = false\n let timeUs = startUs\n let startAt = 0\n let first = true\n const stepUs = Math.round((1000 / Math.max(fps || 30, 1)) * 1000)\n const sampleRate = this.getClipSampleRate(clip)\n const sources: AudioBufferSourceNode[] = []\n\n const timer = window.setInterval(async () => {\n if (stopped)\n return\n const { audio, state } = await clip.tick(Math.round(timeUs))\n timeUs += stepUs\n if (state === 'done')\n return\n if (first) {\n first = false\n return\n }\n const len = audio?.[0]?.length ?? 0\n if (len === 0)\n return\n startAt = this.playFrames(audio as Float32Array[], sampleRate, startAt, gainNode, sources)\n }, Math.round(1000 / Math.max(fps || 30, 1)))\n\n return {\n sources,\n stop: () => {\n stopped = true\n window.clearInterval(timer)\n },\n isStopped: () => stopped,\n }\n }\n\n private startAudioLoop(clip: AudioClip, startUs: number, gainNode: GainNode, playRate: number = 1, maxSourceOffsetUs?: number): LoopState {\n let stopped = false\n let timeUs = startUs\n let startAt = 0\n let initialized = false\n const sampleRate = this.getClipSampleRate(clip)\n const sources: AudioBufferSourceNode[] = []\n // Each iteration fetches 100ms of real-time audio\n // For playRate != 1, we need to fetch more/less source audio\n const realTimeStepUs = 100000\n const sourceStepUs = Math.round(realTimeStepUs * playRate)\n\n const play = async () => {\n if (stopped)\n return\n\n if (!initialized) {\n // First tick: seek to startUs position (discard audio before startUs)\n if (startUs > 0) {\n await clip.tick(startUs)\n }\n initialized = true\n }\n\n timeUs += sourceStepUs\n\n // Check if we've reached the maximum duration for this segment\n if (maxSourceOffsetUs !== undefined && timeUs > maxSourceOffsetUs) {\n stopped = true\n return\n }\n\n const { audio, state } = await clip.tick(timeUs)\n\n // Check stopped flag immediately after async operation\n if (stopped)\n return\n\n // Stop when audio file ends (don't loop)\n if (state === 'done') {\n stopped = true\n return\n }\n const len = audio?.[0]?.length ?? 0\n if (len === 0) {\n // No audio data - either at silence or past end of file\n // Stop playing to avoid infinite loop\n stopped = true\n return\n }\n // Let the browser handle playback-rate resampling for better audio quality.\n startAt = this.playFrames(audio as Float32Array[], sampleRate, startAt, gainNode, sources, playRate)\n\n // Check stopped before recursing\n if (!stopped) {\n // Use setTimeout to avoid deep call stack and allow stop to interrupt\n setTimeout(() => play(), 0)\n }\n }\n\n play()\n return {\n sources,\n stop: () => {\n stopped = true\n },\n // Treat loop as active while there are still scheduled sources playing.\n isStopped: () => stopped && sources.length === 0,\n }\n }\n\n private playFrames(\n audio: Float32Array[],\n sampleRate: number,\n startAt: number,\n gainNode: GainNode,\n sources?: AudioBufferSourceNode[],\n playbackRate: number = 1,\n ) {\n const channels = Math.max(audio.length, 1)\n const len = audio[0]?.length ?? 0\n if (len === 0)\n return startAt\n const buffer = this.ctx.createBuffer(channels, len, sampleRate)\n for (let i = 0; i < channels; i++) {\n const data = audio[i] ?? new Float32Array(len)\n buffer.copyToChannel(new Float32Array(data), i)\n }\n const source = this.ctx.createBufferSource()\n source.buffer = buffer\n const safePlaybackRate = Math.max(0.1, playbackRate)\n source.playbackRate.value = safePlaybackRate\n source.connect(gainNode)\n const nextStart = Math.max(this.ctx.currentTime, startAt)\n source.start(nextStart)\n\n // Track the source so it can be stopped later\n if (sources) {\n sources.push(source)\n // Clean up finished sources after they complete\n const duration = (buffer.duration / safePlaybackRate) * 1000\n setTimeout(() => {\n const index = sources.indexOf(source)\n if (index > -1) {\n sources.splice(index, 1)\n }\n }, duration + 100)\n }\n\n return nextStart + (buffer.duration / safePlaybackRate)\n }\n\n private getOrCreateGain(map: Map<string, GainNode>, id: string, volume?: number) {\n const existing = map.get(id)\n if (existing) {\n if (typeof volume === 'number')\n existing.gain.value = this.normalizeVolume(volume)\n return existing\n }\n const gainNode = this.ctx.createGain()\n gainNode.gain.value = this.normalizeVolume(volume)\n gainNode.connect(this.ctx.destination)\n map.set(id, gainNode)\n return gainNode\n }\n\n private getOrCreateAudioElementState(key: string, segment: IAudioSegment): AudioElementState {\n const existing = this.audioElements.get(key)\n if (existing) {\n if (existing.url !== segment.url) {\n existing.el.pause()\n existing.el.src = segment.url\n existing.el.currentTime = 0\n existing.url = segment.url\n existing.pendingPlay = undefined\n existing.lastTimelineMs = undefined\n existing.lastSourceSec = undefined\n existing.lastSeekTimelineMs = undefined\n }\n return existing\n }\n\n const el = new Audio(segment.url)\n el.preload = 'auto'\n el.loop = false\n el.volume = this.normalizeVolume(segment.volume)\n el.playbackRate = this.normalizePlayRate(segment.playRate)\n const state: AudioElementState = {\n segmentId: segment.id,\n url: segment.url,\n el,\n }\n this.audioElements.set(key, state)\n return state\n }\n\n private destroyAudioElement(el: HTMLAudioElement) {\n try {\n el.pause()\n }\n catch (e) {\n // Ignore media element pause failures.\n }\n el.removeAttribute('src')\n try {\n el.load()\n }\n catch (e) {\n // Ignore load failures during teardown.\n }\n }\n\n private normalizePlayRate(playRate?: number): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return Math.max(0.1, Math.min(100, playRate))\n }\n\n private normalizeVolume(volume?: number): number {\n if (typeof volume !== 'number' || !Number.isFinite(volume))\n return 1\n return Math.max(0, Math.min(1, volume))\n }\n\n private computeSegmentVolume(segment: IAudioSegment, relativeMs: number): number {\n const baseVolume = this.normalizeVolume(segment.volume)\n const segmentDuration = Math.max(0, segment.endTime - segment.startTime)\n const fadeInDuration = Math.max(0, segment.fadeInDuration ?? 0)\n const fadeOutDuration = Math.max(0, segment.fadeOutDuration ?? 0)\n\n let volumeMultiplier = 1\n\n // Apply fade in\n if (fadeInDuration > 0 && relativeMs < fadeInDuration) {\n volumeMultiplier = Math.max(0, relativeMs / fadeInDuration)\n }\n\n // Apply fade out\n const timeUntilEnd = segmentDuration - relativeMs\n if (fadeOutDuration > 0 && timeUntilEnd < fadeOutDuration) {\n volumeMultiplier = Math.min(volumeMultiplier, Math.max(0, timeUntilEnd / fadeOutDuration))\n }\n\n return baseVolume * volumeMultiplier\n }\n\n private audioKey(id: string) {\n return `audio:${id}`\n }\n\n private videoKey(id: string) {\n return `video:${id}`\n }\n\n private async loadClip(segment: IAudioSegment): Promise<ClipEntry | undefined> {\n // Check if already loaded\n const cached = this.clips.get(segment.id)\n if (cached)\n return cached\n\n // Check if currently loading\n const loading = this.loadingClips.get(segment.id)\n if (loading)\n return loading\n\n // Start loading and cache the promise immediately\n const loadingPromise = (async () => {\n try {\n const response = await fetch(segment.url)\n if (!response.body) {\n this.loadingClips.delete(segment.id)\n return undefined\n }\n const clip = new WebAVAudioClip(response.body)\n const entry: ClipEntry = { clip, ready: clip.ready }\n await clip.ready\n if (!this.findSegmentInProtocol(segment.id)) {\n clip.destroy()\n this.loadingClips.delete(segment.id)\n return undefined\n }\n // Move from loading to loaded\n this.clips.set(segment.id, entry)\n this.loadingClips.delete(segment.id)\n return entry\n }\n catch (e) {\n console.error(`[AudioManager] Failed to load audio ${segment.url}`, e)\n this.loadingClips.delete(segment.id)\n return undefined\n }\n })()\n\n this.loadingClips.set(segment.id, loadingPromise)\n return loadingPromise\n }\n\n private findSegmentInProtocol(id: string): boolean {\n for (const track of this.protocol.tracks) {\n for (const segment of track.children) {\n if (segment.id === id) return true\n }\n }\n return false\n }\n\n private getSegmentVolume(id: string): number {\n for (const track of this.protocol.tracks) {\n for (const segment of track.children) {\n if (segment.id !== id)\n continue\n const volume = (segment as { volume?: number }).volume\n return this.normalizeVolume(volume)\n }\n }\n return 1\n }\n\n private getClipSampleRate(clip: AudioClip | MP4Clip): number {\n const meta = (clip as { meta?: Record<string, unknown> }).meta\n if (!meta)\n return 48000\n const audioSampleRate = meta.audioSampleRate\n if (typeof audioSampleRate === 'number' && audioSampleRate > 0)\n return audioSampleRate\n const sampleRate = meta.sampleRate\n if (typeof sampleRate === 'number' && sampleRate > 0)\n return sampleRate\n return 48000\n }\n}\n","import type { ITextBasic } from '@video-editor/shared'\nimport { renderTxt2ImgBitmap } from '@webav/av-cliper'\n\nconst DEFAULT_TEXT_BITMAP_CACHE_LIMIT = 100\nconst textBitmapCache = new Map<string, ImageBitmap>()\nlet textBitmapCacheLimit = DEFAULT_TEXT_BITMAP_CACHE_LIMIT\n\nfunction touchCache(key: string, value: ImageBitmap) {\n textBitmapCache.delete(key)\n textBitmapCache.set(key, value)\n}\n\nfunction trimCache() {\n while (textBitmapCache.size > textBitmapCacheLimit) {\n const [oldestKey, bitmap] = textBitmapCache.entries().next().value as [string, ImageBitmap]\n textBitmapCache.delete(oldestKey)\n bitmap.close?.()\n }\n}\n\nexport function setTextBitmapCacheLimit(limit: number) {\n textBitmapCacheLimit = Math.max(0, Math.floor(limit))\n trimCache()\n}\n\nexport function clearTextBitmapCache() {\n for (const bitmap of textBitmapCache.values())\n bitmap.close?.()\n textBitmapCache.clear()\n}\n\nexport function buildTextContent(texts: ITextBasic[]) {\n return texts.map(item => item.content).filter(Boolean).join('\\n')\n}\n\nexport function buildTextCss(text: ITextBasic) {\n const fontFamily = Array.isArray(text.fontFamily)\n ? text.fontFamily.join(', ')\n : text.fontFamily\n const fontSize = text.fontSize ?? 32\n const fontWeight = text.fontWeight ?? 'normal'\n const fontStyle = text.fontStyle ?? 'normal'\n const fill = text.fill ?? '#ffffff'\n const align = text.align ?? 'left'\n\n const css: string[] = [\n `font-size: ${fontSize}px`,\n `font-weight: ${fontWeight}`,\n `font-style: ${fontStyle}`,\n `color: ${fill}`,\n `text-align: ${align}`,\n 'white-space: pre-wrap',\n ]\n\n if (fontFamily)\n css.push(`font-family: ${fontFamily}`)\n if (typeof text.letterSpacing === 'number')\n css.push(`letter-spacing: ${text.letterSpacing}px`)\n if (typeof text.leading === 'number')\n css.push(`line-height: ${text.leading}px`)\n if (text.background?.color)\n css.push(`background: ${text.background.color}`)\n if (text.stroke?.color && typeof text.stroke.width === 'number')\n css.push(`-webkit-text-stroke: ${text.stroke.width}px ${text.stroke.color}`)\n if (text.underline)\n css.push('text-decoration: underline')\n if (text.dropShadow?.color && typeof text.dropShadow.distance === 'number') {\n const angle = (text.dropShadow.angle ?? 45) * (Math.PI / 180)\n const offsetX = Math.cos(angle) * text.dropShadow.distance\n const offsetY = Math.sin(angle) * text.dropShadow.distance\n const blur = text.dropShadow.blur ?? 0\n css.push(`text-shadow: ${offsetX}px ${offsetY}px ${blur}px ${text.dropShadow.color}`)\n }\n\n return css.join('; ')\n}\n\nexport async function renderTextBitmap(content: string, cssText: string) {\n const key = `${cssText}::${content}`\n const cached = textBitmapCache.get(key)\n if (cached) {\n touchCache(key, cached)\n return cached\n }\n\n const bitmap = await renderTxt2ImgBitmap(content, cssText)\n if (textBitmapCacheLimit > 0) {\n textBitmapCache.set(key, bitmap)\n trimCache()\n }\n return bitmap\n}\n","import type { ITextSegment, IVideoFramesSegment, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { ComputedRef, Ref, ShallowRef } from '@vue/reactivity'\nimport type { Application, ApplicationOptions } from 'pixi.js'\nimport type { MaybeRef, PixiDisplayObject } from './types'\nimport { createResourceManager, createValidator, getResourceKey } from '@video-editor/protocol'\nimport {\n computed,\n effectScope,\n isRef,\n ref,\n shallowRef,\n unref,\n watch,\n} from '@vue/reactivity'\nimport { MP4Clip } from '@webav/av-cliper'\nimport { file as opfsFile } from 'opfs-tools'\nimport { Container, Sprite, Texture } from 'pixi.js'\nimport { createApp as create2dApp } from './2d'\nimport { AudioManager } from './audio-manager'\nimport {\n applyDisplayProps,\n clamp,\n cloneProtocol,\n collectActiveSegments,\n collectResourceUrls,\n computeDuration,\n placeholder,\n} from './helpers'\nimport { buildTextContent, buildTextCss, renderTextBitmap } from './text'\n\nconst DEFAULT_RES_DIR = '/video-editor-res'\n\nexport interface RendererOptions {\n protocol: MaybeRef<IVideoProtocol>\n app?: Application\n appOptions?: Partial<ApplicationOptions>\n resourceDir?: string\n autoPlay?: boolean\n freezeOnPause?: boolean\n manualRender?: boolean\n videoSourceMode?: 'auto' | 'mp4clip' | 'element'\n warmUpResources?: boolean\n}\n\nexport interface Renderer {\n app: Application\n layer: Container\n currentTime: Ref<number>\n duration: ComputedRef<number>\n isPlaying: Ref<boolean>\n play: () => void\n pause: () => void\n tick: (deltaMs?: number) => void\n seek: (time: number) => void\n renderAt: (time: number) => Promise<void>\n destroy: () => void\n}\n\ninterface AudioManagerApi {\n setProtocol: (protocol: IVideoProtocol) => void\n sync: (currentTime: number, isPlaying: boolean) => void | Promise<void>\n ensureMp4Audio: (id: string, clip: MP4Clip, startUs: number, fps: number) => void\n destroy: () => void\n}\n\n/**\n * Create a renderer that reacts to protocol updates and drives playback state.\n * - Pass a reactive `protocol` (Ref/readonly/normal object)\n * - Call `play/pause/seek/tick` to drive the timeline\n * - Rendering updates when `protocol` or `currentTime` changes\n */\nexport async function createRenderer(opts: RendererOptions): Promise<Renderer> {\n const validator = createValidator()\n const protocolInput: Ref<IVideoProtocol> | ShallowRef<IVideoProtocol>\n = isRef(opts.protocol) ? opts.protocol : shallowRef(opts.protocol)\n const validatedProtocol: ShallowRef<IVideoProtocol> = shallowRef(\n validator.verify(cloneProtocol(unref(protocolInput))),\n )\n\n const app = opts.app ?? await create2dApp(opts.appOptions)\n const layer = new Container()\n app.stage.addChild(layer)\n\n const resourceManager = createResourceManager({ dir: opts.resourceDir })\n const resourceWarmUp = new Set<string>()\n const displayCache = new Map<string, PixiDisplayObject>()\n const displayLoading = new Map<string, Promise<PixiDisplayObject | undefined>>()\n const mp4ClipUnsupportedKeys = new Set<string>()\n const mp4ClipErrorLoggedKeys = new Set<string>()\n const videoSourceMode = opts.videoSourceMode ?? 'auto'\n type VideoEntry = (\n | {\n kind: 'mp4clip'\n clip: MP4Clip\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'element'\n video: HTMLVideoElement\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'frozen'\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n )\n const videoEntries = new Map<string, VideoEntry>()\n const videoObjectUrls = new Map<HTMLVideoElement, string>()\n\n const currentTime = ref(0)\n const isPlaying = ref(false)\n const duration = computed(() => computeDuration(validatedProtocol.value))\n const audioManager: AudioManagerApi = new AudioManager(validatedProtocol.value) as unknown as AudioManagerApi\n\n let rafId: number | undefined\n let lastTickAt = 0\n let renderGeneration = 0\n\n interface RenderTask {\n app: Application\n layer: Container\n protocol: IVideoProtocol\n at: number\n getDisplay: (segment: SegmentUnion) => Promise<PixiDisplayObject | undefined>\n }\n\n async function renderScene(task: RenderTask) {\n const generation = renderGeneration\n const { protocol, at, layer } = task\n const renderAt = normalizeRenderTime(protocol, at)\n const active = collectActiveSegments(protocol, renderAt)\n const stageWidth = task.app.renderer.width\n const stageHeight = task.app.renderer.height\n\n audioManager.sync(at, isPlaying.value)\n\n const renders: (PixiDisplayObject | undefined)[] = []\n for (const { segment } of active) {\n if (generation !== renderGeneration)\n return\n const display = await task.getDisplay(segment)\n if (generation !== renderGeneration)\n return\n if (!display)\n continue\n if ((display as { destroyed?: boolean }).destroyed)\n continue\n applyDisplayProps(display, segment, stageWidth, stageHeight)\n if (isVideoSegment(segment))\n await updateVideoFrame(segment, renderAt)\n if (generation !== renderGeneration)\n return\n renders.push(display)\n }\n\n if (generation !== renderGeneration)\n return\n layer.removeChildren()\n const cleaned = renders.filter(Boolean) as PixiDisplayObject[]\n if (cleaned.length)\n layer.addChild(...cleaned)\n if (generation !== renderGeneration)\n return\n task.app.render()\n }\n\n const queueRender = createRenderQueue(() => renderScene({\n app,\n layer,\n protocol: validatedProtocol.value,\n at: currentTime.value,\n getDisplay: getDisplayForSegment,\n }))\n\n const scope = effectScope()\n scope.run(() => {\n // Sync external protocol mutations into a verified snapshot the renderer can rely on.\n watch(\n () => unref(protocolInput),\n (protocol) => {\n try {\n validatedProtocol.value = validator.verify(cloneProtocol(protocol))\n }\n catch (err) {\n console.error('[renderer] invalid protocol update', err)\n return\n }\n audioManager.setProtocol(validatedProtocol.value)\n renderGeneration += 1\n clearDisplays()\n if (opts.warmUpResources !== false)\n warmUpResources(validatedProtocol.value)\n cleanupCache(validatedProtocol.value)\n clampCurrentTime()\n if (!opts.manualRender)\n queueRender()\n },\n { deep: true, immediate: true },\n )\n\n if (!opts.manualRender) {\n // React to time changes.\n watch(currentTime, () => {\n clampCurrentTime()\n queueRender()\n })\n }\n\n // Keep duration/currentTime in sync with protocol updates.\n watch(duration, () => clampCurrentTime())\n })\n\n function clampCurrentTime() {\n const nextDuration = duration.value\n if (nextDuration <= 0)\n currentTime.value = 0\n else if (currentTime.value > nextDuration)\n currentTime.value = nextDuration\n else if (currentTime.value < 0)\n currentTime.value = 0\n }\n\n function warmUpResources(protocol: IVideoProtocol) {\n for (const url of collectResourceUrls(protocol)) {\n if (resourceWarmUp.has(url))\n continue\n\n resourceWarmUp.add(url)\n if (inferUrlMediaType(url) === 'video')\n continue\n if (!shouldUseResourceManager(url))\n continue\n resourceManager.add(url).catch(() => {\n // noop – render will fall back to Texture.from(url)\n })\n }\n }\n\n function cleanupCache(protocol: IVideoProtocol) {\n const ids = new Set<string>()\n for (const track of protocol.tracks) {\n for (const child of track.children)\n ids.add(child.id)\n }\n for (const [id, display] of displayCache) {\n if (ids.has(id))\n continue\n display.destroy()\n displayCache.delete(id)\n }\n for (const [id, entry] of videoEntries) {\n if (ids.has(id))\n continue\n destroyVideoEntry(entry)\n videoEntries.delete(id)\n }\n }\n\n function clearDisplays() {\n layer.removeChildren()\n for (const display of displayCache.values()) {\n display.destroy()\n }\n displayCache.clear()\n displayLoading.clear()\n for (const entry of videoEntries.values())\n destroyVideoEntry(entry)\n videoEntries.clear()\n }\n\n function play() {\n if (isPlaying.value)\n return\n isPlaying.value = true\n lastTickAt = performance.now()\n rafId = requestAnimationFrame(loop)\n }\n\n function pause() {\n isPlaying.value = false\n if (rafId !== undefined)\n cancelAnimationFrame(rafId)\n rafId = undefined\n // Stop audio immediately when pausing\n audioManager.sync(currentTime.value, false)\n if (opts.freezeOnPause !== false)\n freezeVideoEntries()\n }\n\n function loop() {\n tick()\n if (isPlaying.value)\n rafId = requestAnimationFrame(loop)\n }\n\n function tick(deltaMs?: number) {\n if (!isPlaying.value && deltaMs === undefined)\n return\n\n const now = performance.now()\n const delta = deltaMs ?? (lastTickAt ? now - lastTickAt : 0)\n lastTickAt = now\n\n if (delta === 0)\n return\n\n currentTime.value = clamp(\n currentTime.value + delta,\n 0,\n duration.value || Number.POSITIVE_INFINITY,\n )\n\n if (duration.value > 0 && currentTime.value >= duration.value)\n pause()\n\n // render happens via watch on currentTime\n }\n\n function seek(time: number) {\n currentTime.value = clamp(time, 0, duration.value || Number.POSITIVE_INFINITY)\n }\n\n async function renderAt(time: number) {\n currentTime.value = clamp(time, 0, duration.value || Number.POSITIVE_INFINITY)\n await queueRender()\n }\n\n async function getDisplayForSegment(segment: SegmentUnion) {\n const cached = displayCache.get(segment.id)\n if (cached)\n return cached\n\n const loading = displayLoading.get(segment.id)\n if (loading)\n return loading\n\n const promise = loadDisplay(segment)\n displayLoading.set(segment.id, promise)\n\n const display = await promise\n if (display)\n displayCache.set(segment.id, display)\n\n displayLoading.delete(segment.id)\n return display\n }\n\n async function loadDisplay(segment: SegmentUnion): Promise<PixiDisplayObject | undefined> {\n // prioritize static resources via protocol resource manager\n if (segment.segmentType === 'frames' || segment.segmentType === 'sticker') {\n if (!segment.url)\n return placeholder(segment.segmentType)\n\n if ('type' in segment && segment.type === 'video') {\n if (isRenderableVideoUrl(segment.url)) {\n const sprite = await loadVideoSprite(segment)\n if (sprite)\n return sprite\n return placeholder(segment.segmentType, segment.url)\n }\n }\n\n const texture = await loadTexture(segment.url)\n if (texture)\n return new Sprite(texture)\n return placeholder(segment.segmentType, segment.url)\n }\n\n if (segment.segmentType === 'text')\n return await buildTextDisplay(segment)\n\n if (segment.segmentType === 'effect' || segment.segmentType === 'filter')\n return undefined\n\n // audio segments do not render visuals\n return undefined\n }\n\n async function buildTextDisplay(segment: ITextSegment): Promise<PixiDisplayObject | undefined> {\n const content = buildTextContent(segment.texts)\n if (!content)\n return undefined\n\n const [text] = segment.texts\n if (!text)\n return undefined\n\n const bitmap = await renderTextBitmap(content, buildTextCss(text))\n const texture = Texture.from(bitmap)\n return new Sprite(texture)\n }\n\n async function loadTexture(url: string) {\n const isDataUrl = url.startsWith('data:')\n const isHttp = /^https?:\\/\\//.test(url)\n\n if (!isDataUrl && !isHttp) {\n try {\n await resourceManager.add(url)\n const res = await resourceManager.get(url)\n if (res instanceof HTMLImageElement)\n return Texture.from(res)\n }\n catch {\n // fall through to direct image load\n }\n }\n\n // load image directly to avoid invalid path issues with http/data URLs\n return await loadImageTexture(url)\n }\n\n async function loadVideoSprite(segment: SegmentUnion & { type: 'video', url: string }): Promise<Sprite | undefined> {\n const existing = videoEntries.get(segment.id)\n if (existing)\n return existing.sprite\n\n const urlKey = getResourceKey(segment.url)\n const allowMp4Clip = videoSourceMode !== 'element'\n const allowVideoElement = videoSourceMode !== 'mp4clip'\n if (urlKey && mp4ClipUnsupportedKeys.has(urlKey)) {\n if (!allowVideoElement)\n throw new Error(`[renderer] MP4Clip unsupported for ${segment.url}`)\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n return undefined\n }\n\n if (allowMp4Clip) {\n const spriteFromClip = await loadVideoSpriteViaMP4Clip(segment.url).catch((err) => {\n if (urlKey && isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n if (!urlKey || !mp4ClipErrorLoggedKeys.has(urlKey)) {\n if (urlKey)\n mp4ClipErrorLoggedKeys.add(urlKey)\n console.warn('[renderer] failed to load video via MP4Clip', segment.url, err)\n }\n if (!allowVideoElement)\n throw err\n return undefined\n })\n if (spriteFromClip) {\n console.info('[renderer] video source: mp4clip', segment.url)\n videoEntries.set(segment.id, spriteFromClip)\n return spriteFromClip.sprite\n }\n }\n\n if (allowVideoElement) {\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n console.info('[renderer] video source: element', segment.url)\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n }\n\n return undefined\n }\n\n function isMp4ClipUnsupported(err: unknown) {\n if (!(err instanceof Error))\n return false\n const msg = err.message || ''\n return msg.includes('stream is done')\n || msg.includes('not emit ready')\n || msg.includes('tick video timeout')\n }\n\n async function updateVideoFrame(segment: IVideoFramesSegment, at: number) {\n const entry = videoEntries.get(segment.id)\n if (!entry)\n return\n\n try {\n const offsetMs = segment.fromTime ?? 0\n const relativeMs = Math.max(0, at - segment.startTime + offsetMs)\n const relativeUs = Math.floor(relativeMs * 1000)\n if (entry.kind === 'frozen') {\n const urlKey = getResourceKey(segment.url)\n if (!urlKey)\n return\n const revived = await loadVideoEntry(segment.url, urlKey, { sprite: entry.sprite, oldTexture: entry.texture })\n if (!revived)\n return\n videoEntries.set(segment.id, revived)\n return await updateVideoFrame(segment, at)\n }\n if (entry.kind === 'mp4clip') {\n try {\n const res = await entry.clip.tick(relativeUs)\n if (res.video) {\n const ctx = entry.canvas.getContext('2d')\n if (ctx) {\n ctx.drawImage(res.video, 0, 0, entry.canvas.width, entry.canvas.height)\n refreshCanvasTexture(entry.texture)\n }\n res.video.close()\n }\n // Play audio directly from tick result (avoid calling tick twice)\n if (isPlaying.value && res.audio && res.audio.length > 0) {\n const sampleRate = (entry.clip as { meta?: { audioSampleRate?: number } }).meta?.audioSampleRate ?? 48000;\n (audioManager as unknown as { playMp4AudioFrames: (id: string, audio: Float32Array[], sampleRate: number) => void })\n .playMp4AudioFrames(segment.id, res.audio as Float32Array[], sampleRate)\n }\n return\n }\n catch (err) {\n const urlKey = getResourceKey(segment.url)\n if (urlKey && isMp4ClipUnsupported(err)) {\n mp4ClipUnsupportedKeys.add(urlKey)\n entry.clip.destroy()\n if (videoSourceMode !== 'mp4clip') {\n const replacement = await loadVideoSpriteViaElement(segment.url, { sprite: entry.sprite, oldTexture: entry.texture }).catch((elementErr) => {\n console.warn('[renderer] failed to fallback to <video> after MP4Clip error', segment.url, elementErr)\n return undefined\n })\n if (replacement) {\n videoEntries.set(segment.id, replacement)\n return await updateVideoFrame(segment, at)\n }\n }\n }\n if (urlKey && !mp4ClipErrorLoggedKeys.has(urlKey)) {\n mp4ClipErrorLoggedKeys.add(urlKey)\n console.warn('[renderer] MP4Clip tick failed', segment.url, err)\n }\n return\n }\n }\n\n const relativeSec = relativeMs / 1000\n if (!Number.isFinite(relativeSec))\n return\n if (entry.kind !== 'element')\n return\n await updateVideoElementFrame(entry, {\n targetSec: relativeSec,\n playbackRate: segment.playRate ?? 1,\n volume: segment.volume ?? 1,\n })\n }\n catch (err) {\n console.warn('[renderer] update video frame failed', err)\n }\n }\n\n async function loadVideoEntry(url: string, urlKey: string, reuse: { sprite: Sprite, oldTexture?: Texture }) {\n const allowMp4Clip = videoSourceMode !== 'element'\n const allowVideoElement = videoSourceMode !== 'mp4clip'\n if (mp4ClipUnsupportedKeys.has(urlKey)) {\n if (!allowVideoElement)\n throw new Error(`[renderer] MP4Clip unsupported for ${url}`)\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n }\n\n if (allowMp4Clip) {\n const fromClip = await loadVideoSpriteViaMP4Clip(url, reuse).catch((err) => {\n if (isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n if (!allowVideoElement)\n throw err\n return undefined\n })\n if (fromClip)\n return fromClip\n }\n\n if (allowVideoElement)\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n\n return undefined\n }\n\n function isVideoSegment(segment: SegmentUnion): segment is IVideoFramesSegment {\n return segment.segmentType === 'frames'\n && segment.type === 'video'\n && typeof segment.url === 'string'\n && isRenderableVideoUrl(segment.url)\n }\n\n\n function normalizeRenderTime(protocol: IVideoProtocol, at: number) {\n const total = computeDuration(protocol)\n if (total <= 0)\n return 0\n if (at < total)\n return at\n // Keep the last visible frame when playback reaches the end.\n const frameWindow = Math.max(1000 / Math.max(protocol.fps || 30, 1), 1)\n return Math.max(total - frameWindow, 0)\n }\n\n async function getOpfsFile(url: string) {\n const dir = opts.resourceDir ?? DEFAULT_RES_DIR\n try {\n const key = getResourceKey(url)\n if (!key)\n return undefined\n const file = opfsFile(`${dir}/${key}`, 'r')\n if (await file.exists())\n return file\n }\n catch {\n return undefined\n }\n return undefined\n }\n\n function shouldUseResourceManager(url: string) {\n if (!url)\n return false\n if (url.startsWith('data:') || url.startsWith('blob:'))\n return false\n return true\n }\n\n function freezeVideoEntries() {\n for (const [id, entry] of videoEntries) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n videoEntries.set(id, {\n kind: 'frozen',\n canvas: entry.canvas,\n texture: entry.texture,\n sprite: entry.sprite,\n meta: entry.meta,\n })\n continue\n }\n\n if (entry.kind === 'element')\n entry.video.pause()\n }\n }\n\n function destroyVideoEntry(entry: VideoEntry) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n return\n }\n\n if (entry.kind === 'frozen')\n return\n\n entry.video.pause()\n const objectUrl = videoObjectUrls.get(entry.video)\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl)\n videoObjectUrls.delete(entry.video)\n }\n entry.video.removeAttribute('src')\n entry.video.load()\n }\n\n function waitForMediaEvent(target: HTMLMediaElement, type: string, timeoutMs = 1000) {\n return new Promise<void>((resolve, reject) => {\n const timer = window.setTimeout(() => {\n cleanup()\n reject(new Error(`Timed out waiting for media event: ${type}`))\n }, timeoutMs)\n\n const onOk = () => {\n cleanup()\n resolve()\n }\n const onErr = () => {\n cleanup()\n const mediaError = target.error ? `${target.error.code}` : 'unknown'\n reject(new Error(`Media error (${mediaError}) while waiting for ${type}`))\n }\n const cleanup = () => {\n window.clearTimeout(timer)\n target.removeEventListener(type, onOk)\n target.removeEventListener('error', onErr)\n }\n\n target.addEventListener(type, onOk, { once: true })\n target.addEventListener('error', onErr, { once: true })\n })\n }\n\n async function loadVideoSpriteViaMP4Clip(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n let file: ReturnType<typeof opfsFile> | undefined\n if (shouldUseResourceManager(url)) {\n file = await getOpfsFile(url)\n if (!file) {\n await resourceManager.add(url).catch(() => {})\n file = await getOpfsFile(url)\n }\n }\n\n let clip: MP4Clip | undefined\n try {\n if (file) {\n clip = new MP4Clip(file)\n }\n else {\n const res = await fetch(url)\n if (!res.body) {\n const buffer = await res.arrayBuffer()\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(new Uint8Array(buffer))\n controller.close()\n },\n })\n clip = new MP4Clip(stream)\n }\n else {\n clip = new MP4Clip(res.body)\n }\n }\n\n await clip.ready\n\n const { width, height } = clip.meta\n const canvas = document.createElement('canvas')\n canvas.width = width || 1\n canvas.height = height || 1\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'mp4clip', clip, canvas, texture, sprite, meta: { width, height } }\n }\n catch (err) {\n clip?.destroy()\n throw err\n }\n }\n\n function inferUrlMediaType(url: string): 'video' | 'image' | 'audio' | 'unknown' {\n const raw = url.split('#')[0]!.split('?')[0]!\n const ext = raw.split('/').pop()?.split('.').pop()?.toLowerCase() ?? ''\n if (['mp4', 'm4v', 'mov', 'webm'].includes(ext))\n return 'video'\n if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif'].includes(ext))\n return 'image'\n if (['mp3', 'wav', 'aac', 'm4a', 'ogg', 'flac'].includes(ext))\n return 'audio'\n return 'unknown'\n }\n\n function isRenderableVideoUrl(url: string) {\n const kind = inferUrlMediaType(url)\n if (kind === 'image' || kind === 'audio')\n return false\n // Treat unknown as video to support blob URLs or extension-less endpoints.\n return true\n }\n\n async function loadVideoSpriteViaElement(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n const video = document.createElement('video')\n video.crossOrigin = 'anonymous'\n video.muted = false\n video.playsInline = true\n video.preload = 'metadata'\n video.src = url\n video.load()\n\n try {\n await waitForMediaEvent(video, 'loadedmetadata', 15000)\n }\n catch (err) {\n video.pause()\n const objectUrl = videoObjectUrls.get(video)\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl)\n videoObjectUrls.delete(video)\n }\n video.removeAttribute('src')\n video.load()\n throw err\n }\n\n const width = video.videoWidth || 1\n const height = video.videoHeight || 1\n\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'element', video, canvas, texture, sprite, meta: { width, height } }\n }\n\n\n async function updateVideoElementFrame(entry: Extract<VideoEntry, { kind: 'element' }>, opts: { targetSec: number, playbackRate: number, volume?: number }) {\n const { video, canvas, texture } = entry\n\n video.playbackRate = Number.isFinite(opts.playbackRate) && opts.playbackRate > 0 ? opts.playbackRate : 1\n video.volume = Math.max(0, Math.min(1, opts.volume ?? 1))\n\n if (isPlaying.value)\n video.play().catch(() => {})\n else\n video.pause()\n\n const duration = Number.isFinite(video.duration) && video.duration > 0 ? video.duration : null\n const targetSec = duration ? Math.min(opts.targetSec, Math.max(duration - 0.03, 0)) : opts.targetSec\n\n const current = video.currentTime\n const drift = Math.abs(current - targetSec)\n const driftThreshold = isPlaying.value ? 0.25 : 0.03\n if (Number.isFinite(current) && drift > driftThreshold) {\n try {\n video.currentTime = targetSec\n }\n catch {\n // ignore seek errors for not-yet-ready media\n }\n await waitForMediaEvent(video, 'seeked', 250).catch(() => {})\n }\n\n if (video.readyState < 2) {\n // Avoid blocking the render queue for too long.\n await waitForMediaEvent(video, 'canplay', 250).catch(() => {})\n if (video.readyState < 2)\n return\n }\n\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height)\n refreshCanvasTexture(texture)\n }\n\n function loadImageTexture(url: string): Promise<Texture | undefined> {\n return new Promise((resolve) => {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => resolve(Texture.from(img))\n img.onerror = () => {\n console.warn('[renderer] failed to load image', url)\n resolve(undefined)\n }\n img.src = url\n })\n }\n\n function refreshCanvasTexture(texture: Texture) {\n const source = texture.source\n if ('update' in source && typeof source.update === 'function') {\n source.update()\n return\n }\n\n if (typeof texture.update === 'function')\n texture.update()\n }\n\n function destroy() {\n pause()\n renderGeneration += 1\n scope.stop()\n clearDisplays()\n layer.destroy({ children: true })\n displayCache.clear()\n displayLoading.clear()\n resourceWarmUp.clear()\n if (!opts.app)\n app.destroy()\n \n audioManager.destroy()\n }\n\n if (opts.autoPlay)\n play()\n\n return {\n app,\n layer,\n currentTime,\n duration,\n isPlaying,\n play,\n pause,\n tick,\n seek,\n renderAt,\n destroy,\n }\n}\n\nfunction createRenderQueue(job: () => Promise<void> | void) {\n let queued = false\n let running = false\n let pending: Promise<void> | null = null\n let resolvePending: (() => void) | null = null\n\n const run = async () => {\n if (!pending) {\n pending = new Promise((resolve) => {\n resolvePending = resolve\n })\n }\n const done = pending\n if (running) {\n queued = true\n return done\n }\n running = true\n do {\n queued = false\n await job()\n } while (queued)\n running = false\n resolvePending?.()\n pending = null\n resolvePending = null\n return done\n }\n\n return run\n}\n","import type { file as opfsFile } from 'opfs-tools'\nimport type { ICombinatorOpts } from '@webav/av-cliper'\nimport { Combinator, MP4Clip, OffscreenSprite } from '@webav/av-cliper'\n\nexport type VideoConcatSource =\n | string\n | ReadableStream<Uint8Array>\n | Blob\n | ReturnType<typeof opfsFile>\n\nexport interface ConcatVideoSource {\n source: VideoConcatSource\n}\n\nexport interface ConcatVideoOptions extends Omit<ICombinatorOpts, 'width' | 'height'> {\n width?: number\n height?: number\n onProgress?: (progress: number) => void\n}\n\nexport interface ConcatVideoResult {\n stream: ReadableStream<Uint8Array>\n width: number\n height: number\n durationMs: number\n destroy: () => void\n}\n\nfunction isOpfsFile(value: unknown): value is ReturnType<typeof opfsFile> {\n return typeof value === 'object'\n && value !== null\n && 'createReader' in value\n && 'getSize' in value\n}\n\nfunction isReadableStream(value: unknown): value is ReadableStream<Uint8Array> {\n return typeof ReadableStream !== 'undefined' && value instanceof ReadableStream\n}\n\nfunction normalizeInput(input: ConcatVideoSource | VideoConcatSource): ConcatVideoSource {\n if (typeof input === 'string' || input instanceof Blob || isOpfsFile(input) || isReadableStream(input))\n return { source: input }\n return input\n}\n\nasync function toClipSource(source: VideoConcatSource): Promise<ReadableStream<Uint8Array> | ReturnType<typeof opfsFile>> {\n if (typeof source === 'string') {\n const res = await fetch(source)\n if (!res.body)\n throw new Error('concatVideos: unable to read video stream from url')\n return res.body\n }\n\n if (source instanceof Blob)\n return source.stream() as ReadableStream<Uint8Array>\n\n return source\n}\n\nfunction wrapStreamWithCleanup(\n stream: ReadableStream<Uint8Array>,\n cleanup: () => void,\n): ReadableStream<Uint8Array> {\n let cleaned = false\n const finalize = () => {\n if (cleaned)\n return\n cleaned = true\n cleanup()\n }\n\n const reader = stream.getReader()\n return new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read()\n if (done) {\n finalize()\n controller.close()\n return\n }\n controller.enqueue(value)\n },\n async cancel(reason) {\n try {\n await reader.cancel(reason)\n }\n finally {\n finalize()\n }\n },\n })\n}\n\nexport async function concatVideos(\n inputs: Array<ConcatVideoSource | VideoConcatSource>,\n opts: ConcatVideoOptions = {},\n): Promise<ConcatVideoResult> {\n if (inputs.length === 0)\n throw new Error('concatVideos: expected at least one source')\n\n const {\n onProgress,\n width: requestedWidth,\n height: requestedHeight,\n ...combinatorOpts\n } = opts\n\n const normalized = inputs.map(normalizeInput)\n\n const [first, ...rest] = normalized\n const firstSource = await toClipSource(first.source)\n const firstClip = new MP4Clip(firstSource)\n await firstClip.ready\n\n const width = requestedWidth ?? Math.round(firstClip.meta.width || 0)\n const height = requestedHeight ?? Math.round(firstClip.meta.height || 0)\n if (!width || !height)\n {\n firstClip.destroy()\n throw new Error('concatVideos: output width/height is required')\n }\n\n const combinator = new Combinator({\n ...combinatorOpts,\n width,\n height,\n })\n\n if (onProgress)\n combinator.on('OutputProgress', onProgress)\n\n let offset = 0\n\n const addClip = async (clip: MP4Clip) => {\n const duration = clip.meta.duration\n if (!Number.isFinite(duration) || duration <= 0) {\n clip.destroy()\n throw new Error('concatVideos: invalid clip duration')\n }\n\n const sprite = new OffscreenSprite(clip)\n try {\n await sprite.ready\n sprite.rect.x = 0\n sprite.rect.y = 0\n sprite.rect.w = width\n sprite.rect.h = height\n sprite.time.offset = offset\n sprite.time.duration = duration\n\n await combinator.addSprite(sprite)\n offset += duration\n }\n finally {\n sprite.destroy()\n }\n }\n\n try {\n await addClip(firstClip)\n for (const entry of rest) {\n const source = await toClipSource(entry.source)\n const clip = new MP4Clip(source)\n await clip.ready\n await addClip(clip)\n }\n }\n catch (err) {\n combinator.destroy()\n throw err\n }\n\n const maxTime = offset\n const stream = combinator.output({ maxTime })\n const destroy = () => {\n combinator.destroy()\n }\n\n return {\n stream: wrapStreamWithCleanup(stream, destroy),\n width,\n height,\n durationMs: Math.round(maxTime / 1000),\n destroy,\n }\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { IClip } from '@webav/av-cliper'\nimport type { ApplicationOptions } from 'pixi.js'\nimport { Application } from 'pixi.js'\nimport type { RendererOptions } from './renderer-core'\nimport { createRenderer } from './renderer-core'\nimport { computeDuration } from './helpers'\n\nexport interface ProtocolVideoClipOptions {\n width?: number\n height?: number\n fps?: number\n appOptions?: Partial<ApplicationOptions>\n rendererOptions?: Partial<Omit<RendererOptions, 'protocol' | 'app' | 'appOptions'>>\n}\n\ninterface ClipMeta {\n width: number\n height: number\n duration: number\n}\n\nexport class ProtocolVideoClip implements IClip {\n readonly ready: Promise<ClipMeta>\n meta: ClipMeta\n\n private readonly protocol: IVideoProtocol\n private readonly options: ProtocolVideoClipOptions\n private renderer?: Awaited<ReturnType<typeof createRenderer>>\n private app?: Application\n private destroyed = false\n\n constructor(protocol: IVideoProtocol, options: ProtocolVideoClipOptions = {}) {\n this.protocol = protocol\n this.options = options\n\n const width = options.width ?? protocol.width\n const height = options.height ?? protocol.height\n const durationMs = computeDuration(protocol)\n this.meta = {\n width,\n height,\n duration: Math.max(0, Math.round(durationMs * 1000)),\n }\n\n this.ready = this.init()\n }\n\n private async init() {\n const width = this.options.width ?? this.protocol.width\n const height = this.options.height ?? this.protocol.height\n if (!width || !height)\n throw new Error('ProtocolVideoClip: output width/height is required')\n\n const app = new Application()\n await app.init({\n width,\n height,\n backgroundAlpha: 0,\n ...this.options.appOptions,\n })\n app.ticker.stop()\n this.app = app\n\n const rendererOptions = this.options.rendererOptions ?? {}\n const renderer = await createRenderer({\n protocol: this.protocol,\n app,\n ...rendererOptions,\n autoPlay: false,\n freezeOnPause: false,\n manualRender: true,\n videoSourceMode: rendererOptions.videoSourceMode ?? 'mp4clip',\n })\n this.renderer = renderer\n\n const durationMs = renderer.duration.value\n this.meta = {\n width: app.renderer.width,\n height: app.renderer.height,\n duration: Math.max(0, Math.round(durationMs * 1000)),\n }\n\n return this.meta\n }\n\n async tick(time: number): Promise<{\n video?: VideoFrame | ImageBitmap | null\n audio?: Float32Array[]\n state: 'done' | 'success'\n }> {\n const emptyAudio: Float32Array[] = []\n if (this.destroyed)\n return { audio: emptyAudio, state: 'done' }\n\n await this.ready\n if (!this.renderer)\n return { audio: emptyAudio, state: 'done' }\n\n const durationUs = this.meta.duration\n if (time >= durationUs)\n return { audio: emptyAudio, state: 'done' }\n\n const clampedUs = Math.max(0, Math.min(time, durationUs))\n await this.renderer.renderAt(clampedUs / 1000)\n\n const frame = new VideoFrame(this.renderer.app.canvas, {\n timestamp: time,\n })\n\n return {\n video: frame,\n audio: emptyAudio,\n state: 'success',\n }\n }\n\n async clone(): Promise<this> {\n const copy = new ProtocolVideoClip(this.protocol, this.options) as this\n await copy.ready\n return copy\n }\n\n destroy() {\n if (this.destroyed)\n return\n this.destroyed = true\n this.renderer?.destroy()\n this.app?.destroy(true)\n }\n}\n","import type { IAudioSegment, IVideoFramesSegment, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { IClip, ICombinatorOpts } from '@webav/av-cliper'\nimport { AudioClip, Combinator, MP4Clip, OffscreenSprite } from '@webav/av-cliper'\nimport { ProtocolVideoClip } from './protocol-clip'\nimport type { ProtocolVideoClipOptions } from './protocol-clip'\n\nexport interface ComposeProtocolOptions extends Omit<ICombinatorOpts, 'width' | 'height' | 'fps'> {\n width?: number\n height?: number\n fps?: number\n onProgress?: (progress: number) => void\n clipOptions?: ProtocolVideoClipOptions\n audioSprites?: (protocol: IVideoProtocol) => Promise<OffscreenSprite[]>\n}\n\nexport interface ComposeProtocolResult {\n stream: ReadableStream<Uint8Array>\n width: number\n height: number\n durationMs: number\n destroy: () => void\n}\n\ninterface ClipMeta {\n width: number\n height: number\n duration: number\n}\n\ninterface SegmentAudioInput {\n startTime: number\n endTime: number\n fromTime?: number\n playRate?: number\n volume?: number\n fadeInDuration?: number\n fadeOutDuration?: number\n}\n\ninterface SegmentAudioConfig {\n fromUs: number\n segmentDurationUs: number\n playRate: number\n baseVolume: number\n fadeInUs: number\n fadeOutUs: number\n}\n\nconst RESOURCE_TIMEOUT_MS = 12000\n\nfunction withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = globalThis.setTimeout(() => {\n reject(new Error(`composeProtocol: ${label} timed out (${timeoutMs}ms)`))\n }, timeoutMs)\n promise\n .then((value) => {\n globalThis.clearTimeout(timer)\n resolve(value)\n })\n .catch((err) => {\n globalThis.clearTimeout(timer)\n reject(err)\n })\n })\n}\n\nclass SegmentAudioClip implements IClip {\n readonly ready: Promise<ClipMeta>\n\n private clipMeta: ClipMeta = {\n width: 0,\n height: 0,\n duration: 0,\n }\n\n constructor(\n private readonly sourceClip: IClip,\n private readonly config: SegmentAudioConfig,\n ) {\n this.ready = this.sourceClip.ready.then((meta) => {\n const playbackDurationUs = Math.round(this.config.segmentDurationUs * this.config.playRate)\n const availableUs = Math.max(0, meta.duration - this.config.fromUs)\n this.clipMeta = {\n width: meta.width,\n height: meta.height,\n duration: Math.max(0, Math.min(playbackDurationUs, availableUs)),\n }\n return this.meta\n })\n }\n\n get meta() {\n return { ...this.clipMeta }\n }\n\n async tick(time: number): ReturnType<IClip['tick']> {\n const relativeSourceUs = Math.max(0, Math.round(time))\n const relativeTimelineUs = Math.round(relativeSourceUs / this.config.playRate)\n if (relativeTimelineUs >= this.config.segmentDurationUs) {\n return {\n audio: [],\n state: 'done',\n }\n }\n\n const sourceUs = this.config.fromUs + relativeSourceUs\n const result = await this.sourceClip.tick(sourceUs)\n closeFrame(result.video)\n\n const gain = this.resolveGain(relativeTimelineUs)\n return {\n audio: applyGain(result.audio ?? [], gain),\n state: result.state,\n }\n }\n\n async clone(): Promise<this> {\n const clonedSource = await this.sourceClip.clone()\n const copy = new SegmentAudioClip(clonedSource, this.config) as this\n await copy.ready\n return copy\n }\n\n destroy() {\n this.sourceClip.destroy()\n }\n\n private resolveGain(relativeTimelineUs: number): number {\n let volumeMultiplier = 1\n if (this.config.fadeInUs > 0 && relativeTimelineUs < this.config.fadeInUs)\n volumeMultiplier = Math.max(0, relativeTimelineUs / this.config.fadeInUs)\n\n const remainingUs = this.config.segmentDurationUs - relativeTimelineUs\n if (this.config.fadeOutUs > 0 && remainingUs < this.config.fadeOutUs)\n volumeMultiplier = Math.min(volumeMultiplier, Math.max(0, remainingUs / this.config.fadeOutUs))\n\n return this.config.baseVolume * volumeMultiplier\n }\n}\n\nfunction closeFrame(frame: unknown) {\n if (!frame || typeof frame !== 'object')\n return\n const maybeClose = (frame as { close?: unknown }).close\n if (typeof maybeClose === 'function')\n maybeClose.call(frame)\n}\n\nfunction applyGain(audio: Float32Array[], gain: number): Float32Array[] {\n if (!audio.length || gain >= 0.999)\n return audio\n\n if (gain <= 0)\n return audio.map(chan => new Float32Array(chan.length))\n\n return audio.map((chan) => {\n const out = new Float32Array(chan.length)\n for (let i = 0; i < chan.length; i++)\n out[i] = chan[i]! * gain\n return out\n })\n}\n\nfunction toUs(ms: number): number {\n if (!Number.isFinite(ms))\n return 0\n return Math.max(0, Math.round(ms * 1000))\n}\n\nfunction normalizeVolume(volume?: number): number {\n if (typeof volume !== 'number' || !Number.isFinite(volume))\n return 1\n return Math.max(0, Math.min(1, volume))\n}\n\nfunction normalizePlayRate(playRate?: number): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return Math.max(0.1, Math.min(100, playRate))\n}\n\nfunction createSegmentAudioConfig(segment: SegmentAudioInput): SegmentAudioConfig {\n const durationMs = Math.max(0, segment.endTime - segment.startTime)\n const fadeInMs = Math.max(0, Math.min(segment.fadeInDuration ?? 0, durationMs))\n const fadeOutMs = Math.max(0, Math.min(segment.fadeOutDuration ?? 0, durationMs))\n return {\n fromUs: toUs(segment.fromTime ?? 0),\n segmentDurationUs: toUs(durationMs),\n playRate: normalizePlayRate(segment.playRate),\n baseVolume: normalizeVolume(segment.volume),\n fadeInUs: toUs(fadeInMs),\n fadeOutUs: toUs(fadeOutMs),\n }\n}\n\nfunction isAudioSegment(segment: SegmentUnion): segment is IAudioSegment {\n return segment.segmentType === 'audio'\n}\n\nfunction isVideoSegmentWithAudio(segment: SegmentUnion): segment is IVideoFramesSegment {\n return segment.segmentType === 'frames' && segment.type === 'video'\n}\n\nasync function fetchReadable(url: string, timeoutMs: number = RESOURCE_TIMEOUT_MS): Promise<ReadableStream<Uint8Array>> {\n const controller = new AbortController()\n const timeoutId = globalThis.setTimeout(() => controller.abort(), timeoutMs)\n try {\n const response = await fetch(url, { signal: controller.signal })\n if (!response.body)\n throw new Error(`composeProtocol: unable to read resource stream: ${url}`)\n return response.body\n }\n catch (err) {\n if (controller.signal.aborted)\n throw new Error(`composeProtocol: loading resource timed out (${timeoutMs}ms): ${url}`)\n throw err\n }\n finally {\n globalThis.clearTimeout(timeoutId)\n }\n}\n\nasync function createSegmentAudioSprite(sourceClip: IClip, segment: SegmentAudioInput): Promise<OffscreenSprite> {\n const config = createSegmentAudioConfig(segment)\n const clip = new SegmentAudioClip(sourceClip, config)\n const sprite = new OffscreenSprite(clip)\n try {\n await withTimeout(sprite.ready, RESOURCE_TIMEOUT_MS, 'prepare audio sprite')\n }\n catch (err) {\n sprite.destroy()\n throw err\n }\n\n sprite.time.offset = toUs(segment.startTime)\n sprite.time.duration = config.segmentDurationUs\n sprite.time.playbackRate = config.playRate\n return sprite\n}\n\nasync function createAudioSpriteFromAudioSegment(segment: IAudioSegment): Promise<OffscreenSprite> {\n const stream = await fetchReadable(segment.url)\n const sourceClip = new AudioClip(stream)\n return await createSegmentAudioSprite(sourceClip, segment)\n}\n\nasync function createAudioSpriteFromVideoSegment(segment: IVideoFramesSegment): Promise<OffscreenSprite> {\n const stream = await fetchReadable(segment.url)\n const sourceClip = new MP4Clip(stream, { audio: true })\n return await createSegmentAudioSprite(sourceClip, segment)\n}\n\nasync function createProtocolAudioSprites(protocol: IVideoProtocol): Promise<OffscreenSprite[]> {\n const tasks: Array<Promise<OffscreenSprite>> = []\n for (const track of protocol.tracks) {\n for (const child of track.children) {\n if (child.endTime <= child.startTime)\n continue\n\n if (isAudioSegment(child)) {\n if (normalizeVolume(child.volume) <= 0)\n continue\n tasks.push(createAudioSpriteFromAudioSegment(child))\n continue\n }\n\n if (isVideoSegmentWithAudio(child)) {\n if (normalizeVolume(child.volume) <= 0)\n continue\n tasks.push(createAudioSpriteFromVideoSegment(child))\n }\n }\n }\n\n if (!tasks.length)\n return []\n\n const settled = await Promise.allSettled(tasks)\n const sprites: OffscreenSprite[] = []\n for (const item of settled) {\n if (item.status === 'fulfilled') {\n sprites.push(item.value)\n continue\n }\n console.warn('[compose] skip audio sprite due to load failure', item.reason)\n }\n return sprites\n}\n\nfunction destroySprites(sprites: OffscreenSprite[]) {\n for (const sprite of sprites)\n sprite.destroy()\n}\n\nfunction wrapStreamWithCleanup(\n stream: ReadableStream<Uint8Array>,\n cleanup: () => void,\n): ReadableStream<Uint8Array> {\n let cleaned = false\n const finalize = () => {\n if (cleaned)\n return\n cleaned = true\n cleanup()\n }\n\n const reader = stream.getReader()\n return new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read()\n if (done) {\n finalize()\n controller.close()\n return\n }\n controller.enqueue(value)\n },\n async cancel(reason) {\n try {\n await reader.cancel(reason)\n }\n finally {\n finalize()\n }\n },\n })\n}\n\nexport async function composeProtocol(\n protocol: IVideoProtocol,\n opts: ComposeProtocolOptions = {},\n): Promise<ComposeProtocolResult> {\n const {\n width: requestedWidth,\n height: requestedHeight,\n fps: requestedFps,\n onProgress,\n clipOptions,\n audioSprites,\n ...combinatorOpts\n } = opts\n\n const width = requestedWidth ?? protocol.width\n const height = requestedHeight ?? protocol.height\n if (!width || !height)\n throw new Error('composeProtocol: output width/height is required')\n\n const fps = requestedFps ?? protocol.fps\n\n const resolvedAudioSprites = combinatorOpts.audio === false\n ? []\n : (typeof audioSprites === 'function'\n ? await audioSprites(protocol)\n : await createProtocolAudioSprites(protocol))\n\n const audio = combinatorOpts.audio ?? (resolvedAudioSprites.length > 0 ? undefined : false)\n const combinator = new Combinator({\n ...combinatorOpts,\n audio,\n width,\n height,\n fps,\n })\n\n if (onProgress)\n combinator.on('OutputProgress', onProgress)\n\n let clip: ProtocolVideoClip | undefined\n let sprite: OffscreenSprite | undefined\n try {\n clip = new ProtocolVideoClip(protocol, {\n width,\n height,\n fps,\n ...clipOptions,\n rendererOptions: {\n warmUpResources: false,\n ...clipOptions?.rendererOptions,\n },\n })\n await clip.ready\n\n sprite = new OffscreenSprite(clip)\n await sprite.ready\n sprite.time.offset = 0\n sprite.time.duration = clip.meta.duration\n sprite.rect.x = 0\n sprite.rect.y = 0\n sprite.rect.w = clip.meta.width\n sprite.rect.h = clip.meta.height\n\n await combinator.addSprite(sprite, { main: true })\n\n for (const extra of resolvedAudioSprites)\n await combinator.addSprite(extra)\n }\n catch (err) {\n destroySprites(resolvedAudioSprites)\n sprite?.destroy()\n clip?.destroy()\n combinator.destroy()\n throw err\n }\n\n const maxTime = clip?.meta.duration ?? 0\n if (!maxTime) {\n destroySprites(resolvedAudioSprites)\n sprite?.destroy()\n clip?.destroy()\n combinator.destroy()\n throw new Error('composeProtocol: protocol has no duration')\n }\n\n const stream = combinator.output({ maxTime })\n let destroyed = false\n const destroy = () => {\n if (destroyed)\n return\n destroyed = true\n destroySprites(resolvedAudioSprites)\n sprite?.destroy()\n clip?.destroy()\n combinator.destroy()\n }\n\n return {\n stream: wrapStreamWithCleanup(stream, destroy),\n width,\n height,\n durationMs: Math.round(maxTime / 1000),\n destroy,\n }\n}\n"],"names":["createApp","opts","app","Application","resolveFillSize","mode","sourceWidth","sourceHeight","stageWidth","stageHeight","safeSourceWidth","safeSourceHeight","sourceRatio","stageRatio","computeSegmentLayout","segment","fillMode","width","height","transform","px","py","sx","sy","rotation","finalWidth","finalHeight","centerX","centerY","collectResourceUrls","protocol","urls","track","collectActiveSegments","at","active","trackIndex","childIndex","a","b","aTrack","bTrack","aIsMain","bIsMain","total","aOrder","bOrder","applyDisplayProps","display","opacity","readOpacity","Sprite","layout","Texture","placeholderTexture","Graphics","stringToColor","hasOpacity","placeholder","key","url","g","color","svg","hash","i","computeDuration","endTimes","seg","clamp","num","min","max","cloneProtocol","raw","toRaw","AudioManager","currentTime","isPlaying","activeSegments","activeAudioKeys","activeVideoKeys","loop","source","state","id","audio","sampleRate","volume","gainNode","clip","startUs","fps","existing","elapsedUs","expectedUs","entry","gain","offset","playRate","relativeMs","sourceOffsetMs","existingLoop","sourceDurationMs","maxSourceOffsetMs","segmentMaxSourceSec","mediaDurationSec","effectiveMaxSourceSec","targetSourceSec","isSourceExhausted","targetVolume","seekDriftThresholdSec","seekCooldownMs","largeJumpMs","rewindMs","lastTimelineMs","lastSourceSec","deltaTimelineMs","shouldSeek","predictedSourceSec","driftSec","cooldownPassed","maybePromise","stopped","timeUs","startAt","first","stepUs","sources","timer","maxSourceOffsetUs","initialized","sourceStepUs","play","playbackRate","channels","len","buffer","data","safePlaybackRate","nextStart","duration","index","map","el","baseVolume","segmentDuration","fadeInDuration","fadeOutDuration","volumeMultiplier","timeUntilEnd","cached","loading","loadingPromise","response","WebAVAudioClip","e","meta","audioSampleRate","DEFAULT_TEXT_BITMAP_CACHE_LIMIT","textBitmapCache","textBitmapCacheLimit","touchCache","value","trimCache","oldestKey","bitmap","buildTextContent","texts","item","buildTextCss","text","fontFamily","fontSize","fontWeight","fontStyle","fill","align","css","angle","offsetX","offsetY","blur","renderTextBitmap","content","cssText","renderTxt2ImgBitmap","DEFAULT_RES_DIR","createRenderer","validator","createValidator","protocolInput","isRef","shallowRef","validatedProtocol","unref","create2dApp","layer","Container","resourceManager","createResourceManager","resourceWarmUp","displayCache","displayLoading","mp4ClipUnsupportedKeys","mp4ClipErrorLoggedKeys","videoSourceMode","videoEntries","videoObjectUrls","ref","computed","audioManager","rafId","lastTickAt","renderGeneration","renderScene","task","generation","renderAt","normalizeRenderTime","renders","isVideoSegment","updateVideoFrame","cleaned","queueRender","createRenderQueue","getDisplayForSegment","scope","effectScope","watch","err","clearDisplays","warmUpResources","cleanupCache","clampCurrentTime","nextDuration","inferUrlMediaType","shouldUseResourceManager","ids","child","destroyVideoEntry","pause","freezeVideoEntries","tick","deltaMs","now","delta","seek","time","promise","loadDisplay","isRenderableVideoUrl","sprite","loadVideoSprite","texture","loadTexture","buildTextDisplay","isDataUrl","isHttp","res","loadImageTexture","urlKey","getResourceKey","allowMp4Clip","allowVideoElement","spriteFromElement","loadVideoSpriteViaElement","spriteFromClip","loadVideoSpriteViaMP4Clip","isMp4ClipUnsupported","msg","offsetMs","relativeUs","revived","loadVideoEntry","ctx","refreshCanvasTexture","replacement","elementErr","relativeSec","updateVideoElementFrame","reuse","fromClip","frameWindow","getOpfsFile","dir","file","opfsFile","objectUrl","waitForMediaEvent","target","type","timeoutMs","resolve","reject","cleanup","onOk","onErr","mediaError","MP4Clip","stream","controller","canvas","ext","kind","video","targetSec","current","drift","driftThreshold","img","destroy","job","queued","running","pending","resolvePending","done","isOpfsFile","isReadableStream","normalizeInput","input","toClipSource","wrapStreamWithCleanup","finalize","reader","reason","concatVideos","inputs","onProgress","requestedWidth","requestedHeight","combinatorOpts","normalized","rest","firstSource","firstClip","combinator","Combinator","addClip","OffscreenSprite","maxTime","ProtocolVideoClip","options","durationMs","rendererOptions","renderer","emptyAudio","durationUs","clampedUs","copy","RESOURCE_TIMEOUT_MS","withTimeout","label","SegmentAudioClip","sourceClip","config","playbackDurationUs","availableUs","relativeSourceUs","relativeTimelineUs","sourceUs","result","closeFrame","applyGain","clonedSource","remainingUs","frame","maybeClose","chan","out","toUs","ms","normalizeVolume","normalizePlayRate","createSegmentAudioConfig","fadeInMs","fadeOutMs","isAudioSegment","isVideoSegmentWithAudio","fetchReadable","timeoutId","createSegmentAudioSprite","createAudioSpriteFromAudioSegment","AudioClip","createAudioSpriteFromVideoSegment","createProtocolAudioSprites","tasks","settled","sprites","destroySprites","composeProtocol","requestedFps","clipOptions","audioSprites","resolvedAudioSprites","extra","destroyed"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/2d/index.ts","../src/audio-manager.ts","../src/layout.ts","../src/helpers.ts","../src/timeline/transport.ts","../src/timeline/transition-resolver.ts","../src/timeline/evaluator.ts","../src/timeline/stateful-evaluator.ts","../src/timeline/preview-runner.ts","../src/timeline/compose-runner.ts","../src/timeline/audio-ticker.ts","../src/timeline/visual-plan.ts","../src/timeline/pixi-effects.ts","../src/timeline/compose-audio-plan.ts","../src/text.ts","../src/renderer-core.ts","../src/concat.ts","../src/protocol-clip.ts","../src/compose.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport type { ApplicationOptions } from 'pixi.js'\nimport { Application } from 'pixi.js'\n\ndeclare global {\n\n // eslint-disable-next-line vars-on-top\n var __PIXI_APP__: Application\n}\n\nexport async function createApp(opts?: Partial<ApplicationOptions>) {\n const app = new Application()\n\n await app.init({ resizeTo: window, backgroundAlpha: 0, ...opts })\n\n if (import.meta.env.DEV) {\n globalThis.__PIXI_APP__ = app\n }\n\n return app\n}\n","import type { IAudioSegment, IVideoFramesSegment, IVideoProtocol } from '@video-editor/shared'\nimport type { AudioPlanEvent, TimelinePlan } from './timeline'\ninterface Mp4State {\n sources: AudioBufferSourceNode[]\n nextStartAt?: number\n}\n\ninterface AudioElementState {\n segmentId: string\n url: string\n el: HTMLAudioElement\n pendingPlay?: Promise<void>\n lastTimelineMs?: number\n lastSourceSec?: number\n lastSeekTimelineMs?: number\n}\n\ntype VoicePhase = 'idle' | 'playing' | 'ended'\n\ninterface PlannedVoiceRuntime {\n phase: VoicePhase\n segmentKind: 'audio' | 'video'\n lastSourceSec?: number\n lastGain?: number\n lastRate?: number\n}\n\ntype AudioElementSegment = IAudioSegment | IVideoFramesSegment\n\ninterface AudioManagerOptions {\n resolveMediaElementUrl?: (segment: AudioElementSegment) => string | undefined\n}\n\nexport class AudioManager {\n private protocol: IVideoProtocol\n private options: AudioManagerOptions\n private mp4States = new Map<string, Mp4State>()\n private mp4Gains = new Map<string, GainNode>()\n private plannedVideoAudioGains = new Map<string, number>()\n private plannedVideoAudioRates = new Map<string, number>()\n private plannedVoices = new Map<string, PlannedVoiceRuntime>()\n private audioElements = new Map<string, AudioElementState>()\n private ctx: AudioContext\n\n constructor(protocol: IVideoProtocol, options: AudioManagerOptions = {}) {\n this.protocol = protocol\n this.options = options\n this.ctx = new (window.AudioContext || (window as any).webkitAudioContext)()\n }\n\n public setProtocol(protocol: IVideoProtocol) {\n this.protocol = protocol\n }\n\n public applyTimelinePlan(\n plan: TimelinePlan,\n isPlaying: boolean,\n ) {\n if (!isPlaying) {\n this.stopAll()\n return\n }\n\n if (this.ctx.state === 'suspended')\n this.ctx.resume().catch(() => {})\n\n for (const event of plan.audioEvents)\n this.applyAudioPlanEvent(event)\n }\n\n public resetTimelineState(options: { stop?: boolean } = {}) {\n this.plannedVoices.clear()\n this.plannedVideoAudioGains.clear()\n this.plannedVideoAudioRates.clear()\n if (options.stop)\n this.stopAll()\n }\n\n /**\n * Play audio frames from MP4 video directly.\n * Called by renderer after it gets audio data from clip.tick()\n */\n public playMp4AudioFrames(id: string, audio: Float32Array[] | Float32Array | undefined, sampleRate: number) {\n const pcmChannels = this.normalizePcmChannels(audio)\n if (!pcmChannels)\n return\n\n const key = this.videoKey(id)\n const plannedVolume = this.plannedVideoAudioGains.get(key)\n const volume = typeof plannedVolume === 'number'\n ? this.normalizeVolume(plannedVolume)\n : this.getSegmentVolume(id)\n const plannedRate = this.plannedVideoAudioRates.get(key)\n const playbackRate = typeof plannedRate === 'number'\n ? this.normalizePlayRate(plannedRate)\n : 1\n const gainNode = this.getOrCreateGain(this.mp4Gains, key, volume)\n\n if (this.ctx.state === 'suspended')\n this.ctx.resume().catch(() => {})\n\n // Get or initialize the playback state for this video\n let state = this.mp4States.get(key)\n if (!state) {\n state = {\n sources: [],\n nextStartAt: 0,\n }\n this.mp4States.set(key, state)\n }\n\n // Play the audio frames\n state.nextStartAt = this.playFrames(\n pcmChannels,\n this.normalizeSampleRate(sampleRate),\n state.nextStartAt ?? 0,\n gainNode,\n state.sources,\n playbackRate,\n )\n }\n\n /**\n * Reset MP4 audio playback state (call when seeking or pausing)\n */\n public resetMp4Audio(id: string) {\n const key = this.videoKey(id)\n const state = this.mp4States.get(key)\n if (state) {\n state.nextStartAt = 0\n }\n }\n\n /**\n * Stop and clean up MP4 audio for a video segment\n */\n public stopMp4Audio(id: string) {\n const key = this.videoKey(id)\n const state = this.mp4States.get(key)\n if (state) {\n // Stop all audio buffer sources\n for (const source of state.sources) {\n try {\n source.stop()\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n state.sources.length = 0\n this.mp4States.delete(key)\n this.mp4Gains.delete(key)\n }\n }\n\n public destroy() {\n this.stopAll()\n for (const state of this.audioElements.values())\n this.destroyAudioElement(state.el)\n this.audioElements.clear()\n }\n\n private stopAll() {\n for (const state of this.audioElements.values()) {\n this.pauseAudioElementState(state)\n }\n\n for (const state of this.mp4States.values()) {\n for (const source of state.sources) {\n try {\n source.stop(0)\n source.disconnect()\n }\n catch (e) {\n // Source may already be stopped or disconnected\n }\n }\n state.sources.length = 0\n }\n // Disconnect all gain nodes to completely silence audio\n for (const gain of this.mp4Gains.values()) {\n try {\n gain.disconnect()\n }\n catch (e) {\n // Gain may already be disconnected\n }\n }\n this.mp4States.clear()\n this.mp4Gains.clear()\n this.plannedVoices.clear()\n this.plannedVideoAudioGains.clear()\n this.plannedVideoAudioRates.clear()\n }\n\n private applyAudioPlanEvent(event: AudioPlanEvent) {\n if (event.segmentKind === 'audio') {\n this.applySegmentAudioEvent(event)\n return\n }\n this.applyVideoAudioEvent(event)\n }\n\n private applySegmentAudioEvent(event: AudioPlanEvent) {\n const key = this.audioKey(event.segmentId)\n const voice = this.getOrCreatePlannedVoice(event)\n\n if (event.action === 'stop') {\n const state = this.audioElements.get(key)\n if (!state) {\n this.plannedVoices.delete(event.voiceId)\n return\n }\n this.pauseAudioElementState(state)\n voice.phase = 'ended'\n this.plannedVoices.delete(event.voiceId)\n return\n }\n\n const segment = this.findAudioSegment(event.segmentId)\n if (!segment)\n return\n const state = this.getOrCreateAudioElementState(key, segment)\n\n if (event.action === 'start' || event.action === 'seek') {\n const sourceOffsetMs = this.computeSegmentSourceOffsetMs(\n segment,\n event.atTimelineMs,\n event.sourceTimeMs,\n )\n const { targetSourceSec, isSourceExhausted } = this.resolveAudioElementSourceWindow(\n state,\n segment,\n sourceOffsetMs,\n )\n if (isSourceExhausted) {\n this.pauseAudioElementState(state)\n voice.lastSourceSec = targetSourceSec\n voice.phase = 'ended'\n return\n }\n const needsSeek = targetSourceSec !== undefined\n && (voice.phase !== 'playing'\n || voice.lastSourceSec === undefined\n || Math.abs((voice.lastSourceSec ?? 0) - targetSourceSec) > 0.02)\n if (needsSeek) {\n const seekApplied = this.seekAudioElement(state, targetSourceSec, event.atTimelineMs)\n if (!seekApplied && targetSourceSec > 0.05) {\n // Avoid accidental replay from 0 when target seek is not ready yet.\n this.pauseAudioElementState(state)\n voice.phase = 'idle'\n return\n }\n }\n\n if (typeof event.gain === 'number') {\n const normalizedGain = this.normalizeVolume(event.gain)\n if (voice.lastGain === undefined || Math.abs((voice.lastGain ?? 0) - normalizedGain) > 0.001)\n state.el.volume = normalizedGain\n voice.lastGain = normalizedGain\n }\n if (typeof event.rate === 'number') {\n const normalizedRate = this.normalizePlayRate(event.rate)\n if (voice.lastRate === undefined || Math.abs((voice.lastRate ?? 0) - normalizedRate) > 0.001)\n state.el.playbackRate = normalizedRate\n voice.lastRate = normalizedRate\n }\n if (targetSourceSec !== undefined)\n voice.lastSourceSec = targetSourceSec\n this.playAudioElementState(state)\n voice.phase = 'playing'\n return\n }\n\n if (event.action === 'gain') {\n if (typeof event.gain === 'number') {\n const normalizedGain = this.normalizeVolume(event.gain)\n if (voice.lastGain === undefined || Math.abs((voice.lastGain ?? 0) - normalizedGain) > 0.001)\n state.el.volume = normalizedGain\n voice.lastGain = normalizedGain\n }\n return\n }\n\n if (event.action === 'rate' && typeof event.rate === 'number') {\n const normalizedRate = this.normalizePlayRate(event.rate)\n if (voice.lastRate === undefined || Math.abs((voice.lastRate ?? 0) - normalizedRate) > 0.001)\n state.el.playbackRate = normalizedRate\n voice.lastRate = normalizedRate\n }\n }\n\n private applyVideoAudioEvent(event: AudioPlanEvent) {\n const key = this.videoKey(event.segmentId)\n const voice = this.getOrCreatePlannedVoice(event)\n if (event.action === 'stop') {\n const state = this.audioElements.get(key)\n if (state)\n this.pauseAudioElementState(state)\n this.stopMp4Audio(event.segmentId)\n this.plannedVideoAudioGains.delete(key)\n this.plannedVideoAudioRates.delete(key)\n voice.phase = 'ended'\n this.plannedVoices.delete(event.voiceId)\n return\n }\n\n const segment = this.findVideoSegment(event.segmentId)\n if (!segment)\n return\n const state = this.getOrCreateAudioElementState(key, segment)\n\n if (event.action === 'start' || event.action === 'seek') {\n this.stopMp4Audio(event.segmentId)\n const sourceOffsetMs = this.computeSegmentSourceOffsetMs(\n segment,\n event.atTimelineMs,\n event.sourceTimeMs,\n )\n const { targetSourceSec, isSourceExhausted } = this.resolveAudioElementSourceWindow(\n state,\n segment,\n sourceOffsetMs,\n )\n if (isSourceExhausted) {\n this.pauseAudioElementState(state)\n voice.lastSourceSec = targetSourceSec\n voice.phase = 'ended'\n return\n }\n const needsSeek = targetSourceSec !== undefined\n && (voice.phase !== 'playing'\n || event.action === 'seek'\n || voice.lastSourceSec === undefined\n || Math.abs((voice.lastSourceSec ?? 0) - targetSourceSec) > 0.02)\n if (needsSeek) {\n const seekApplied = this.seekAudioElement(state, targetSourceSec, event.atTimelineMs)\n if (!seekApplied && targetSourceSec > 0.05) {\n this.pauseAudioElementState(state)\n voice.phase = 'idle'\n return\n }\n }\n\n if (typeof event.gain === 'number') {\n const normalizedGain = this.normalizeVolume(event.gain)\n if (voice.lastGain === undefined || Math.abs((voice.lastGain ?? 0) - normalizedGain) > 0.001)\n state.el.volume = normalizedGain\n this.plannedVideoAudioGains.set(key, normalizedGain)\n voice.lastGain = normalizedGain\n }\n if (typeof event.rate === 'number') {\n const normalizedRate = this.normalizePlayRate(event.rate)\n if (voice.lastRate === undefined || Math.abs((voice.lastRate ?? 0) - normalizedRate) > 0.001)\n state.el.playbackRate = normalizedRate\n this.plannedVideoAudioRates.set(key, normalizedRate)\n voice.lastRate = normalizedRate\n }\n if (targetSourceSec !== undefined)\n voice.lastSourceSec = targetSourceSec\n this.playAudioElementState(state)\n voice.phase = 'playing'\n }\n\n if (typeof event.gain === 'number') {\n const normalizedGain = this.normalizeVolume(event.gain)\n if (voice.lastGain === undefined || Math.abs((voice.lastGain ?? 0) - normalizedGain) > 0.001)\n this.plannedVideoAudioGains.set(key, normalizedGain)\n if (voice.lastGain === undefined || Math.abs((voice.lastGain ?? 0) - normalizedGain) > 0.001)\n state.el.volume = normalizedGain\n const gainNode = this.mp4Gains.get(key)\n if (gainNode)\n gainNode.gain.value = normalizedGain\n voice.lastGain = normalizedGain\n }\n\n if (typeof event.rate === 'number') {\n const normalizedRate = this.normalizePlayRate(event.rate)\n if (voice.lastRate === undefined || Math.abs((voice.lastRate ?? 0) - normalizedRate) > 0.001)\n this.plannedVideoAudioRates.set(key, normalizedRate)\n if (voice.lastRate === undefined || Math.abs((voice.lastRate ?? 0) - normalizedRate) > 0.001)\n state.el.playbackRate = normalizedRate\n voice.lastRate = normalizedRate\n }\n }\n\n private getOrCreatePlannedVoice(event: AudioPlanEvent): PlannedVoiceRuntime {\n const existing = this.plannedVoices.get(event.voiceId)\n if (existing)\n return existing\n const runtime: PlannedVoiceRuntime = {\n phase: 'idle',\n segmentKind: event.segmentKind,\n }\n this.plannedVoices.set(event.voiceId, runtime)\n return runtime\n }\n\n private playFrames(\n audio: Float32Array[],\n sampleRate: number,\n startAt: number,\n gainNode: GainNode,\n sources?: AudioBufferSourceNode[],\n playbackRate: number = 1,\n ) {\n const channels = Math.max(audio.length, 1)\n const len = audio[0]?.length ?? 0\n if (len === 0)\n return startAt\n const buffer = this.ctx.createBuffer(channels, len, sampleRate)\n for (let i = 0; i < channels; i++) {\n const data = audio[i] ?? new Float32Array(len)\n buffer.copyToChannel(new Float32Array(data), i)\n }\n const source = this.ctx.createBufferSource()\n source.buffer = buffer\n const safePlaybackRate = Math.max(0.1, playbackRate)\n source.playbackRate.value = safePlaybackRate\n source.connect(gainNode)\n const nextStart = Math.max(this.ctx.currentTime, startAt)\n source.start(nextStart)\n\n // Track the source so it can be stopped later\n if (sources) {\n sources.push(source)\n // Clean up finished sources after they complete\n const duration = (buffer.duration / safePlaybackRate) * 1000\n setTimeout(() => {\n const index = sources.indexOf(source)\n if (index > -1) {\n sources.splice(index, 1)\n }\n }, duration + 100)\n }\n\n return nextStart + (buffer.duration / safePlaybackRate)\n }\n\n private getOrCreateGain(map: Map<string, GainNode>, id: string, volume?: number) {\n const existing = map.get(id)\n if (existing) {\n if (typeof volume === 'number')\n existing.gain.value = this.normalizeVolume(volume)\n return existing\n }\n const gainNode = this.ctx.createGain()\n gainNode.gain.value = this.normalizeVolume(volume)\n gainNode.connect(this.ctx.destination)\n map.set(id, gainNode)\n return gainNode\n }\n\n private getOrCreateAudioElementState(key: string, segment: AudioElementSegment): AudioElementState {\n const nextUrl = this.options.resolveMediaElementUrl?.(segment) ?? segment.url\n const existing = this.audioElements.get(key)\n if (existing) {\n if (existing.url !== nextUrl) {\n existing.el.pause()\n existing.el.src = nextUrl\n existing.el.currentTime = 0\n existing.url = nextUrl\n existing.pendingPlay = undefined\n existing.lastTimelineMs = undefined\n existing.lastSourceSec = undefined\n existing.lastSeekTimelineMs = undefined\n }\n return existing\n }\n\n const el = new Audio(nextUrl)\n el.preload = 'auto'\n el.loop = false\n el.volume = this.normalizeVolume(segment.volume)\n el.playbackRate = this.normalizePlayRate(segment.playRate)\n const state: AudioElementState = {\n segmentId: segment.id,\n url: nextUrl,\n el,\n }\n this.audioElements.set(key, state)\n return state\n }\n\n private destroyAudioElement(el: HTMLAudioElement) {\n try {\n el.pause()\n }\n catch (e) {\n // Ignore media element pause failures.\n }\n el.removeAttribute('src')\n try {\n el.load()\n }\n catch (e) {\n // Ignore load failures during teardown.\n }\n }\n\n private playAudioElementState(state: AudioElementState) {\n if (!state.el.paused || state.pendingPlay)\n return\n const maybePromise = state.el.play()\n if (maybePromise && typeof maybePromise.then === 'function') {\n state.pendingPlay = maybePromise\n .catch(() => {})\n .finally(() => {\n state.pendingPlay = undefined\n })\n }\n }\n\n private pauseAudioElementState(state: AudioElementState) {\n try {\n state.el.pause()\n }\n catch (e) {\n // Ignore media element pause failures.\n }\n state.pendingPlay = undefined\n state.lastTimelineMs = undefined\n state.lastSourceSec = undefined\n state.lastSeekTimelineMs = undefined\n }\n\n private seekAudioElement(state: AudioElementState, targetSec: number, timelineMs: number): boolean {\n const normalizedTargetSec = Math.max(0, targetSec)\n if (Math.abs(state.el.currentTime - normalizedTargetSec) <= 0.02) {\n state.lastTimelineMs = timelineMs\n state.lastSourceSec = normalizedTargetSec\n return true\n }\n try {\n state.el.currentTime = normalizedTargetSec\n state.lastSeekTimelineMs = timelineMs\n state.lastTimelineMs = timelineMs\n state.lastSourceSec = normalizedTargetSec\n return true\n }\n catch (e) {\n // Metadata not ready or browser rejected out-of-range seek.\n return false\n }\n }\n\n private normalizePlayRate(playRate?: number): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return Math.max(0.1, Math.min(100, playRate))\n }\n\n private normalizeVolume(volume?: number): number {\n if (typeof volume !== 'number' || !Number.isFinite(volume))\n return 1\n return Math.max(0, Math.min(1, volume))\n }\n\n private computeSegmentSourceOffsetMs(\n segment: AudioElementSegment,\n timelineMs: number,\n sourceTimeMs?: number,\n ): number {\n if (typeof sourceTimeMs === 'number' && Number.isFinite(sourceTimeMs))\n return Math.max(0, sourceTimeMs)\n const relativeMs = Math.max(0, timelineMs - segment.startTime)\n const fromTimeMs = Math.max(0, segment.fromTime ?? 0)\n const playRate = this.normalizePlayRate(segment.playRate)\n return Math.max(0, fromTimeMs + relativeMs * playRate)\n }\n\n private resolveAudioElementSourceWindow(\n state: AudioElementState,\n segment: AudioElementSegment,\n sourceOffsetMs: number,\n ): { targetSourceSec: number, isSourceExhausted: boolean } {\n const playRate = this.normalizePlayRate(segment.playRate)\n const fromTimeMs = Math.max(0, segment.fromTime ?? 0)\n const segmentDurationMs = Math.max(0, segment.endTime - segment.startTime)\n const segmentSourceDurationMs = segmentDurationMs * playRate\n const segmentMaxSourceSec = Math.max(0, fromTimeMs + segmentSourceDurationMs) / 1000\n const mediaDurationSec = Number.isFinite(state.el.duration) ? Math.max(0, state.el.duration) : undefined\n const effectiveMaxSourceSec = mediaDurationSec === undefined\n ? segmentMaxSourceSec\n : Math.min(segmentMaxSourceSec, mediaDurationSec)\n const normalizedSourceSec = Math.max(0, sourceOffsetMs / 1000)\n const targetSourceSec = Math.max(0, Math.min(normalizedSourceSec, effectiveMaxSourceSec))\n const isSourceExhausted = normalizedSourceSec >= (effectiveMaxSourceSec - 0.01)\n return { targetSourceSec, isSourceExhausted }\n }\n\n private normalizeSampleRate(sampleRate: number): number {\n if (!Number.isFinite(sampleRate) || sampleRate <= 0)\n return 48000\n return Math.round(sampleRate)\n }\n\n private normalizePcmChannels(\n audio: Float32Array[] | Float32Array | undefined,\n ): Float32Array[] | undefined {\n if (!audio)\n return undefined\n if (audio instanceof Float32Array)\n return audio.length > 0 ? [audio] : undefined\n if (!Array.isArray(audio) || audio.length === 0)\n return undefined\n\n const channels: Float32Array[] = []\n for (const channel of audio) {\n if (!(channel instanceof Float32Array) || channel.length === 0)\n continue\n channels.push(channel)\n }\n if (channels.length === 0)\n return undefined\n return channels\n }\n\n private audioKey(id: string) {\n return `audio:${id}`\n }\n\n private videoKey(id: string) {\n return `video:${id}`\n }\n\n private findAudioSegment(id: string): IAudioSegment | undefined {\n for (const track of this.protocol.tracks) {\n for (const segment of track.children) {\n if (segment.id === id && segment.segmentType === 'audio')\n return segment as IAudioSegment\n }\n }\n return undefined\n }\n\n private findVideoSegment(id: string): IVideoFramesSegment | undefined {\n for (const track of this.protocol.tracks) {\n for (const segment of track.children) {\n if (segment.id === id && segment.segmentType === 'frames' && segment.type === 'video')\n return segment as IVideoFramesSegment\n }\n }\n return undefined\n }\n\n private getSegmentVolume(id: string): number {\n for (const track of this.protocol.tracks) {\n for (const segment of track.children) {\n if (segment.id !== id)\n continue\n const volume = (segment as { volume?: number }).volume\n return this.normalizeVolume(volume)\n }\n }\n return 1\n }\n}\n","import type { IFillMode, SegmentUnion } from '@video-editor/shared'\n\nexport interface SegmentLayout {\n width: number\n height: number\n centerX: number\n centerY: number\n rotationRad: number\n}\n\nexport function resolveFillSize(\n mode: IFillMode | undefined,\n sourceWidth: number,\n sourceHeight: number,\n stageWidth: number,\n stageHeight: number,\n) {\n const safeSourceWidth = sourceWidth || stageWidth\n const safeSourceHeight = sourceHeight || stageHeight\n if (!safeSourceWidth || !safeSourceHeight)\n return { width: stageWidth, height: stageHeight }\n\n const sourceRatio = safeSourceWidth / safeSourceHeight\n const stageRatio = stageWidth / stageHeight\n\n switch (mode) {\n case 'none':\n return { width: safeSourceWidth, height: safeSourceHeight }\n case 'cover':\n if (sourceRatio > stageRatio)\n return { width: stageHeight * sourceRatio, height: stageHeight }\n return { width: stageWidth, height: stageWidth / sourceRatio }\n case 'stretch':\n return { width: stageWidth, height: stageHeight }\n case 'contain':\n default:\n if (sourceRatio > stageRatio)\n return { width: stageWidth, height: stageWidth / sourceRatio }\n return { width: stageHeight * sourceRatio, height: stageHeight }\n }\n}\n\nexport function computeSegmentLayout(\n segment: SegmentUnion,\n stageWidth: number,\n stageHeight: number,\n sourceWidth: number,\n sourceHeight: number,\n): SegmentLayout {\n const fillMode = 'fillMode' in segment ? segment.fillMode : undefined\n const { width, height } = resolveFillSize(\n fillMode,\n sourceWidth,\n sourceHeight,\n stageWidth,\n stageHeight,\n )\n\n const transform = 'transform' in segment ? segment.transform : undefined\n const [px, py] = transform?.position ?? [0, 0]\n const [sx, sy] = transform?.scale ?? [1, 1]\n const rotation = transform?.rotation?.[2] ?? 0\n\n const finalWidth = width * sx\n const finalHeight = height * sy\n const centerX = stageWidth / 2 + (px * stageWidth) / 2\n const centerY = stageHeight / 2 - (py * stageHeight) / 2\n\n return {\n width: finalWidth,\n height: finalHeight,\n centerX,\n centerY,\n rotationRad: (rotation / 180) * Math.PI,\n }\n}\n","import type { IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { PixiDisplayObject } from './types'\nimport { toRaw } from '@vue/reactivity'\nimport { Graphics, Sprite, Texture } from 'pixi.js'\nimport { computeSegmentLayout } from './layout'\n\nexport function collectResourceUrls(protocol: IVideoProtocol) {\n const urls = new Set<string>()\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (segment.url)\n urls.add(segment.url)\n }\n }\n return urls\n}\n\nexport interface ApplyDisplayPropsOptions {\n opacity?: number\n}\n\nexport function applyDisplayProps(\n display: PixiDisplayObject,\n segment: SegmentUnion,\n width: number,\n height: number,\n options: ApplyDisplayPropsOptions = {},\n) {\n const opacity = normalizeOpacity(options.opacity ?? readOpacity(segment))\n const sourceWidth = display instanceof Sprite ? display.texture.width || width : width\n const sourceHeight = display instanceof Sprite ? display.texture.height || height : height\n const layout = computeSegmentLayout(segment, width, height, sourceWidth, sourceHeight)\n\n if (display instanceof Sprite) {\n display.anchor.set(0.5)\n display.width = layout.width\n display.height = layout.height\n display.position.set(layout.centerX, layout.centerY)\n display.rotation = layout.rotationRad\n const src = display.texture.source as { addEventListener?: (type: string, cb: () => void, opts?: AddEventListenerOptions) => void } | undefined\n src?.addEventListener?.('error', () => {\n // fallback to a colored rect if texture failed\n display.texture = Texture.from(placeholderTexture(width, height))\n }, { once: true })\n }\n else if (display instanceof Graphics) {\n display.clear()\n display\n .rect(0, 0, layout.width, layout.height)\n .fill({ color: stringToColor('url' in segment && typeof segment.url === 'string' ? segment.url : segment.segmentType), alpha: hasOpacity(segment) ? opacity : 0.35 })\n display.pivot.set(layout.width / 2, layout.height / 2)\n display.position.set(layout.centerX, layout.centerY)\n display.rotation = layout.rotationRad\n }\n\n display.alpha = opacity\n}\n\nexport function placeholder(key: string, url?: string) {\n const g = new Graphics()\n g.rect(0, 0, 10, 10).fill({ color: stringToColor(url ?? key), alpha: 1 })\n return g\n}\n\nexport function placeholderTexture(width: number, height: number, color?: string) {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"><rect width=\"100%\" height=\"100%\" fill=\"${color ?? '#0f172a'}\" fill-opacity=\"0.8\"/></svg>`\n return `data:image/svg+xml;base64,${btoa(svg)}`\n}\n\nexport function stringToColor(key: string) {\n let hash = 0\n for (let i = 0; i < key.length; i++)\n hash = key.charCodeAt(i) + ((hash << 5) - hash)\n return hash & 0x00FFFFFF\n}\n\nexport function computeDuration(protocol: IVideoProtocol) {\n const endTimes = protocol.tracks.flatMap(track => track.children.map(seg => seg.endTime))\n return endTimes.length ? Math.max(...endTimes) : 0\n}\n\nexport function clamp(num: number, min: number, max: number) {\n return Math.min(Math.max(num, min), max)\n}\n\nexport function cloneProtocol(protocol: IVideoProtocol) {\n const raw = toRaw(protocol) as IVideoProtocol\n // use JSON clone to avoid structuredClone errors on proxies (e.g., Vue reactive)\n return JSON.parse(JSON.stringify(raw)) as IVideoProtocol\n}\n\nfunction hasOpacity(segment: SegmentUnion): segment is SegmentUnion & { opacity?: number } {\n return 'opacity' in segment\n}\n\nfunction readOpacity(segment: SegmentUnion) {\n if (hasOpacity(segment) && typeof segment.opacity === 'number')\n return segment.opacity\n return 1\n}\n\nfunction normalizeOpacity(opacity: number) {\n if (!Number.isFinite(opacity))\n return 1\n return Math.min(Math.max(opacity, 0), 1)\n}\n","import type { TransportSnapshot } from './types'\n\nexport interface CreateTimelineTransportOptions {\n now?: () => number\n initialTimelineMs?: number\n initialRate?: number\n playing?: boolean\n}\n\nexport interface TimelineTransport {\n getSnapshot: (nowMs?: number) => TransportSnapshot\n play: (nowMs?: number) => TransportSnapshot\n pause: (nowMs?: number) => TransportSnapshot\n seek: (timelineMs: number, nowMs?: number) => TransportSnapshot\n setRate: (rate: number, nowMs?: number) => TransportSnapshot\n subscribe: (listener: (snapshot: TransportSnapshot) => void) => () => void\n}\n\nconst MIN_PLAY_RATE = 0.1\nconst MAX_PLAY_RATE = 100\n\nexport function createTimelineTransport(\n opts: CreateTimelineTransportOptions = {},\n): TimelineTransport {\n const nowProvider = opts.now ?? defaultNow\n let playing = Boolean(opts.playing)\n let rate = normalizeRate(opts.initialRate)\n let discontinuitySeq = 0\n let epochWallMs = resolveNow(undefined, nowProvider)\n let epochTimelineMs = normalizeTimelineMs(opts.initialTimelineMs)\n\n const listeners = new Set<(snapshot: TransportSnapshot) => void>()\n\n if (playing)\n epochWallMs = resolveNow(undefined, nowProvider)\n\n const currentTimelineMs = (nowMs: number) =>\n playing ? epochTimelineMs + (nowMs - epochWallMs) * rate : epochTimelineMs\n\n const snapshotAt = (nowMs: number): TransportSnapshot => ({\n playing,\n timelineMs: normalizeTimelineMs(currentTimelineMs(nowMs)),\n rate,\n epochWallMs,\n epochTimelineMs,\n discontinuitySeq,\n })\n\n const emit = (snapshot: TransportSnapshot) => {\n for (const listener of listeners)\n listener(snapshot)\n }\n\n const anchorAt = (timelineMs: number, nowMs: number) => {\n epochTimelineMs = normalizeTimelineMs(timelineMs)\n epochWallMs = nowMs\n }\n\n return {\n getSnapshot(nowMs) {\n return snapshotAt(resolveNow(nowMs, nowProvider))\n },\n\n play(nowMs) {\n const resolvedNow = resolveNow(nowMs, nowProvider)\n if (!playing) {\n const timelineMs = currentTimelineMs(resolvedNow)\n playing = true\n anchorAt(timelineMs, resolvedNow)\n }\n const snapshot = snapshotAt(resolvedNow)\n emit(snapshot)\n return snapshot\n },\n\n pause(nowMs) {\n const resolvedNow = resolveNow(nowMs, nowProvider)\n if (playing) {\n const timelineMs = currentTimelineMs(resolvedNow)\n playing = false\n anchorAt(timelineMs, resolvedNow)\n }\n const snapshot = snapshotAt(resolvedNow)\n emit(snapshot)\n return snapshot\n },\n\n seek(timelineMs, nowMs) {\n const resolvedNow = resolveNow(nowMs, nowProvider)\n anchorAt(timelineMs, resolvedNow)\n discontinuitySeq += 1\n const snapshot = snapshotAt(resolvedNow)\n emit(snapshot)\n return snapshot\n },\n\n setRate(nextRate, nowMs) {\n const resolvedNow = resolveNow(nowMs, nowProvider)\n const normalizedNextRate = normalizeRate(nextRate)\n const timelineMs = currentTimelineMs(resolvedNow)\n anchorAt(timelineMs, resolvedNow)\n if (Math.abs(rate - normalizedNextRate) > 0.0001) {\n rate = normalizedNextRate\n discontinuitySeq += 1\n }\n const snapshot = snapshotAt(resolvedNow)\n emit(snapshot)\n return snapshot\n },\n\n subscribe(listener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n }\n}\n\nfunction resolveNow(nowMs: number | undefined, nowProvider: () => number): number {\n if (typeof nowMs === 'number' && Number.isFinite(nowMs))\n return nowMs\n return nowProvider()\n}\n\nfunction normalizeTimelineMs(timelineMs: number | undefined): number {\n if (typeof timelineMs !== 'number' || !Number.isFinite(timelineMs))\n return 0\n return Math.max(0, timelineMs)\n}\n\nfunction normalizeRate(rate: number | undefined): number {\n if (typeof rate !== 'number' || !Number.isFinite(rate))\n return 1\n return Math.min(MAX_PLAY_RATE, Math.max(MIN_PLAY_RATE, rate))\n}\n\nfunction defaultNow() {\n if (typeof globalThis.performance !== 'undefined' && typeof globalThis.performance.now === 'function')\n return globalThis.performance.now()\n return Date.now()\n}\n","import type {\n ITransitionEdge,\n IVideoProtocol,\n} from '@video-editor/shared'\n\nexport interface ResolvedTransitionEdge {\n id: string\n name: string\n duration: number\n fromSegmentId: string\n toSegmentId: string\n}\n\nexport function collectTransitionByFromSegmentId(protocol: IVideoProtocol): Map<string, ResolvedTransitionEdge> {\n const transitionByFromSegmentId = new Map<string, ResolvedTransitionEdge>()\n const adjacentToByFrom = collectAdjacentFramePairs(protocol)\n\n for (const transition of protocol.transitions ?? []) {\n if (!isValidTransitionEdge(transition))\n continue\n const adjacentTo = adjacentToByFrom.get(transition.fromSegmentId)\n if (adjacentTo !== transition.toSegmentId)\n continue\n transitionByFromSegmentId.set(transition.fromSegmentId, {\n id: transition.id,\n name: transition.name,\n duration: transition.duration,\n fromSegmentId: transition.fromSegmentId,\n toSegmentId: transition.toSegmentId,\n })\n }\n\n return transitionByFromSegmentId\n}\n\nfunction isValidTransition(transition: ITransitionEdge | null | undefined): transition is ITransitionEdge {\n if (!transition || typeof transition !== 'object')\n return false\n if (typeof transition.id !== 'string' || typeof transition.name !== 'string')\n return false\n return Number.isFinite(transition.duration) && transition.duration > 0\n}\n\nfunction isValidTransitionEdge(edge: ITransitionEdge | null | undefined): edge is ITransitionEdge {\n if (!edge || typeof edge !== 'object')\n return false\n if (typeof edge.fromSegmentId !== 'string' || typeof edge.toSegmentId !== 'string')\n return false\n return isValidTransition(edge)\n}\n\nfunction collectAdjacentFramePairs(protocol: IVideoProtocol): Map<string, string> {\n const adjacentToByFrom = new Map<string, string>()\n for (const track of protocol.tracks) {\n if (track.trackType !== 'frames')\n continue\n const children = track.children\n for (let i = 0; i < children.length - 1; i++) {\n const fromSegment = children[i]\n const toSegment = children[i + 1]\n if (!fromSegment || !toSegment)\n continue\n adjacentToByFrom.set(fromSegment.id, toSegment.id)\n }\n }\n return adjacentToByFrom\n}\n","import type {\n IAudioSegment,\n IVideoProtocol,\n SegmentUnion,\n TrackUnion,\n} from '@video-editor/shared'\nimport type {\n ActiveVoiceRef,\n AudioPlanEvent,\n EvalContext,\n EvaluatorOutput,\n EvaluatorState,\n VisualEffectParam,\n VisualPlanItem,\n} from './types'\nimport { isAudioSegment, isVideoFramesSegment } from '@video-editor/shared'\nimport { collectTransitionByFromSegmentId } from './transition-resolver'\nimport type { ResolvedTransitionEdge } from './transition-resolver'\n\ninterface ActiveVoiceMeta extends ActiveVoiceRef {\n sourceTimeMs: number\n gain: number\n rate: number\n}\n\nexport function createEmptyEvaluatorState(): EvaluatorState {\n return {\n activeVoices: [],\n }\n}\n\nexport function evaluateTimelinePlan(\n protocol: IVideoProtocol,\n context: EvalContext,\n previousState: EvaluatorState = createEmptyEvaluatorState(),\n): EvaluatorOutput {\n const atMs = normalizeTimeMs(context.atMs)\n const windowStartMs = normalizeTimeMs(context.windowStartMs)\n const windowEndMs = Math.max(windowStartMs, normalizeTimeMs(context.windowEndMs))\n\n const visuals: VisualPlanItem[] = []\n const activeVoiceById = new Map<string, ActiveVoiceMeta>()\n const activeEffects = collectActiveEffects(protocol, atMs)\n const transitionByFromSegmentId = collectTransitionByFromSegmentId(protocol)\n\n for (let trackIndex = 0; trackIndex < protocol.tracks.length; trackIndex++) {\n const track = protocol.tracks[trackIndex]!\n const trackOrder = getTrackOrder(protocol.tracks.length, trackIndex, track)\n\n for (let childIndex = 0; childIndex < track.children.length; childIndex++) {\n const segment = track.children[childIndex]!\n if (!isActiveAt(segment, atMs))\n continue\n\n if (segment.segmentType === 'effect' || segment.segmentType === 'filter')\n continue\n\n if (segment.segmentType !== 'audio') {\n visuals.push(buildVisualPlanItem({\n segment,\n track,\n trackOrder,\n childIndex,\n atMs,\n transition: transitionByFromSegmentId.get(segment.id),\n effects: activeEffects,\n }))\n }\n\n const voice = toActiveVoiceMeta(segment, track, atMs)\n if (voice)\n activeVoiceById.set(voice.voiceId, voice)\n }\n }\n\n visuals.sort((a, b) => {\n if (a.zOrder !== b.zOrder)\n return a.zOrder - b.zOrder\n return a.segmentId.localeCompare(b.segmentId)\n })\n\n const previousVoiceById = new Map<string, ActiveVoiceRef>()\n for (const previousVoice of previousState.activeVoices)\n previousVoiceById.set(previousVoice.voiceId, previousVoice)\n\n const audioEvents: AudioPlanEvent[] = []\n for (const [voiceId, previousVoice] of previousVoiceById) {\n if (activeVoiceById.has(voiceId))\n continue\n audioEvents.push({\n voiceId,\n segmentId: previousVoice.segmentId,\n trackId: previousVoice.trackId,\n segmentKind: previousVoice.segmentKind,\n action: 'stop',\n atTimelineMs: atMs,\n })\n }\n\n const activeVoices: ActiveVoiceRef[] = []\n for (const voice of activeVoiceById.values()) {\n activeVoices.push({\n voiceId: voice.voiceId,\n segmentId: voice.segmentId,\n trackId: voice.trackId,\n segmentKind: voice.segmentKind,\n })\n if (!previousVoiceById.has(voice.voiceId)) {\n audioEvents.push({\n voiceId: voice.voiceId,\n segmentId: voice.segmentId,\n trackId: voice.trackId,\n segmentKind: voice.segmentKind,\n action: 'start',\n atTimelineMs: atMs,\n sourceTimeMs: voice.sourceTimeMs,\n gain: voice.gain,\n rate: voice.rate,\n })\n }\n else if (context.discontinuity) {\n audioEvents.push({\n voiceId: voice.voiceId,\n segmentId: voice.segmentId,\n trackId: voice.trackId,\n segmentKind: voice.segmentKind,\n action: 'seek',\n atTimelineMs: atMs,\n sourceTimeMs: voice.sourceTimeMs,\n })\n }\n audioEvents.push({\n voiceId: voice.voiceId,\n segmentId: voice.segmentId,\n trackId: voice.trackId,\n segmentKind: voice.segmentKind,\n action: 'gain',\n atTimelineMs: atMs,\n gain: voice.gain,\n })\n audioEvents.push({\n voiceId: voice.voiceId,\n segmentId: voice.segmentId,\n trackId: voice.trackId,\n segmentKind: voice.segmentKind,\n action: 'rate',\n atTimelineMs: atMs,\n rate: voice.rate,\n })\n }\n\n return {\n plan: {\n atMs,\n windowStartMs,\n windowEndMs,\n visuals,\n audioEvents,\n },\n state: {\n activeVoices,\n },\n }\n}\n\nfunction buildVisualPlanItem(input: {\n segment: SegmentUnion\n track: TrackUnion\n trackOrder: number\n childIndex: number\n atMs: number\n transition: ResolvedTransitionEdge | undefined\n effects: VisualEffectParam[]\n}): VisualPlanItem {\n const {\n segment,\n track,\n trackOrder,\n childIndex,\n atMs,\n transition,\n effects,\n } = input\n return {\n segmentId: segment.id,\n trackId: track.trackId,\n trackType: track.trackType,\n segmentType: segment.segmentType,\n zOrder: trackOrder * 10000 + childIndex,\n sourceTimeMs: mapSourceTimeMs(segment, atMs),\n opacity: readOpacity(segment),\n transition: computeTransition(segment, transition, atMs),\n effects: effects.length ? effects : undefined,\n }\n}\n\nfunction toActiveVoiceMeta(segment: SegmentUnion, track: TrackUnion, atMs: number): ActiveVoiceMeta | undefined {\n if (isAudioSegment(segment)) {\n const relativeMs = Math.max(0, atMs - segment.startTime)\n return {\n voiceId: `audio:${segment.id}`,\n segmentId: segment.id,\n trackId: track.trackId,\n segmentKind: 'audio',\n sourceTimeMs: mapRemappableSourceTimeMs(segment, atMs),\n gain: computeAudioSegmentGain(segment, relativeMs),\n rate: normalizePlayRate(segment.playRate),\n }\n }\n\n if (isVideoFramesSegment(segment)) {\n const gain = normalizeVolume(segment.volume)\n if (gain <= 0)\n return undefined\n return {\n voiceId: `video:${segment.id}`,\n segmentId: segment.id,\n trackId: track.trackId,\n segmentKind: 'video',\n sourceTimeMs: mapRemappableSourceTimeMs(segment, atMs),\n gain,\n rate: normalizePlayRate(segment.playRate),\n }\n }\n\n return undefined\n}\n\nfunction mapSourceTimeMs(segment: SegmentUnion, atMs: number): number {\n if (isAudioSegment(segment) || isVideoFramesSegment(segment))\n return mapRemappableSourceTimeMs(segment, atMs)\n return Math.max(0, atMs - segment.startTime)\n}\n\nfunction mapRemappableSourceTimeMs(\n segment: { startTime: number, fromTime?: number, playRate?: number },\n atMs: number,\n): number {\n const relativeMs = Math.max(0, atMs - segment.startTime)\n const fromTime = normalizeTimeMs(segment.fromTime ?? 0)\n const playRate = normalizePlayRate(segment.playRate)\n return Math.max(0, fromTime + relativeMs * playRate)\n}\n\nfunction computeTransition(\n segment: SegmentUnion,\n transition: ResolvedTransitionEdge | undefined,\n atMs: number,\n): VisualPlanItem['transition'] {\n if (segment.segmentType !== 'frames')\n return undefined\n if (!transition)\n return undefined\n if (transition.fromSegmentId !== segment.id)\n return undefined\n const startMs = segment.endTime - transition.duration\n if (atMs < startMs || atMs >= segment.endTime)\n return undefined\n const progress = (atMs - startMs) / transition.duration\n return {\n fromSegmentId: segment.id,\n toSegmentId: transition.toSegmentId,\n progress: clamp(progress, 0, 1),\n transitionId: transition.id,\n transitionName: transition.name,\n durationMs: transition.duration,\n }\n}\n\nfunction isActiveAt(segment: SegmentUnion, atMs: number): boolean {\n return segment.startTime <= atMs && atMs < segment.endTime\n}\n\nfunction readOpacity(segment: SegmentUnion): number {\n if ('opacity' in segment && typeof segment.opacity === 'number' && Number.isFinite(segment.opacity))\n return clamp(segment.opacity, 0, 1)\n return 1\n}\n\nfunction computeAudioSegmentGain(segment: IAudioSegment, relativeMs: number): number {\n const baseVolume = normalizeVolume(segment.volume)\n const segmentDurationMs = Math.max(0, segment.endTime - segment.startTime)\n const fadeInDurationMs = Math.max(0, segment.fadeInDuration ?? 0)\n const fadeOutDurationMs = Math.max(0, segment.fadeOutDuration ?? 0)\n\n let envelope = 1\n if (fadeInDurationMs > 0 && relativeMs < fadeInDurationMs)\n envelope = Math.max(0, relativeMs / fadeInDurationMs)\n\n const timeUntilEnd = segmentDurationMs - relativeMs\n if (fadeOutDurationMs > 0 && timeUntilEnd < fadeOutDurationMs)\n envelope = Math.min(envelope, Math.max(0, timeUntilEnd / fadeOutDurationMs))\n\n return baseVolume * envelope\n}\n\nfunction getTrackOrder(trackCount: number, trackIndex: number, track: TrackUnion): number {\n if (track.trackType === 'frames' && 'isMain' in track && Boolean(track.isMain))\n return 0\n return trackCount - trackIndex\n}\n\nfunction collectActiveEffects(protocol: IVideoProtocol, atMs: number): VisualEffectParam[] {\n const effects: VisualEffectParam[] = []\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (!isActiveAt(segment, atMs))\n continue\n if (segment.segmentType === 'effect') {\n effects.push({\n segmentType: 'effect',\n segmentId: segment.id,\n effectId: segment.effectId,\n name: segment.name,\n })\n }\n else if (segment.segmentType === 'filter') {\n effects.push({\n segmentType: 'filter',\n segmentId: segment.id,\n filterId: segment.filterId,\n name: segment.name,\n intensity: normalizeVolume(segment.intensity),\n })\n }\n }\n }\n return effects\n}\n\nfunction normalizeTimeMs(value: number): number {\n if (!Number.isFinite(value))\n return 0\n return Math.max(0, value)\n}\n\nfunction normalizeVolume(volume: number | undefined): number {\n if (typeof volume !== 'number' || !Number.isFinite(volume))\n return 1\n return clamp(volume, 0, 1)\n}\n\nfunction normalizePlayRate(playRate: number | undefined): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return clamp(playRate, 0.1, 100)\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { EvalContext, EvaluatorState, TimelinePlan } from './types'\nimport { createEmptyEvaluatorState, evaluateTimelinePlan } from './evaluator'\n\nexport interface StatefulTimelineEvaluator {\n evaluate: (protocol: IVideoProtocol, context: EvalContext) => TimelinePlan\n reset: () => void\n getState: () => EvaluatorState\n}\n\nexport function createStatefulTimelineEvaluator(): StatefulTimelineEvaluator {\n let state = createEmptyEvaluatorState()\n\n return {\n evaluate(protocol, context) {\n const output = evaluateTimelinePlan(protocol, context, state)\n state = output.state\n return output.plan\n },\n reset() {\n state = createEmptyEvaluatorState()\n },\n getState() {\n return state\n },\n }\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { TimelineTransport } from './transport'\nimport type { EvaluatorState, TimelinePlan } from './types'\nimport { createStatefulTimelineEvaluator } from './stateful-evaluator'\n\nconst DEFAULT_LOOKBACK_MS = 20\nconst DEFAULT_LOOKAHEAD_MS = 100\n\nexport interface CreatePreviewRunnerOptions {\n transport: TimelineTransport\n lookbackMs?: number\n lookaheadMs?: number\n}\n\nexport interface PreviewRunner {\n evaluate: (protocol: IVideoProtocol, atMs?: number) => TimelinePlan\n reset: () => void\n getState: () => EvaluatorState\n}\n\nexport function createPreviewRunner(opts: CreatePreviewRunnerOptions): PreviewRunner {\n const lookbackMs = normalizeWindowMs(opts.lookbackMs, DEFAULT_LOOKBACK_MS)\n const lookaheadMs = normalizeWindowMs(opts.lookaheadMs, DEFAULT_LOOKAHEAD_MS)\n const evaluator = createStatefulTimelineEvaluator()\n let lastDiscontinuitySeq = opts.transport.getSnapshot().discontinuitySeq\n\n return {\n evaluate(protocol, atMs) {\n const snapshot = opts.transport.getSnapshot()\n const timelineMs = normalizeTimelineMs(typeof atMs === 'number' ? atMs : snapshot.timelineMs)\n const discontinuity = snapshot.discontinuitySeq !== lastDiscontinuitySeq\n if (discontinuity)\n lastDiscontinuitySeq = snapshot.discontinuitySeq\n\n return evaluator.evaluate(protocol, {\n atMs: timelineMs,\n windowStartMs: Math.max(0, timelineMs - lookbackMs),\n windowEndMs: timelineMs + lookaheadMs,\n fps: Math.max(protocol.fps || 30, 1),\n discontinuity,\n })\n },\n\n reset() {\n evaluator.reset()\n lastDiscontinuitySeq = opts.transport.getSnapshot().discontinuitySeq\n },\n\n getState() {\n return evaluator.getState()\n },\n }\n}\n\nfunction normalizeWindowMs(windowMs: number | undefined, fallback: number): number {\n if (typeof windowMs !== 'number' || !Number.isFinite(windowMs))\n return fallback\n return Math.max(0, windowMs)\n}\n\nfunction normalizeTimelineMs(timelineMs: number): number {\n if (!Number.isFinite(timelineMs))\n return 0\n return Math.max(0, timelineMs)\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { EvalContext, EvaluatorState, TimelinePlan } from './types'\nimport { createStatefulTimelineEvaluator } from './stateful-evaluator'\n\nexport interface ComposeRunnerEvaluateOptions {\n windowStartMs?: number\n windowEndMs?: number\n discontinuity?: boolean\n}\n\nexport interface ComposeRunner {\n evaluateAt: (\n protocol: IVideoProtocol,\n atMs: number,\n options?: ComposeRunnerEvaluateOptions,\n ) => TimelinePlan\n evaluateSequence: (protocol: IVideoProtocol, atMsList: number[]) => TimelinePlan[]\n reset: () => void\n getState: () => EvaluatorState\n}\n\nexport function createComposeRunner(): ComposeRunner {\n const evaluator = createStatefulTimelineEvaluator()\n let lastAtMs: number | undefined\n\n return {\n evaluateAt(protocol, atMs, options = {}) {\n const normalizedAtMs = normalizeTimelineMs(atMs)\n const windowStartMs = normalizeTimelineMs(options.windowStartMs ?? normalizedAtMs)\n const windowEndMs = Math.max(\n windowStartMs,\n normalizeTimelineMs(options.windowEndMs ?? normalizedAtMs),\n )\n\n const context: EvalContext = {\n atMs: normalizedAtMs,\n windowStartMs,\n windowEndMs,\n fps: Math.max(protocol.fps || 30, 1),\n discontinuity:\n typeof options.discontinuity === 'boolean'\n ? options.discontinuity\n : (lastAtMs !== undefined && normalizedAtMs < lastAtMs),\n }\n\n lastAtMs = normalizedAtMs\n return evaluator.evaluate(protocol, context)\n },\n\n evaluateSequence(protocol, atMsList) {\n const plans: TimelinePlan[] = []\n for (const atMs of atMsList)\n plans.push(this.evaluateAt(protocol, atMs))\n return plans\n },\n\n reset() {\n evaluator.reset()\n lastAtMs = undefined\n },\n\n getState() {\n return evaluator.getState()\n },\n }\n}\n\nfunction normalizeTimelineMs(timelineMs: number | undefined): number {\n if (typeof timelineMs !== 'number' || !Number.isFinite(timelineMs))\n return 0\n return Math.max(0, timelineMs)\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { PreviewRunner } from './preview-runner'\nimport type { TimelineTransport } from './transport'\nimport type { TimelinePlan, TransportSnapshot } from './types'\n\nconst DEFAULT_TICK_INTERVAL_MS = 20\n\ntype IntervalHandle = ReturnType<typeof setInterval>\n\nexport interface CreatePreviewAudioTickerOptions {\n transport: TimelineTransport\n runner: PreviewRunner\n getProtocol: () => IVideoProtocol\n onPlan: (plan: TimelinePlan, snapshot: TransportSnapshot) => void\n intervalMs?: number\n setInterval?: (callback: () => void, intervalMs: number) => IntervalHandle\n clearInterval?: (handle: IntervalHandle) => void\n}\n\nexport interface PreviewAudioTicker {\n start: () => void\n stop: () => void\n tick: () => TimelinePlan\n isRunning: () => boolean\n}\n\nexport function createPreviewAudioTicker(opts: CreatePreviewAudioTickerOptions): PreviewAudioTicker {\n const intervalMs = normalizeIntervalMs(opts.intervalMs, DEFAULT_TICK_INTERVAL_MS)\n const setIntervalFn = opts.setInterval ?? ((callback: () => void, tickIntervalMs: number) => {\n return globalThis.setInterval(callback, tickIntervalMs) as IntervalHandle\n })\n const clearIntervalFn = opts.clearInterval ?? ((handle: IntervalHandle) => {\n globalThis.clearInterval(handle)\n })\n let timer: IntervalHandle | undefined\n\n const tick = () => {\n const snapshot = opts.transport.getSnapshot()\n const plan = opts.runner.evaluate(opts.getProtocol(), snapshot.timelineMs)\n opts.onPlan(plan, snapshot)\n return plan\n }\n\n return {\n start() {\n if (timer !== undefined)\n return\n tick()\n timer = setIntervalFn(() => {\n tick()\n }, intervalMs)\n },\n\n stop() {\n if (timer === undefined)\n return\n clearIntervalFn(timer)\n timer = undefined\n },\n\n tick,\n\n isRunning() {\n return timer !== undefined\n },\n }\n}\n\nfunction normalizeIntervalMs(intervalMs: number | undefined, fallback: number): number {\n if (typeof intervalMs !== 'number' || !Number.isFinite(intervalMs))\n return fallback\n return Math.max(1, intervalMs)\n}\n","import type { SegmentUnion, IVideoProtocol } from '@video-editor/shared'\nimport type { VisualEffectParam, VisualPlanItem } from './types'\nimport { isVideoFramesSegment } from '@video-editor/shared'\n\nexport interface VisualRenderItem {\n segment: SegmentUnion\n sourceTimeMs: number\n opacity: number\n includeAudio: boolean\n effects?: VisualEffectParam[]\n}\n\nexport function createVisualRenderItems(\n protocol: IVideoProtocol,\n visuals: VisualPlanItem[],\n): VisualRenderItem[] {\n const segmentById = indexSegments(protocol)\n const activeSegmentIds = new Set<string>()\n for (const visual of visuals)\n activeSegmentIds.add(visual.segmentId)\n\n const items: VisualRenderItem[] = []\n for (const visual of visuals) {\n const segment = segmentById.get(visual.segmentId)\n if (!segment)\n continue\n\n const progress = clamp01(visual.transition?.progress ?? 0)\n const fromOpacity = clamp01(visual.opacity) * (visual.transition ? (1 - progress) : 1)\n\n items.push({\n segment,\n sourceTimeMs: Math.max(0, visual.sourceTimeMs),\n opacity: fromOpacity,\n includeAudio: true,\n effects: visual.effects,\n })\n\n if (!visual.transition || progress <= 0)\n continue\n if (activeSegmentIds.has(visual.transition.toSegmentId))\n continue\n\n const targetSegment = segmentById.get(visual.transition.toSegmentId)\n if (!targetSegment)\n continue\n\n const transitionDurationMs = normalizeTimeMs(visual.transition.durationMs)\n if (transitionDurationMs <= 0)\n continue\n const elapsedTransitionMs = transitionDurationMs * progress\n const targetSourceTimeMs = mapTransitionTargetSourceTimeMs(targetSegment, elapsedTransitionMs)\n const targetOpacity = readSegmentOpacity(targetSegment) * progress\n\n items.push({\n segment: targetSegment,\n sourceTimeMs: targetSourceTimeMs,\n opacity: targetOpacity,\n includeAudio: false,\n effects: visual.effects,\n })\n }\n\n return items\n}\n\nfunction indexSegments(protocol: IVideoProtocol): Map<string, SegmentUnion> {\n const segmentById = new Map<string, SegmentUnion>()\n for (const track of protocol.tracks) {\n for (const segment of track.children)\n segmentById.set(segment.id, segment)\n }\n return segmentById\n}\n\nfunction mapTransitionTargetSourceTimeMs(segment: SegmentUnion, elapsedTransitionMs: number): number {\n if (isVideoFramesSegment(segment)) {\n const fromTime = normalizeTimeMs(segment.fromTime)\n const playRate = normalizePlayRate(segment.playRate)\n return Math.max(0, fromTime + elapsedTransitionMs * playRate)\n }\n return Math.max(0, elapsedTransitionMs)\n}\n\nfunction readSegmentOpacity(segment: SegmentUnion): number {\n if ('opacity' in segment && typeof segment.opacity === 'number' && Number.isFinite(segment.opacity))\n return clamp01(segment.opacity)\n return 1\n}\n\nfunction normalizeTimeMs(value: number | undefined): number {\n if (typeof value !== 'number' || !Number.isFinite(value))\n return 0\n return Math.max(0, value)\n}\n\nfunction normalizePlayRate(playRate: number | undefined): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return Math.min(Math.max(playRate, 0.1), 100)\n}\n\nfunction clamp01(value: number): number {\n if (!Number.isFinite(value))\n return 0\n return Math.min(Math.max(value, 0), 1)\n}\n","import type { Filter } from 'pixi.js'\nimport type { VisualEffectParam } from './types'\nimport { BlurFilter, ColorMatrixFilter } from 'pixi.js'\n\nexport function createPixiFiltersFromVisualEffects(effects: VisualEffectParam[] | undefined): Filter[] {\n if (!effects?.length)\n return []\n\n const filters: Filter[] = []\n for (const effect of effects) {\n const filter = effect.segmentType === 'filter'\n ? buildFilterTrackEffect(effect)\n : buildNamedEffect(effect)\n if (filter)\n filters.push(filter)\n }\n return filters\n}\n\nfunction buildFilterTrackEffect(effect: Extract<VisualEffectParam, { segmentType: 'filter' }>): Filter | undefined {\n const token = normalizeToken(effect.name, effect.filterId)\n const intensity = normalizeIntensity(effect.intensity)\n\n if (looksLikeBlur(token))\n return new BlurFilter({ strength: 1 + intensity * 14, quality: 2, kernelSize: 5 })\n\n const matrix = new ColorMatrixFilter()\n if (looksLikeGray(token))\n matrix.grayscale(intensity, false)\n else if (token.includes('sepia') || token.includes('warm'))\n matrix.sepia(false)\n else if (token.includes('negative') || token.includes('invert'))\n matrix.negative(false)\n else if (token.includes('vintage') || token.includes('retro'))\n matrix.vintage(false)\n else if (token.includes('contrast'))\n matrix.contrast(0.5 + intensity * 0.5, false)\n else if (token.includes('brightness') || token.includes('bright'))\n matrix.brightness(0.5 + intensity, false)\n else if (token.includes('saturate') || token.includes('vivid'))\n matrix.saturate(intensity, false)\n else if (token.includes('cool'))\n matrix.hue(-20 * intensity, false)\n else\n matrix.saturate(-0.3 * intensity, false)\n\n return matrix\n}\n\nfunction buildNamedEffect(effect: Extract<VisualEffectParam, { segmentType: 'effect' }>): Filter | undefined {\n const token = normalizeToken(effect.name, effect.effectId)\n if (looksLikeBlur(token) || token.includes('glow') || token.includes('dream') || token.includes('soft'))\n return new BlurFilter({ strength: 4, quality: 2, kernelSize: 5 })\n\n if (token.includes('vintage') || token.includes('retro')) {\n const matrix = new ColorMatrixFilter()\n matrix.vintage(false)\n return matrix\n }\n\n if (token.includes('sharpen') || token.includes('clarity')) {\n const matrix = new ColorMatrixFilter()\n matrix.contrast(0.75, false)\n return matrix\n }\n\n return undefined\n}\n\nfunction looksLikeBlur(token: string): boolean {\n return token.includes('blur') || token.includes('gaussian')\n}\n\nfunction looksLikeGray(token: string): boolean {\n return token.includes('grayscale')\n || token.includes('grey')\n || token.includes('gray')\n || token.includes('mono')\n || token.includes('blackwhite')\n || token.includes('bw')\n}\n\nfunction normalizeToken(...parts: string[]): string {\n return parts\n .join(' ')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '')\n}\n\nfunction normalizeIntensity(value: number): number {\n if (!Number.isFinite(value))\n return 1\n return Math.min(Math.max(value, 0), 1)\n}\n","import type { IAudioSegment, IVideoFramesSegment, IVideoProtocol } from '@video-editor/shared'\nimport type { AudioPlanEvent } from './types'\nimport { createComposeRunner } from './compose-runner'\n\nexport interface ComposeAudioInput {\n segmentId: string\n segmentKind: 'audio' | 'video'\n url: string\n startTime: number\n endTime: number\n fromTime?: number\n playRate?: number\n volume?: number\n fadeInDuration?: number\n fadeOutDuration?: number\n}\n\ninterface SegmentLookup {\n audioById: Map<string, IAudioSegment>\n videoById: Map<string, IVideoFramesSegment>\n}\n\ninterface ActiveVoiceRuntime {\n voiceId: string\n segmentKind: 'audio' | 'video'\n segmentId: string\n startTime: number\n fromTime: number\n playRate: number\n}\n\nexport function createComposeAudioInputs(protocol: IVideoProtocol): ComposeAudioInput[] {\n const lookup = createSegmentLookup(protocol)\n const boundaries = collectEvaluationBoundaries(lookup)\n if (!boundaries.length)\n return []\n\n const outputs: ComposeAudioInput[] = []\n const activeVoices = new Map<string, ActiveVoiceRuntime>()\n const runner = createComposeRunner()\n const plans = runner.evaluateSequence(protocol, boundaries)\n for (const plan of plans) {\n for (const event of plan.audioEvents)\n applyAudioEvent(event, lookup, activeVoices, outputs)\n }\n\n for (const runtime of activeVoices.values()) {\n const finalized = finalizeVoice(runtime, lookup, lookupSegmentEnd(runtime, lookup))\n if (finalized)\n outputs.push(finalized)\n }\n\n return outputs.sort((a, b) => {\n if (a.startTime !== b.startTime)\n return a.startTime - b.startTime\n if (a.endTime !== b.endTime)\n return a.endTime - b.endTime\n return a.segmentId.localeCompare(b.segmentId)\n })\n}\n\nfunction applyAudioEvent(\n event: AudioPlanEvent,\n lookup: SegmentLookup,\n activeVoices: Map<string, ActiveVoiceRuntime>,\n outputs: ComposeAudioInput[],\n) {\n if (event.action === 'start') {\n const segment = lookupSegment(event.segmentKind, event.segmentId, lookup)\n if (!segment)\n return\n const volume = readSegmentVolume(segment)\n if (volume <= 0)\n return\n\n const runtime: ActiveVoiceRuntime = {\n voiceId: event.voiceId,\n segmentKind: event.segmentKind,\n segmentId: event.segmentId,\n startTime: event.atTimelineMs,\n fromTime: Math.max(0, event.sourceTimeMs ?? readSegmentFromTime(segment)),\n playRate: normalizePlayRate(event.rate ?? readSegmentPlayRate(segment)),\n }\n activeVoices.set(event.voiceId, runtime)\n return\n }\n\n if (event.action !== 'stop')\n return\n\n const runtime = activeVoices.get(event.voiceId)\n if (!runtime)\n return\n activeVoices.delete(event.voiceId)\n\n const finalized = finalizeVoice(runtime, lookup, event.atTimelineMs)\n if (finalized)\n outputs.push(finalized)\n}\n\nfunction finalizeVoice(\n runtime: ActiveVoiceRuntime,\n lookup: SegmentLookup,\n stopTime: number,\n): ComposeAudioInput | undefined {\n const segment = lookupSegment(runtime.segmentKind, runtime.segmentId, lookup)\n if (!segment)\n return undefined\n\n const startTime = clamp(runtime.startTime, segment.startTime, segment.endTime)\n const endTime = clamp(stopTime, startTime, segment.endTime)\n if (endTime <= startTime)\n return undefined\n\n const base: ComposeAudioInput = {\n segmentId: segment.id,\n segmentKind: runtime.segmentKind,\n url: segment.url,\n startTime,\n endTime,\n fromTime: runtime.fromTime,\n playRate: runtime.playRate,\n volume: readSegmentVolume(segment),\n }\n\n if (segment.segmentType === 'audio') {\n const durationMs = Math.max(0, endTime - startTime)\n return {\n ...base,\n fadeInDuration: normalizeFadeDuration(segment.fadeInDuration, durationMs),\n fadeOutDuration: normalizeFadeDuration(segment.fadeOutDuration, durationMs),\n }\n }\n\n return base\n}\n\nfunction createSegmentLookup(protocol: IVideoProtocol): SegmentLookup {\n const audioById = new Map<string, IAudioSegment>()\n const videoById = new Map<string, IVideoFramesSegment>()\n\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (segment.segmentType === 'audio')\n audioById.set(segment.id, segment)\n else if (segment.segmentType === 'frames' && segment.type === 'video')\n videoById.set(segment.id, segment)\n }\n }\n\n return { audioById, videoById }\n}\n\nfunction collectEvaluationBoundaries(lookup: SegmentLookup): number[] {\n const boundaries = new Set<number>([0])\n for (const segment of lookup.audioById.values())\n addBoundaries(boundaries, segment.startTime, segment.endTime)\n for (const segment of lookup.videoById.values())\n addBoundaries(boundaries, segment.startTime, segment.endTime)\n return [...boundaries].sort((a, b) => a - b)\n}\n\nfunction addBoundaries(boundaries: Set<number>, startTime: number, endTime: number) {\n if (!Number.isFinite(startTime) || !Number.isFinite(endTime))\n return\n if (endTime <= startTime)\n return\n boundaries.add(Math.max(0, startTime))\n boundaries.add(Math.max(0, endTime))\n}\n\nfunction lookupSegment(\n segmentKind: 'audio' | 'video',\n segmentId: string,\n lookup: SegmentLookup,\n): IAudioSegment | IVideoFramesSegment | undefined {\n if (segmentKind === 'audio')\n return lookup.audioById.get(segmentId)\n return lookup.videoById.get(segmentId)\n}\n\nfunction lookupSegmentEnd(runtime: ActiveVoiceRuntime, lookup: SegmentLookup): number {\n const segment = lookupSegment(runtime.segmentKind, runtime.segmentId, lookup)\n if (!segment)\n return runtime.startTime\n return segment.endTime\n}\n\nfunction readSegmentFromTime(segment: IAudioSegment | IVideoFramesSegment): number {\n if (typeof segment.fromTime !== 'number' || !Number.isFinite(segment.fromTime))\n return 0\n return Math.max(0, segment.fromTime)\n}\n\nfunction readSegmentPlayRate(segment: IAudioSegment | IVideoFramesSegment): number {\n return normalizePlayRate(segment.playRate)\n}\n\nfunction readSegmentVolume(segment: IAudioSegment | IVideoFramesSegment): number {\n return normalizeVolume(segment.volume)\n}\n\nfunction normalizeFadeDuration(durationMs: number | undefined, maxDurationMs: number): number {\n if (typeof durationMs !== 'number' || !Number.isFinite(durationMs))\n return 0\n return Math.max(0, Math.min(durationMs, maxDurationMs))\n}\n\nfunction normalizePlayRate(playRate: number | undefined): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return Math.max(0.1, Math.min(100, playRate))\n}\n\nfunction normalizeVolume(volume: number | undefined): number {\n if (typeof volume !== 'number' || !Number.isFinite(volume))\n return 1\n return Math.max(0, Math.min(1, volume))\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max)\n}\n","import type { ITextBasic } from '@video-editor/shared'\nimport { renderTxt2ImgBitmap } from '@webav/av-cliper'\n\nconst DEFAULT_TEXT_BITMAP_CACHE_LIMIT = 100\nconst textBitmapCache = new Map<string, ImageBitmap>()\nlet textBitmapCacheLimit = DEFAULT_TEXT_BITMAP_CACHE_LIMIT\n\nfunction touchCache(key: string, value: ImageBitmap) {\n textBitmapCache.delete(key)\n textBitmapCache.set(key, value)\n}\n\nfunction trimCache() {\n while (textBitmapCache.size > textBitmapCacheLimit) {\n const [oldestKey, bitmap] = textBitmapCache.entries().next().value as [string, ImageBitmap]\n textBitmapCache.delete(oldestKey)\n bitmap.close?.()\n }\n}\n\nexport function setTextBitmapCacheLimit(limit: number) {\n textBitmapCacheLimit = Math.max(0, Math.floor(limit))\n trimCache()\n}\n\nexport function clearTextBitmapCache() {\n for (const bitmap of textBitmapCache.values())\n bitmap.close?.()\n textBitmapCache.clear()\n}\n\nexport function buildTextContent(texts: ITextBasic[]) {\n return texts.map(item => item.content).filter(Boolean).join('\\n')\n}\n\nexport function buildTextCss(text: ITextBasic) {\n const fontFamily = Array.isArray(text.fontFamily)\n ? text.fontFamily.join(', ')\n : text.fontFamily\n const fontSize = text.fontSize ?? 32\n const fontWeight = text.fontWeight ?? 'normal'\n const fontStyle = text.fontStyle ?? 'normal'\n const fill = text.fill ?? '#ffffff'\n const align = text.align ?? 'left'\n\n const css: string[] = [\n `font-size: ${fontSize}px`,\n `font-weight: ${fontWeight}`,\n `font-style: ${fontStyle}`,\n `color: ${fill}`,\n `text-align: ${align}`,\n 'white-space: pre-wrap',\n ]\n\n if (fontFamily)\n css.push(`font-family: ${fontFamily}`)\n if (typeof text.letterSpacing === 'number')\n css.push(`letter-spacing: ${text.letterSpacing}px`)\n if (typeof text.leading === 'number')\n css.push(`line-height: ${text.leading}px`)\n if (text.background?.color)\n css.push(`background: ${text.background.color}`)\n if (text.stroke?.color && typeof text.stroke.width === 'number')\n css.push(`-webkit-text-stroke: ${text.stroke.width}px ${text.stroke.color}`)\n if (text.underline)\n css.push('text-decoration: underline')\n if (text.dropShadow?.color && typeof text.dropShadow.distance === 'number') {\n const angle = (text.dropShadow.angle ?? 45) * (Math.PI / 180)\n const offsetX = Math.cos(angle) * text.dropShadow.distance\n const offsetY = Math.sin(angle) * text.dropShadow.distance\n const blur = text.dropShadow.blur ?? 0\n css.push(`text-shadow: ${offsetX}px ${offsetY}px ${blur}px ${text.dropShadow.color}`)\n }\n\n return css.join('; ')\n}\n\nexport async function renderTextBitmap(content: string, cssText: string) {\n const key = `${cssText}::${content}`\n const cached = textBitmapCache.get(key)\n if (cached) {\n touchCache(key, cached)\n return cached\n }\n\n const bitmap = await renderTxt2ImgBitmap(content, cssText)\n if (textBitmapCacheLimit > 0) {\n textBitmapCache.set(key, bitmap)\n trimCache()\n }\n return bitmap\n}\n","import type { ITextSegment, IVideoFramesSegment, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { ComputedRef, Ref, ShallowRef } from '@vue/reactivity'\nimport type { Filter as PixiFilter } from 'pixi.js'\nimport type { Application, ApplicationOptions } from 'pixi.js'\nimport type { TimelinePlan } from './timeline'\nimport type { MaybeRef, PixiDisplayObject } from './types'\nimport { createResourceManager, createValidator, getResourceKey } from '@video-editor/protocol'\nimport {\n computed,\n effectScope,\n isRef,\n ref,\n shallowRef,\n unref,\n watch,\n} from '@vue/reactivity'\nimport { MP4Clip } from '@webav/av-cliper'\nimport { file as opfsFile } from 'opfs-tools'\nimport { Container, Sprite, Texture } from 'pixi.js'\nimport { createApp as create2dApp } from './2d'\nimport { AudioManager } from './audio-manager'\nimport {\n applyDisplayProps,\n clamp,\n cloneProtocol,\n collectResourceUrls,\n computeDuration,\n placeholder,\n} from './helpers'\nimport {\n createEmptyEvaluatorState,\n createPixiFiltersFromVisualEffects,\n createPreviewAudioTicker,\n createPreviewRunner,\n createVisualRenderItems,\n createTimelineTransport,\n evaluateTimelinePlan,\n} from './timeline'\nimport { buildTextContent, buildTextCss, renderTextBitmap } from './text'\n\nconst DEFAULT_RES_DIR = '/video-editor-res'\nconst VIDEO_PRELOAD_LOOKAHEAD_MS = 1500\nconst VIDEO_PRELOAD_LIMIT = 2\n\nexport interface RendererOptions {\n protocol: MaybeRef<IVideoProtocol>\n app?: Application\n appOptions?: Partial<ApplicationOptions>\n resourceDir?: string\n autoPlay?: boolean\n freezeOnPause?: boolean\n manualRender?: boolean\n videoSourceMode?: 'auto' | 'mp4clip' | 'element'\n warmUpResources?: boolean\n}\n\nexport interface Renderer {\n app: Application\n layer: Container\n currentTime: Ref<number>\n duration: ComputedRef<number>\n isPlaying: Ref<boolean>\n play: () => void\n pause: () => void\n tick: (deltaMs?: number) => void\n seek: (time: number) => void\n renderAt: (time: number) => Promise<void>\n destroy: () => void\n}\n\ninterface AudioManagerApi {\n setProtocol: (protocol: IVideoProtocol) => void\n applyTimelinePlan: (plan: TimelinePlan, isPlaying: boolean) => void\n resetTimelineState: (options?: { stop?: boolean }) => void\n destroy: () => void\n}\n\n/**\n * Create a renderer that reacts to protocol updates and drives playback state.\n * - Pass a reactive `protocol` (Ref/readonly/normal object)\n * - Call `play/pause/seek/tick` to drive the timeline\n * - Rendering updates when `protocol` or `currentTime` changes\n */\nexport async function createRenderer(opts: RendererOptions): Promise<Renderer> {\n const validator = createValidator()\n const protocolInput: Ref<IVideoProtocol> | ShallowRef<IVideoProtocol>\n = isRef(opts.protocol) ? opts.protocol : shallowRef(opts.protocol)\n const validatedProtocol: ShallowRef<IVideoProtocol> = shallowRef(\n validator.verify(cloneProtocol(unref(protocolInput))),\n )\n\n const app = opts.app ?? await create2dApp(opts.appOptions)\n const layer = new Container()\n app.stage.addChild(layer)\n\n const resourceManager = createResourceManager({ dir: opts.resourceDir })\n const resourceWarmUp = new Set<string>()\n const displayCache = new Map<string, PixiDisplayObject>()\n const displayLoading = new Map<string, Promise<PixiDisplayObject | undefined>>()\n const mp4ClipUnsupportedKeys = new Set<string>()\n const mp4ClipErrorLoggedKeys = new Set<string>()\n const videoSourceMode = opts.videoSourceMode ?? 'auto'\n type VideoEntry = (\n | {\n kind: 'mp4clip'\n clip: MP4Clip\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'element'\n video: HTMLVideoElement\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'frozen'\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n )\n const videoEntries = new Map<string, VideoEntry>()\n const videoObjectUrls = new Map<HTMLVideoElement, string>()\n const videoDisplayPreloading = new Set<string>()\n\n const currentTime = ref(0)\n const isPlaying = ref(false)\n const duration = computed(() => computeDuration(validatedProtocol.value))\n const mediaElementObjectUrls = new Map<string, string>()\n const mediaElementObjectUrlLoading = new Map<string, Promise<string | undefined>>()\n const audioManager: AudioManagerApi = new AudioManager(validatedProtocol.value, {\n resolveMediaElementUrl,\n }) as unknown as AudioManagerApi\n const transport = createTimelineTransport({\n initialTimelineMs: currentTime.value,\n initialRate: 1,\n playing: false,\n })\n const previewRunner = createPreviewRunner({\n transport,\n })\n const previewAudioTicker = createPreviewAudioTicker({\n transport,\n runner: previewRunner,\n getProtocol: () => validatedProtocol.value,\n onPlan: (plan) => {\n applyAudioPlan(plan)\n },\n })\n\n let rafId: number | undefined\n let lastTickAt = 0\n let renderGeneration = 0\n\n interface RenderTask {\n app: Application\n layer: Container\n protocol: IVideoProtocol\n at: number\n getDisplay: (segment: SegmentUnion) => Promise<PixiDisplayObject | undefined>\n }\n\n function resetSchedulerState() {\n previewRunner.reset()\n audioManager.resetTimelineState({ stop: true })\n }\n\n function applyAudioPlan(plan: TimelinePlan) {\n audioManager.applyTimelinePlan(plan, isPlaying.value)\n }\n\n function syncAudioWithScheduler(protocol: IVideoProtocol, at: number) {\n if (isPlaying.value)\n return\n\n const plan = previewRunner.evaluate(protocol, at)\n applyAudioPlan(plan)\n }\n\n async function renderScene(task: RenderTask) {\n const generation = renderGeneration\n const { protocol, at, layer } = task\n const renderTimelineMs = normalizeRenderTime(protocol, at)\n const stageWidth = task.app.renderer.width\n const stageHeight = task.app.renderer.height\n\n syncAudioWithScheduler(protocol, at)\n preloadUpcomingVideoDisplays(protocol, renderTimelineMs)\n\n const visualPlan = evaluateTimelinePlan(protocol, {\n atMs: renderTimelineMs,\n windowStartMs: renderTimelineMs,\n windowEndMs: renderTimelineMs,\n fps: Math.max(protocol.fps || 30, 1),\n }, createEmptyEvaluatorState()).plan.visuals\n const visualItems = createVisualRenderItems(protocol, visualPlan)\n const filterCache = new Map<string, PixiFilter[] | null>()\n\n const renders: (PixiDisplayObject | undefined)[] = []\n for (const visual of visualItems) {\n const { segment } = visual\n if (generation !== renderGeneration)\n return\n const display = await task.getDisplay(segment)\n if (generation !== renderGeneration)\n return\n if (!display)\n continue\n if ((display as { destroyed?: boolean }).destroyed)\n continue\n applyVisualEffects(display, visual.effects, filterCache)\n applyDisplayProps(display, segment, stageWidth, stageHeight, {\n opacity: visual.opacity,\n })\n if (isVideoSegment(segment))\n await updateVideoFrame(segment, visual.sourceTimeMs)\n if (generation !== renderGeneration)\n return\n renders.push(display)\n }\n\n if (generation !== renderGeneration)\n return\n layer.removeChildren()\n const cleaned = renders.filter(Boolean) as PixiDisplayObject[]\n if (cleaned.length)\n layer.addChild(...cleaned)\n if (generation !== renderGeneration)\n return\n task.app.render()\n }\n\n function applyVisualEffects(\n display: PixiDisplayObject,\n effects: TimelinePlan['visuals'][number]['effects'],\n cache: Map<string, PixiFilter[] | null>,\n ) {\n const key = effects?.length ? JSON.stringify(effects) : ''\n let resolved = cache.get(key)\n if (resolved === undefined) {\n resolved = effects?.length\n ? createPixiFiltersFromVisualEffects(effects)\n : null\n cache.set(key, resolved)\n }\n ;(display as PixiDisplayObject & { filters?: PixiFilter[] | null }).filters = resolved\n }\n\n const queueRender = createRenderQueue(() => renderScene({\n app,\n layer,\n protocol: validatedProtocol.value,\n at: currentTime.value,\n getDisplay: getDisplayForSegment,\n }))\n\n const scope = effectScope()\n scope.run(() => {\n // Sync external protocol mutations into a verified snapshot the renderer can rely on.\n watch(\n () => unref(protocolInput),\n (protocol) => {\n try {\n validatedProtocol.value = validator.verify(cloneProtocol(protocol))\n }\n catch (err) {\n console.error('[renderer] invalid protocol update', err)\n return\n }\n audioManager.setProtocol(validatedProtocol.value)\n resetSchedulerState()\n if (isPlaying.value)\n previewAudioTicker.tick()\n renderGeneration += 1\n clearDisplays()\n if (opts.warmUpResources !== false) {\n warmUpResources(validatedProtocol.value)\n warmUpMediaElementSources(validatedProtocol.value)\n }\n cleanupCache(validatedProtocol.value)\n cleanupMediaElementObjectUrls(validatedProtocol.value)\n clampCurrentTime()\n if (!opts.manualRender)\n queueRender()\n },\n { deep: true, immediate: true },\n )\n\n if (!opts.manualRender) {\n // React to time changes.\n watch(currentTime, () => {\n clampCurrentTime()\n queueRender()\n })\n }\n\n // Keep duration/currentTime in sync with protocol updates.\n watch(duration, () => clampCurrentTime())\n })\n\n function clampCurrentTime() {\n const nextDuration = duration.value\n if (nextDuration <= 0)\n currentTime.value = 0\n else if (currentTime.value > nextDuration)\n currentTime.value = nextDuration\n else if (currentTime.value < 0)\n currentTime.value = 0\n }\n\n function warmUpResources(protocol: IVideoProtocol) {\n for (const url of collectResourceUrls(protocol)) {\n if (resourceWarmUp.has(url))\n continue\n\n resourceWarmUp.add(url)\n if (inferUrlMediaType(url) === 'video')\n continue\n if (!shouldUseResourceManager(url))\n continue\n resourceManager.add(url).catch(() => {\n // noop – render will fall back to Texture.from(url)\n })\n }\n }\n\n function warmUpMediaElementSources(protocol: IVideoProtocol) {\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (!isVideoSegment(segment))\n continue\n if ((segment.volume ?? 1) <= 0)\n continue\n void ensureMediaElementObjectUrl(segment.url)\n }\n }\n }\n\n function cleanupCache(protocol: IVideoProtocol) {\n const ids = new Set<string>()\n for (const track of protocol.tracks) {\n for (const child of track.children)\n ids.add(child.id)\n }\n for (const [id, display] of displayCache) {\n if (ids.has(id))\n continue\n display.destroy()\n displayCache.delete(id)\n }\n for (const [id, entry] of videoEntries) {\n if (ids.has(id))\n continue\n destroyVideoEntry(entry)\n videoEntries.delete(id)\n }\n }\n\n function cleanupMediaElementObjectUrls(protocol: IVideoProtocol) {\n const activeKeys = new Set<string>()\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (!isVideoSegment(segment))\n continue\n const key = getResourceKey(segment.url)\n if (key)\n activeKeys.add(key)\n }\n }\n\n for (const [key, objectUrl] of mediaElementObjectUrls) {\n if (activeKeys.has(key))\n continue\n URL.revokeObjectURL(objectUrl)\n mediaElementObjectUrls.delete(key)\n }\n }\n\n function clearDisplays() {\n layer.removeChildren()\n for (const display of displayCache.values()) {\n display.destroy()\n }\n displayCache.clear()\n displayLoading.clear()\n for (const entry of videoEntries.values())\n destroyVideoEntry(entry)\n videoEntries.clear()\n }\n\n function play() {\n if (isPlaying.value)\n return\n isPlaying.value = true\n const now = performance.now()\n transport.seek(currentTime.value, now)\n transport.play(now)\n previewAudioTicker.start()\n lastTickAt = now\n rafId = requestAnimationFrame(loop)\n }\n\n function pause() {\n isPlaying.value = false\n const now = performance.now()\n transport.pause(now)\n previewAudioTicker.stop()\n resetSchedulerState()\n if (rafId !== undefined)\n cancelAnimationFrame(rafId)\n rafId = undefined\n if (opts.freezeOnPause !== false)\n freezeVideoEntries()\n }\n\n function loop() {\n tick()\n if (isPlaying.value)\n rafId = requestAnimationFrame(loop)\n }\n\n function tick(deltaMs?: number) {\n if (!isPlaying.value && deltaMs === undefined)\n return\n\n const now = performance.now()\n const delta = deltaMs ?? (lastTickAt ? now - lastTickAt : 0)\n lastTickAt = now\n\n if (delta === 0)\n return\n\n currentTime.value = clamp(\n currentTime.value + delta,\n 0,\n duration.value || Number.POSITIVE_INFINITY,\n )\n\n if (duration.value > 0 && currentTime.value >= duration.value)\n pause()\n\n // render happens via watch on currentTime\n }\n\n function seek(time: number) {\n currentTime.value = clamp(time, 0, duration.value || Number.POSITIVE_INFINITY)\n transport.seek(currentTime.value, performance.now())\n resetSchedulerState()\n if (isPlaying.value)\n previewAudioTicker.tick()\n }\n\n async function renderAt(time: number) {\n currentTime.value = clamp(time, 0, duration.value || Number.POSITIVE_INFINITY)\n transport.seek(currentTime.value, performance.now())\n resetSchedulerState()\n if (isPlaying.value)\n previewAudioTicker.tick()\n await queueRender()\n }\n\n async function getDisplayForSegment(segment: SegmentUnion) {\n const cached = displayCache.get(segment.id)\n if (cached)\n return cached\n\n const loading = displayLoading.get(segment.id)\n if (loading)\n return loading\n\n const promise = loadDisplay(segment)\n displayLoading.set(segment.id, promise)\n\n const display = await promise\n if (display)\n displayCache.set(segment.id, display)\n\n displayLoading.delete(segment.id)\n return display\n }\n\n function preloadUpcomingVideoDisplays(protocol: IVideoProtocol, atMs: number) {\n const availableSlots = VIDEO_PRELOAD_LIMIT - videoDisplayPreloading.size\n if (availableSlots <= 0)\n return\n\n const windowEndMs = atMs + VIDEO_PRELOAD_LOOKAHEAD_MS\n const candidates: IVideoFramesSegment[] = []\n\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (!isVideoSegment(segment))\n continue\n if (segment.startTime <= atMs || segment.startTime > windowEndMs)\n continue\n if (displayCache.has(segment.id) || displayLoading.has(segment.id) || videoDisplayPreloading.has(segment.id))\n continue\n candidates.push(segment)\n }\n }\n\n candidates.sort((left, right) => left.startTime - right.startTime)\n for (const segment of candidates.slice(0, availableSlots))\n void preloadVideoDisplay(segment)\n }\n\n async function preloadVideoDisplay(segment: IVideoFramesSegment) {\n videoDisplayPreloading.add(segment.id)\n try {\n const display = await loadDisplay(segment)\n if (display && !displayCache.has(segment.id))\n displayCache.set(segment.id, display)\n await updateVideoFrame(segment, Math.max(segment.fromTime ?? 0, 0))\n }\n catch (err) {\n console.error('[renderer] failed to preload upcoming video segment', segment.url, err)\n }\n finally {\n videoDisplayPreloading.delete(segment.id)\n }\n }\n\n async function loadDisplay(segment: SegmentUnion): Promise<PixiDisplayObject | undefined> {\n // prioritize static resources via protocol resource manager\n if (segment.segmentType === 'frames' || segment.segmentType === 'sticker') {\n if (!segment.url)\n return placeholder(segment.segmentType)\n\n if ('type' in segment && segment.type === 'video') {\n if (isRenderableVideoUrl(segment.url)) {\n const sprite = await loadVideoSprite(segment)\n if (sprite)\n return sprite\n return placeholder(segment.segmentType, segment.url)\n }\n }\n\n const texture = await loadTexture(segment.url)\n if (texture)\n return new Sprite(texture)\n return placeholder(segment.segmentType, segment.url)\n }\n\n if (segment.segmentType === 'text')\n return await buildTextDisplay(segment)\n\n if (segment.segmentType === 'effect' || segment.segmentType === 'filter')\n return undefined\n\n // audio segments do not render visuals\n return undefined\n }\n\n async function buildTextDisplay(segment: ITextSegment): Promise<PixiDisplayObject | undefined> {\n const content = buildTextContent(segment.texts)\n if (!content)\n return undefined\n\n const [text] = segment.texts\n if (!text)\n return undefined\n\n const bitmap = await renderTextBitmap(content, buildTextCss(text))\n const texture = Texture.from(bitmap)\n return new Sprite(texture)\n }\n\n async function loadTexture(url: string) {\n const isDataUrl = url.startsWith('data:')\n const isHttp = /^https?:\\/\\//.test(url)\n\n if (!isDataUrl && !isHttp) {\n try {\n await resourceManager.add(url)\n const res = await resourceManager.get(url)\n if (res instanceof HTMLImageElement)\n return Texture.from(res)\n }\n catch {\n // fall through to direct image load\n }\n }\n\n // load image directly to avoid invalid path issues with http/data URLs\n return await loadImageTexture(url)\n }\n\n async function loadVideoSprite(segment: SegmentUnion & { type: 'video', url: string }): Promise<Sprite | undefined> {\n const existing = videoEntries.get(segment.id)\n if (existing)\n return existing.sprite\n\n void ensureMediaElementObjectUrl(segment.url)\n const urlKey = getResourceKey(segment.url)\n const allowMp4Clip = videoSourceMode !== 'element'\n const allowVideoElement = videoSourceMode !== 'mp4clip'\n if (urlKey && mp4ClipUnsupportedKeys.has(urlKey)) {\n if (!allowVideoElement)\n throw new Error(`[renderer] MP4Clip unsupported for ${segment.url}`)\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n return undefined\n }\n\n if (allowMp4Clip) {\n const spriteFromClip = await loadVideoSpriteViaMP4Clip(segment.url).catch((err) => {\n if (urlKey && isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n if (!urlKey || !mp4ClipErrorLoggedKeys.has(urlKey)) {\n if (urlKey)\n mp4ClipErrorLoggedKeys.add(urlKey)\n console.warn('[renderer] failed to load video via MP4Clip', segment.url, err)\n }\n if (!allowVideoElement)\n throw err\n return undefined\n })\n if (spriteFromClip) {\n console.info('[renderer] video source: mp4clip', segment.url)\n videoEntries.set(segment.id, spriteFromClip)\n return spriteFromClip.sprite\n }\n }\n\n if (allowVideoElement) {\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n console.info('[renderer] video source: element', segment.url)\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n }\n\n return undefined\n }\n\n function isMp4ClipUnsupported(err: unknown) {\n if (!(err instanceof Error))\n return false\n const msg = err.message || ''\n return msg.includes('stream is done')\n || msg.includes('not emit ready')\n || msg.includes('tick video timeout')\n }\n\n async function updateVideoFrame(\n segment: IVideoFramesSegment,\n sourceTimeMs: number,\n ) {\n const entry = videoEntries.get(segment.id)\n if (!entry)\n return\n\n try {\n const relativeMs = Math.max(0, sourceTimeMs)\n const relativeUs = Math.floor(relativeMs * 1000)\n if (entry.kind === 'frozen') {\n const urlKey = getResourceKey(segment.url)\n if (!urlKey)\n return\n const revived = await loadVideoEntry(segment.url, urlKey, { sprite: entry.sprite, oldTexture: entry.texture })\n if (!revived)\n return\n videoEntries.set(segment.id, revived)\n return await updateVideoFrame(segment, sourceTimeMs)\n }\n if (entry.kind === 'mp4clip') {\n try {\n const res = await entry.clip.tick(relativeUs)\n if (res.video) {\n const ctx = entry.canvas.getContext('2d')\n if (ctx) {\n ctx.drawImage(res.video, 0, 0, entry.canvas.width, entry.canvas.height)\n refreshCanvasTexture(entry.texture)\n }\n res.video.close()\n }\n return\n }\n catch (err) {\n const urlKey = getResourceKey(segment.url)\n if (urlKey && isMp4ClipUnsupported(err)) {\n mp4ClipUnsupportedKeys.add(urlKey)\n entry.clip.destroy()\n if (videoSourceMode !== 'mp4clip') {\n const replacement = await loadVideoSpriteViaElement(segment.url, { sprite: entry.sprite, oldTexture: entry.texture }).catch((elementErr) => {\n console.warn('[renderer] failed to fallback to <video> after MP4Clip error', segment.url, elementErr)\n return undefined\n })\n if (replacement) {\n videoEntries.set(segment.id, replacement)\n return await updateVideoFrame(segment, sourceTimeMs)\n }\n }\n }\n if (urlKey && !mp4ClipErrorLoggedKeys.has(urlKey)) {\n mp4ClipErrorLoggedKeys.add(urlKey)\n console.warn('[renderer] MP4Clip tick failed', segment.url, err)\n }\n return\n }\n }\n\n const relativeSec = relativeMs / 1000\n if (!Number.isFinite(relativeSec))\n return\n if (entry.kind !== 'element')\n return\n await updateVideoElementFrame(entry, {\n targetSec: relativeSec,\n playbackRate: segment.playRate ?? 1,\n })\n }\n catch (err) {\n console.warn('[renderer] update video frame failed', err)\n }\n }\n\n async function loadVideoEntry(url: string, urlKey: string, reuse: { sprite: Sprite, oldTexture?: Texture }) {\n const allowMp4Clip = videoSourceMode !== 'element'\n const allowVideoElement = videoSourceMode !== 'mp4clip'\n if (mp4ClipUnsupportedKeys.has(urlKey)) {\n if (!allowVideoElement)\n throw new Error(`[renderer] MP4Clip unsupported for ${url}`)\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n }\n\n if (allowMp4Clip) {\n const fromClip = await loadVideoSpriteViaMP4Clip(url, reuse).catch((err) => {\n if (isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n if (!allowVideoElement)\n throw err\n return undefined\n })\n if (fromClip)\n return fromClip\n }\n\n if (allowVideoElement)\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n\n return undefined\n }\n\n function isVideoSegment(segment: SegmentUnion): segment is IVideoFramesSegment {\n return segment.segmentType === 'frames'\n && segment.type === 'video'\n && typeof segment.url === 'string'\n && isRenderableVideoUrl(segment.url)\n }\n\n\n function normalizeRenderTime(protocol: IVideoProtocol, at: number) {\n const total = computeDuration(protocol)\n if (total <= 0)\n return 0\n if (at < total)\n return at\n // Keep the last visible frame when playback reaches the end.\n const frameWindow = Math.max(1000 / Math.max(protocol.fps || 30, 1), 1)\n return Math.max(total - frameWindow, 0)\n }\n\n async function getOpfsFile(url: string) {\n const dir = opts.resourceDir ?? DEFAULT_RES_DIR\n try {\n const key = getResourceKey(url)\n if (!key)\n return undefined\n const file = opfsFile(`${dir}/${key}`, 'r')\n if (await file.exists())\n return file\n }\n catch {\n return undefined\n }\n return undefined\n }\n\n function resolveMediaElementUrl(segment: { url: string, segmentType?: string, type?: string }) {\n if (segment.segmentType !== 'frames' || segment.type !== 'video')\n return undefined\n\n const key = getResourceKey(segment.url)\n if (!key)\n return undefined\n\n void ensureMediaElementObjectUrl(segment.url)\n return mediaElementObjectUrls.get(key)\n }\n\n async function ensureMediaElementObjectUrl(url: string): Promise<string | undefined> {\n if (!shouldUseResourceManager(url))\n return undefined\n\n const key = getResourceKey(url)\n if (!key)\n return undefined\n\n const existing = mediaElementObjectUrls.get(key)\n if (existing)\n return existing\n\n const loading = mediaElementObjectUrlLoading.get(key)\n if (loading)\n return await loading\n\n const job = (async () => {\n let file = await getOpfsFile(url)\n if (!file) {\n await resourceManager.add(url).catch(() => {})\n file = await getOpfsFile(url)\n }\n if (!file)\n return undefined\n\n const originFile = await file.getOriginFile()\n if (!originFile)\n return undefined\n\n const objectUrl = URL.createObjectURL(originFile)\n mediaElementObjectUrls.set(key, objectUrl)\n return objectUrl\n })()\n\n mediaElementObjectUrlLoading.set(key, job)\n try {\n return await job\n }\n finally {\n mediaElementObjectUrlLoading.delete(key)\n }\n }\n\n function shouldUseResourceManager(url: string) {\n if (!url)\n return false\n if (url.startsWith('data:') || url.startsWith('blob:'))\n return false\n return true\n }\n\n function freezeVideoEntries() {\n for (const [id, entry] of videoEntries) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n videoEntries.set(id, {\n kind: 'frozen',\n canvas: entry.canvas,\n texture: entry.texture,\n sprite: entry.sprite,\n meta: entry.meta,\n })\n continue\n }\n\n if (entry.kind === 'element')\n entry.video.pause()\n }\n }\n\n function destroyVideoEntry(entry: VideoEntry) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n return\n }\n\n if (entry.kind === 'frozen')\n return\n\n entry.video.pause()\n const objectUrl = videoObjectUrls.get(entry.video)\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl)\n videoObjectUrls.delete(entry.video)\n }\n entry.video.removeAttribute('src')\n entry.video.load()\n }\n\n function waitForMediaEvent(target: HTMLMediaElement, type: string, timeoutMs = 1000) {\n return new Promise<void>((resolve, reject) => {\n const timer = window.setTimeout(() => {\n cleanup()\n reject(new Error(`Timed out waiting for media event: ${type}`))\n }, timeoutMs)\n\n const onOk = () => {\n cleanup()\n resolve()\n }\n const onErr = () => {\n cleanup()\n const mediaError = target.error ? `${target.error.code}` : 'unknown'\n reject(new Error(`Media error (${mediaError}) while waiting for ${type}`))\n }\n const cleanup = () => {\n window.clearTimeout(timer)\n target.removeEventListener(type, onOk)\n target.removeEventListener('error', onErr)\n }\n\n target.addEventListener(type, onOk, { once: true })\n target.addEventListener('error', onErr, { once: true })\n })\n }\n\n async function loadVideoSpriteViaMP4Clip(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n let file: ReturnType<typeof opfsFile> | undefined\n if (shouldUseResourceManager(url)) {\n file = await getOpfsFile(url)\n if (!file) {\n await resourceManager.add(url).catch(() => {})\n file = await getOpfsFile(url)\n }\n }\n\n let clip: MP4Clip | undefined\n try {\n if (file) {\n clip = new MP4Clip(file, { audio: false })\n }\n else {\n const res = await fetch(url)\n if (!res.body) {\n const buffer = await res.arrayBuffer()\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n controller.enqueue(new Uint8Array(buffer))\n controller.close()\n },\n })\n clip = new MP4Clip(stream, { audio: false })\n }\n else {\n clip = new MP4Clip(res.body, { audio: false })\n }\n }\n\n await clip.ready\n\n const { width, height } = clip.meta\n const canvas = document.createElement('canvas')\n canvas.width = width || 1\n canvas.height = height || 1\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'mp4clip', clip, canvas, texture, sprite, meta: { width, height } }\n }\n catch (err) {\n clip?.destroy()\n throw err\n }\n }\n\n function inferUrlMediaType(url: string): 'video' | 'image' | 'audio' | 'unknown' {\n const raw = url.split('#')[0]!.split('?')[0]!\n const ext = raw.split('/').pop()?.split('.').pop()?.toLowerCase() ?? ''\n if (['mp4', 'm4v', 'mov', 'webm'].includes(ext))\n return 'video'\n if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif'].includes(ext))\n return 'image'\n if (['mp3', 'wav', 'aac', 'm4a', 'ogg', 'flac'].includes(ext))\n return 'audio'\n return 'unknown'\n }\n\n function isRenderableVideoUrl(url: string) {\n const kind = inferUrlMediaType(url)\n if (kind === 'image' || kind === 'audio')\n return false\n // Treat unknown as video to support blob URLs or extension-less endpoints.\n return true\n }\n\n async function loadVideoSpriteViaElement(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n const video = document.createElement('video')\n video.crossOrigin = 'anonymous'\n video.muted = true\n video.playsInline = true\n video.preload = 'metadata'\n video.src = url\n video.load()\n\n try {\n await waitForMediaEvent(video, 'loadedmetadata', 15000)\n }\n catch (err) {\n video.pause()\n const objectUrl = videoObjectUrls.get(video)\n if (objectUrl) {\n URL.revokeObjectURL(objectUrl)\n videoObjectUrls.delete(video)\n }\n video.removeAttribute('src')\n video.load()\n throw err\n }\n\n const width = video.videoWidth || 1\n const height = video.videoHeight || 1\n\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'element', video, canvas, texture, sprite, meta: { width, height } }\n }\n\n\n async function updateVideoElementFrame(entry: Extract<VideoEntry, { kind: 'element' }>, opts: { targetSec: number, playbackRate: number }) {\n const { video, canvas, texture } = entry\n\n video.playbackRate = Number.isFinite(opts.playbackRate) && opts.playbackRate > 0 ? opts.playbackRate : 1\n video.muted = true\n video.volume = 0\n\n if (isPlaying.value)\n video.play().catch(() => {})\n else\n video.pause()\n\n const duration = Number.isFinite(video.duration) && video.duration > 0 ? video.duration : null\n const targetSec = duration ? Math.min(opts.targetSec, Math.max(duration - 0.03, 0)) : opts.targetSec\n\n const current = video.currentTime\n const drift = Math.abs(current - targetSec)\n const driftThreshold = isPlaying.value ? 0.25 : 0.03\n if (Number.isFinite(current) && drift > driftThreshold) {\n try {\n video.currentTime = targetSec\n }\n catch {\n // ignore seek errors for not-yet-ready media\n }\n await waitForMediaEvent(video, 'seeked', 250).catch(() => {})\n }\n\n if (video.readyState < 2) {\n // Avoid blocking the render queue for too long.\n await waitForMediaEvent(video, 'canplay', 250).catch(() => {})\n if (video.readyState < 2)\n return\n }\n\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height)\n refreshCanvasTexture(texture)\n }\n\n function loadImageTexture(url: string): Promise<Texture | undefined> {\n return new Promise((resolve) => {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => resolve(Texture.from(img))\n img.onerror = () => {\n console.warn('[renderer] failed to load image', url)\n resolve(undefined)\n }\n img.src = url\n })\n }\n\n function refreshCanvasTexture(texture: Texture) {\n const source = texture.source\n if ('update' in source && typeof source.update === 'function') {\n source.update()\n return\n }\n\n if (typeof texture.update === 'function')\n texture.update()\n }\n\n function destroy() {\n pause()\n renderGeneration += 1\n scope.stop()\n clearDisplays()\n layer.destroy({ children: true })\n displayCache.clear()\n displayLoading.clear()\n resourceWarmUp.clear()\n for (const objectUrl of mediaElementObjectUrls.values())\n URL.revokeObjectURL(objectUrl)\n mediaElementObjectUrls.clear()\n mediaElementObjectUrlLoading.clear()\n if (!opts.app)\n app.destroy()\n\n audioManager.destroy()\n }\n\n if (opts.autoPlay)\n play()\n\n return {\n app,\n layer,\n currentTime,\n duration,\n isPlaying,\n play,\n pause,\n tick,\n seek,\n renderAt,\n destroy,\n }\n}\n\nfunction createRenderQueue(job: () => Promise<void> | void) {\n let queued = false\n let running = false\n let pending: Promise<void> | null = null\n let resolvePending: (() => void) | null = null\n\n const run = async () => {\n if (!pending) {\n pending = new Promise((resolve) => {\n resolvePending = resolve\n })\n }\n const done = pending\n if (running) {\n queued = true\n return done\n }\n running = true\n do {\n queued = false\n await job()\n } while (queued)\n running = false\n resolvePending?.()\n pending = null\n resolvePending = null\n return done\n }\n\n return run\n}\n","import type { file as opfsFile } from 'opfs-tools'\nimport type { ICombinatorOpts } from '@webav/av-cliper'\nimport { Combinator, MP4Clip, OffscreenSprite } from '@webav/av-cliper'\n\nexport type VideoConcatSource =\n | string\n | ReadableStream<Uint8Array>\n | Blob\n | ReturnType<typeof opfsFile>\n\nexport interface ConcatVideoSource {\n source: VideoConcatSource\n}\n\nexport interface ConcatVideoOptions extends Omit<ICombinatorOpts, 'width' | 'height'> {\n width?: number\n height?: number\n onProgress?: (progress: number) => void\n}\n\nexport interface ConcatVideoResult {\n stream: ReadableStream<Uint8Array>\n width: number\n height: number\n durationMs: number\n destroy: () => void\n}\n\nfunction isOpfsFile(value: unknown): value is ReturnType<typeof opfsFile> {\n return typeof value === 'object'\n && value !== null\n && 'createReader' in value\n && 'getSize' in value\n}\n\nfunction isReadableStream(value: unknown): value is ReadableStream<Uint8Array> {\n return typeof ReadableStream !== 'undefined' && value instanceof ReadableStream\n}\n\nfunction normalizeInput(input: ConcatVideoSource | VideoConcatSource): ConcatVideoSource {\n if (typeof input === 'string' || input instanceof Blob || isOpfsFile(input) || isReadableStream(input))\n return { source: input }\n return input\n}\n\nasync function toClipSource(source: VideoConcatSource): Promise<ReadableStream<Uint8Array> | ReturnType<typeof opfsFile>> {\n if (typeof source === 'string') {\n const res = await fetch(source)\n if (!res.body)\n throw new Error('concatVideos: unable to read video stream from url')\n return res.body\n }\n\n if (source instanceof Blob)\n return source.stream() as ReadableStream<Uint8Array>\n\n return source\n}\n\nfunction wrapStreamWithCleanup(\n stream: ReadableStream<Uint8Array>,\n cleanup: () => void,\n): ReadableStream<Uint8Array> {\n let cleaned = false\n const finalize = () => {\n if (cleaned)\n return\n cleaned = true\n cleanup()\n }\n\n const reader = stream.getReader()\n return new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read()\n if (done) {\n finalize()\n controller.close()\n return\n }\n controller.enqueue(value)\n },\n async cancel(reason) {\n try {\n await reader.cancel(reason)\n }\n finally {\n finalize()\n }\n },\n })\n}\n\nexport async function concatVideos(\n inputs: Array<ConcatVideoSource | VideoConcatSource>,\n opts: ConcatVideoOptions = {},\n): Promise<ConcatVideoResult> {\n if (inputs.length === 0)\n throw new Error('concatVideos: expected at least one source')\n\n const {\n onProgress,\n width: requestedWidth,\n height: requestedHeight,\n ...combinatorOpts\n } = opts\n\n const normalized = inputs.map(normalizeInput)\n\n const [first, ...rest] = normalized\n const firstSource = await toClipSource(first.source)\n const firstClip = new MP4Clip(firstSource)\n await firstClip.ready\n\n const width = requestedWidth ?? Math.round(firstClip.meta.width || 0)\n const height = requestedHeight ?? Math.round(firstClip.meta.height || 0)\n if (!width || !height)\n {\n firstClip.destroy()\n throw new Error('concatVideos: output width/height is required')\n }\n\n const combinator = new Combinator({\n ...combinatorOpts,\n width,\n height,\n })\n\n if (onProgress)\n combinator.on('OutputProgress', onProgress)\n\n let offset = 0\n\n const addClip = async (clip: MP4Clip) => {\n const duration = clip.meta.duration\n if (!Number.isFinite(duration) || duration <= 0) {\n clip.destroy()\n throw new Error('concatVideos: invalid clip duration')\n }\n\n const sprite = new OffscreenSprite(clip)\n try {\n await sprite.ready\n sprite.rect.x = 0\n sprite.rect.y = 0\n sprite.rect.w = width\n sprite.rect.h = height\n sprite.time.offset = offset\n sprite.time.duration = duration\n\n await combinator.addSprite(sprite)\n offset += duration\n }\n finally {\n sprite.destroy()\n }\n }\n\n try {\n await addClip(firstClip)\n for (const entry of rest) {\n const source = await toClipSource(entry.source)\n const clip = new MP4Clip(source)\n await clip.ready\n await addClip(clip)\n }\n }\n catch (err) {\n combinator.destroy()\n throw err\n }\n\n const maxTime = offset\n const stream = combinator.output({ maxTime })\n const destroy = () => {\n combinator.destroy()\n }\n\n return {\n stream: wrapStreamWithCleanup(stream, destroy),\n width,\n height,\n durationMs: Math.round(maxTime / 1000),\n destroy,\n }\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { IClip } from '@webav/av-cliper'\nimport type { ApplicationOptions } from 'pixi.js'\nimport { Application } from 'pixi.js'\nimport type { RendererOptions } from './renderer-core'\nimport { createRenderer } from './renderer-core'\nimport { computeDuration } from './helpers'\n\nexport interface ProtocolVideoClipOptions {\n width?: number\n height?: number\n fps?: number\n appOptions?: Partial<ApplicationOptions>\n rendererOptions?: Partial<Omit<RendererOptions, 'protocol' | 'app' | 'appOptions'>>\n}\n\ninterface ClipMeta {\n width: number\n height: number\n duration: number\n}\n\nexport class ProtocolVideoClip implements IClip {\n readonly ready: Promise<ClipMeta>\n meta: ClipMeta\n\n private readonly protocol: IVideoProtocol\n private readonly options: ProtocolVideoClipOptions\n private renderer?: Awaited<ReturnType<typeof createRenderer>>\n private app?: Application\n private destroyed = false\n\n constructor(protocol: IVideoProtocol, options: ProtocolVideoClipOptions = {}) {\n this.protocol = protocol\n this.options = options\n\n const width = options.width ?? protocol.width\n const height = options.height ?? protocol.height\n const durationMs = computeDuration(protocol)\n this.meta = {\n width,\n height,\n duration: Math.max(0, Math.round(durationMs * 1000)),\n }\n\n this.ready = this.init()\n }\n\n private async init() {\n const width = this.options.width ?? this.protocol.width\n const height = this.options.height ?? this.protocol.height\n if (!width || !height)\n throw new Error('ProtocolVideoClip: output width/height is required')\n\n const app = new Application()\n await app.init({\n width,\n height,\n backgroundAlpha: 0,\n ...this.options.appOptions,\n })\n app.ticker.stop()\n this.app = app\n\n const rendererOptions = this.options.rendererOptions ?? {}\n const renderer = await createRenderer({\n protocol: this.protocol,\n app,\n ...rendererOptions,\n autoPlay: false,\n freezeOnPause: false,\n manualRender: true,\n videoSourceMode: rendererOptions.videoSourceMode ?? 'mp4clip',\n })\n this.renderer = renderer\n\n const durationMs = renderer.duration.value\n this.meta = {\n width: app.renderer.width,\n height: app.renderer.height,\n duration: Math.max(0, Math.round(durationMs * 1000)),\n }\n\n return this.meta\n }\n\n async tick(time: number): Promise<{\n video?: VideoFrame | ImageBitmap | null\n audio?: Float32Array[]\n state: 'done' | 'success'\n }> {\n const emptyAudio: Float32Array[] = []\n if (this.destroyed)\n return { audio: emptyAudio, state: 'done' }\n\n await this.ready\n if (!this.renderer)\n return { audio: emptyAudio, state: 'done' }\n\n const durationUs = this.meta.duration\n if (time >= durationUs)\n return { audio: emptyAudio, state: 'done' }\n\n const clampedUs = Math.max(0, Math.min(time, durationUs))\n await this.renderer.renderAt(clampedUs / 1000)\n\n const frame = new VideoFrame(this.renderer.app.canvas, {\n timestamp: time,\n })\n\n return {\n video: frame,\n audio: emptyAudio,\n state: 'success',\n }\n }\n\n async clone(): Promise<this> {\n const copy = new ProtocolVideoClip(this.protocol, this.options) as this\n await copy.ready\n return copy\n }\n\n destroy() {\n if (this.destroyed)\n return\n this.destroyed = true\n this.renderer?.destroy()\n this.app?.destroy(true)\n }\n}\n","import type { IVideoProtocol } from '@video-editor/shared'\nimport type { IClip, ICombinatorOpts } from '@webav/av-cliper'\nimport { AudioClip, Combinator, MP4Clip, OffscreenSprite } from '@webav/av-cliper'\nimport { ProtocolVideoClip } from './protocol-clip'\nimport type { ProtocolVideoClipOptions } from './protocol-clip'\nimport { createComposeAudioInputs } from './timeline'\nimport type { ComposeAudioInput } from './timeline'\n\nexport interface ComposeProtocolOptions extends Omit<ICombinatorOpts, 'width' | 'height' | 'fps'> {\n width?: number\n height?: number\n fps?: number\n onProgress?: (progress: number) => void\n clipOptions?: ProtocolVideoClipOptions\n audioSprites?: (protocol: IVideoProtocol) => Promise<OffscreenSprite[]>\n}\n\nexport interface ComposeProtocolResult {\n stream: ReadableStream<Uint8Array>\n width: number\n height: number\n durationMs: number\n destroy: () => void\n}\n\ninterface ClipMeta {\n width: number\n height: number\n duration: number\n}\n\ninterface SegmentAudioInput {\n startTime: number\n endTime: number\n fromTime?: number\n playRate?: number\n volume?: number\n fadeInDuration?: number\n fadeOutDuration?: number\n}\n\ninterface SegmentAudioConfig {\n fromUs: number\n segmentDurationUs: number\n playRate: number\n baseVolume: number\n fadeInUs: number\n fadeOutUs: number\n}\n\nconst RESOURCE_TIMEOUT_MS = 12000\n\nfunction withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const timer = globalThis.setTimeout(() => {\n reject(new Error(`composeProtocol: ${label} timed out (${timeoutMs}ms)`))\n }, timeoutMs)\n promise\n .then((value) => {\n globalThis.clearTimeout(timer)\n resolve(value)\n })\n .catch((err) => {\n globalThis.clearTimeout(timer)\n reject(err)\n })\n })\n}\n\nclass SegmentAudioClip implements IClip {\n readonly ready: Promise<ClipMeta>\n\n private clipMeta: ClipMeta = {\n width: 0,\n height: 0,\n duration: 0,\n }\n\n constructor(\n private readonly sourceClip: IClip,\n private readonly config: SegmentAudioConfig,\n ) {\n this.ready = this.sourceClip.ready.then((meta) => {\n const playbackDurationUs = Math.round(this.config.segmentDurationUs * this.config.playRate)\n const availableUs = Math.max(0, meta.duration - this.config.fromUs)\n this.clipMeta = {\n width: meta.width,\n height: meta.height,\n duration: Math.max(0, Math.min(playbackDurationUs, availableUs)),\n }\n return this.meta\n })\n }\n\n get meta() {\n return { ...this.clipMeta }\n }\n\n async tick(time: number): ReturnType<IClip['tick']> {\n const relativeSourceUs = Math.max(0, Math.round(time))\n const relativeTimelineUs = Math.round(relativeSourceUs / this.config.playRate)\n if (relativeTimelineUs >= this.config.segmentDurationUs) {\n return {\n audio: [],\n state: 'done',\n }\n }\n\n const sourceUs = this.config.fromUs + relativeSourceUs\n const result = await this.sourceClip.tick(sourceUs)\n closeFrame(result.video)\n\n const gain = this.resolveGain(relativeTimelineUs)\n return {\n audio: applyGain(result.audio ?? [], gain),\n state: result.state,\n }\n }\n\n async clone(): Promise<this> {\n const clonedSource = await this.sourceClip.clone()\n const copy = new SegmentAudioClip(clonedSource, this.config) as this\n await copy.ready\n return copy\n }\n\n destroy() {\n this.sourceClip.destroy()\n }\n\n private resolveGain(relativeTimelineUs: number): number {\n let volumeMultiplier = 1\n if (this.config.fadeInUs > 0 && relativeTimelineUs < this.config.fadeInUs)\n volumeMultiplier = Math.max(0, relativeTimelineUs / this.config.fadeInUs)\n\n const remainingUs = this.config.segmentDurationUs - relativeTimelineUs\n if (this.config.fadeOutUs > 0 && remainingUs < this.config.fadeOutUs)\n volumeMultiplier = Math.min(volumeMultiplier, Math.max(0, remainingUs / this.config.fadeOutUs))\n\n return this.config.baseVolume * volumeMultiplier\n }\n}\n\nfunction closeFrame(frame: unknown) {\n if (!frame || typeof frame !== 'object')\n return\n const maybeClose = (frame as { close?: unknown }).close\n if (typeof maybeClose === 'function')\n maybeClose.call(frame)\n}\n\nfunction applyGain(audio: Float32Array[], gain: number): Float32Array[] {\n if (!audio.length || gain >= 0.999)\n return audio\n\n if (gain <= 0)\n return audio.map(chan => new Float32Array(chan.length))\n\n return audio.map((chan) => {\n const out = new Float32Array(chan.length)\n for (let i = 0; i < chan.length; i++)\n out[i] = chan[i]! * gain\n return out\n })\n}\n\nfunction toUs(ms: number): number {\n if (!Number.isFinite(ms))\n return 0\n return Math.max(0, Math.round(ms * 1000))\n}\n\nfunction normalizeVolume(volume?: number): number {\n if (typeof volume !== 'number' || !Number.isFinite(volume))\n return 1\n return Math.max(0, Math.min(1, volume))\n}\n\nfunction normalizePlayRate(playRate?: number): number {\n if (typeof playRate !== 'number' || !Number.isFinite(playRate))\n return 1\n return Math.max(0.1, Math.min(100, playRate))\n}\n\nfunction createSegmentAudioConfig(segment: SegmentAudioInput): SegmentAudioConfig {\n const durationMs = Math.max(0, segment.endTime - segment.startTime)\n const fadeInMs = Math.max(0, Math.min(segment.fadeInDuration ?? 0, durationMs))\n const fadeOutMs = Math.max(0, Math.min(segment.fadeOutDuration ?? 0, durationMs))\n return {\n fromUs: toUs(segment.fromTime ?? 0),\n segmentDurationUs: toUs(durationMs),\n playRate: normalizePlayRate(segment.playRate),\n baseVolume: normalizeVolume(segment.volume),\n fadeInUs: toUs(fadeInMs),\n fadeOutUs: toUs(fadeOutMs),\n }\n}\n\nasync function fetchReadable(url: string, timeoutMs: number = RESOURCE_TIMEOUT_MS): Promise<ReadableStream<Uint8Array>> {\n const controller = new AbortController()\n const timeoutId = globalThis.setTimeout(() => controller.abort(), timeoutMs)\n try {\n const response = await fetch(url, { signal: controller.signal })\n if (!response.body)\n throw new Error(`composeProtocol: unable to read resource stream: ${url}`)\n return response.body\n }\n catch (err) {\n if (controller.signal.aborted)\n throw new Error(`composeProtocol: loading resource timed out (${timeoutMs}ms): ${url}`)\n throw err\n }\n finally {\n globalThis.clearTimeout(timeoutId)\n }\n}\n\nasync function createSegmentAudioSprite(sourceClip: IClip, segment: SegmentAudioInput): Promise<OffscreenSprite> {\n const config = createSegmentAudioConfig(segment)\n const clip = new SegmentAudioClip(sourceClip, config)\n const sprite = new OffscreenSprite(clip)\n try {\n await withTimeout(sprite.ready, RESOURCE_TIMEOUT_MS, 'prepare audio sprite')\n }\n catch (err) {\n sprite.destroy()\n throw err\n }\n\n sprite.time.offset = toUs(segment.startTime)\n sprite.time.duration = config.segmentDurationUs\n sprite.time.playbackRate = config.playRate\n return sprite\n}\n\nasync function createAudioSpriteFromInput(input: ComposeAudioInput): Promise<OffscreenSprite> {\n const stream = await fetchReadable(input.url)\n const sourceClip: IClip = input.segmentKind === 'audio'\n ? new AudioClip(stream)\n : new MP4Clip(stream, { audio: true })\n return await createSegmentAudioSprite(sourceClip, input)\n}\n\nasync function createProtocolAudioSprites(protocol: IVideoProtocol): Promise<OffscreenSprite[]> {\n const inputs = createComposeAudioInputs(protocol)\n const tasks = inputs.map(input => createAudioSpriteFromInput(input))\n\n if (!tasks.length)\n return []\n\n const settled = await Promise.allSettled(tasks)\n const sprites: OffscreenSprite[] = []\n for (const item of settled) {\n if (item.status === 'fulfilled') {\n sprites.push(item.value)\n continue\n }\n console.warn('[compose] skip audio sprite due to load failure', item.reason)\n }\n return sprites\n}\n\nfunction destroySprites(sprites: OffscreenSprite[]) {\n for (const sprite of sprites)\n sprite.destroy()\n}\n\nfunction wrapStreamWithCleanup(\n stream: ReadableStream<Uint8Array>,\n cleanup: () => void,\n): ReadableStream<Uint8Array> {\n let cleaned = false\n const finalize = () => {\n if (cleaned)\n return\n cleaned = true\n cleanup()\n }\n\n const reader = stream.getReader()\n return new ReadableStream({\n async pull(controller) {\n const { done, value } = await reader.read()\n if (done) {\n finalize()\n controller.close()\n return\n }\n controller.enqueue(value)\n },\n async cancel(reason) {\n try {\n await reader.cancel(reason)\n }\n finally {\n finalize()\n }\n },\n })\n}\n\nexport async function composeProtocol(\n protocol: IVideoProtocol,\n opts: ComposeProtocolOptions = {},\n): Promise<ComposeProtocolResult> {\n const {\n width: requestedWidth,\n height: requestedHeight,\n fps: requestedFps,\n onProgress,\n clipOptions,\n audioSprites,\n ...combinatorOpts\n } = opts\n\n const width = requestedWidth ?? protocol.width\n const height = requestedHeight ?? protocol.height\n if (!width || !height)\n throw new Error('composeProtocol: output width/height is required')\n\n const fps = requestedFps ?? protocol.fps\n\n const resolvedAudioSprites = combinatorOpts.audio === false\n ? []\n : (typeof audioSprites === 'function'\n ? await audioSprites(protocol)\n : await createProtocolAudioSprites(protocol))\n\n const audio = combinatorOpts.audio ?? (resolvedAudioSprites.length > 0 ? undefined : false)\n const combinator = new Combinator({\n ...combinatorOpts,\n audio,\n width,\n height,\n fps,\n })\n\n if (onProgress)\n combinator.on('OutputProgress', onProgress)\n\n let clip: ProtocolVideoClip | undefined\n let sprite: OffscreenSprite | undefined\n try {\n clip = new ProtocolVideoClip(protocol, {\n width,\n height,\n fps,\n ...clipOptions,\n rendererOptions: {\n warmUpResources: false,\n ...clipOptions?.rendererOptions,\n },\n })\n await clip.ready\n\n sprite = new OffscreenSprite(clip)\n await sprite.ready\n sprite.time.offset = 0\n sprite.time.duration = clip.meta.duration\n sprite.rect.x = 0\n sprite.rect.y = 0\n sprite.rect.w = clip.meta.width\n sprite.rect.h = clip.meta.height\n\n await combinator.addSprite(sprite, { main: true })\n\n for (const extra of resolvedAudioSprites)\n await combinator.addSprite(extra)\n }\n catch (err) {\n destroySprites(resolvedAudioSprites)\n sprite?.destroy()\n clip?.destroy()\n combinator.destroy()\n throw err\n }\n\n const maxTime = clip?.meta.duration ?? 0\n if (!maxTime) {\n destroySprites(resolvedAudioSprites)\n sprite?.destroy()\n clip?.destroy()\n combinator.destroy()\n throw new Error('composeProtocol: protocol has no duration')\n }\n\n const stream = combinator.output({ maxTime })\n let destroyed = false\n const destroy = () => {\n if (destroyed)\n return\n destroyed = true\n destroySprites(resolvedAudioSprites)\n sprite?.destroy()\n clip?.destroy()\n combinator.destroy()\n }\n\n return {\n stream: wrapStreamWithCleanup(stream, destroy),\n width,\n height,\n durationMs: Math.round(maxTime / 1000),\n destroy,\n }\n}\n"],"names":["createApp","opts","app","Application","AudioManager","protocol","options","plan","isPlaying","event","id","audio","sampleRate","pcmChannels","key","plannedVolume","volume","plannedRate","playbackRate","gainNode","state","source","gain","voice","segment","sourceOffsetMs","targetSourceSec","isSourceExhausted","normalizedGain","normalizedRate","existing","runtime","startAt","sources","channels","len","buffer","i","data","safePlaybackRate","nextStart","duration","index","map","nextUrl","el","maybePromise","targetSec","timelineMs","normalizedTargetSec","playRate","sourceTimeMs","relativeMs","fromTimeMs","segmentSourceDurationMs","segmentMaxSourceSec","mediaDurationSec","effectiveMaxSourceSec","normalizedSourceSec","channel","track","resolveFillSize","mode","sourceWidth","sourceHeight","stageWidth","stageHeight","safeSourceWidth","safeSourceHeight","sourceRatio","stageRatio","computeSegmentLayout","fillMode","width","height","transform","px","py","sx","sy","rotation","finalWidth","finalHeight","centerX","centerY","collectResourceUrls","urls","applyDisplayProps","display","opacity","normalizeOpacity","readOpacity","Sprite","layout","Texture","placeholderTexture","Graphics","stringToColor","hasOpacity","placeholder","url","g","color","svg","hash","computeDuration","endTimes","seg","clamp","num","min","max","cloneProtocol","raw","toRaw","MIN_PLAY_RATE","MAX_PLAY_RATE","createTimelineTransport","nowProvider","defaultNow","playing","rate","normalizeRate","discontinuitySeq","epochWallMs","resolveNow","epochTimelineMs","normalizeTimelineMs","listeners","currentTimelineMs","nowMs","snapshotAt","emit","snapshot","listener","anchorAt","resolvedNow","nextRate","normalizedNextRate","collectTransitionByFromSegmentId","transitionByFromSegmentId","adjacentToByFrom","collectAdjacentFramePairs","transition","isValidTransitionEdge","isValidTransition","edge","children","fromSegment","toSegment","createEmptyEvaluatorState","evaluateTimelinePlan","context","previousState","atMs","normalizeTimeMs","windowStartMs","windowEndMs","visuals","activeVoiceById","activeEffects","collectActiveEffects","trackIndex","trackOrder","getTrackOrder","childIndex","isActiveAt","buildVisualPlanItem","toActiveVoiceMeta","a","b","previousVoiceById","previousVoice","audioEvents","voiceId","activeVoices","input","effects","mapSourceTimeMs","computeTransition","isAudioSegment","mapRemappableSourceTimeMs","computeAudioSegmentGain","normalizePlayRate","isVideoFramesSegment","normalizeVolume","fromTime","startMs","progress","baseVolume","segmentDurationMs","fadeInDurationMs","fadeOutDurationMs","envelope","timeUntilEnd","trackCount","value","createStatefulTimelineEvaluator","output","DEFAULT_LOOKBACK_MS","DEFAULT_LOOKAHEAD_MS","createPreviewRunner","lookbackMs","normalizeWindowMs","lookaheadMs","evaluator","lastDiscontinuitySeq","discontinuity","windowMs","fallback","createComposeRunner","lastAtMs","normalizedAtMs","atMsList","plans","DEFAULT_TICK_INTERVAL_MS","createPreviewAudioTicker","intervalMs","normalizeIntervalMs","setIntervalFn","callback","tickIntervalMs","clearIntervalFn","handle","timer","tick","createVisualRenderItems","segmentById","indexSegments","activeSegmentIds","visual","items","clamp01","fromOpacity","targetSegment","transitionDurationMs","elapsedTransitionMs","targetSourceTimeMs","mapTransitionTargetSourceTimeMs","targetOpacity","readSegmentOpacity","createPixiFiltersFromVisualEffects","filters","effect","filter","buildFilterTrackEffect","buildNamedEffect","token","normalizeToken","intensity","normalizeIntensity","looksLikeBlur","BlurFilter","matrix","ColorMatrixFilter","looksLikeGray","parts","createComposeAudioInputs","lookup","createSegmentLookup","boundaries","collectEvaluationBoundaries","outputs","applyAudioEvent","finalized","finalizeVoice","lookupSegmentEnd","lookupSegment","readSegmentVolume","readSegmentFromTime","readSegmentPlayRate","stopTime","startTime","endTime","base","durationMs","normalizeFadeDuration","audioById","videoById","addBoundaries","segmentKind","segmentId","maxDurationMs","DEFAULT_TEXT_BITMAP_CACHE_LIMIT","textBitmapCache","textBitmapCacheLimit","touchCache","trimCache","oldestKey","bitmap","buildTextContent","texts","item","buildTextCss","text","fontFamily","fontSize","fontWeight","fontStyle","fill","align","css","angle","offsetX","offsetY","blur","renderTextBitmap","content","cssText","cached","renderTxt2ImgBitmap","DEFAULT_RES_DIR","VIDEO_PRELOAD_LOOKAHEAD_MS","VIDEO_PRELOAD_LIMIT","createRenderer","validator","createValidator","protocolInput","isRef","shallowRef","validatedProtocol","unref","create2dApp","layer","Container","resourceManager","createResourceManager","resourceWarmUp","displayCache","displayLoading","mp4ClipUnsupportedKeys","mp4ClipErrorLoggedKeys","videoSourceMode","videoEntries","videoObjectUrls","videoDisplayPreloading","currentTime","ref","computed","mediaElementObjectUrls","mediaElementObjectUrlLoading","audioManager","resolveMediaElementUrl","transport","previewRunner","previewAudioTicker","applyAudioPlan","rafId","lastTickAt","renderGeneration","resetSchedulerState","syncAudioWithScheduler","at","renderScene","task","generation","renderTimelineMs","normalizeRenderTime","preloadUpcomingVideoDisplays","visualPlan","visualItems","filterCache","renders","applyVisualEffects","isVideoSegment","updateVideoFrame","cleaned","cache","resolved","queueRender","createRenderQueue","getDisplayForSegment","scope","effectScope","watch","err","clearDisplays","warmUpResources","warmUpMediaElementSources","cleanupCache","cleanupMediaElementObjectUrls","clampCurrentTime","nextDuration","inferUrlMediaType","shouldUseResourceManager","ensureMediaElementObjectUrl","ids","child","entry","destroyVideoEntry","activeKeys","getResourceKey","objectUrl","play","now","loop","pause","freezeVideoEntries","deltaMs","delta","seek","time","renderAt","loading","promise","loadDisplay","availableSlots","candidates","left","right","preloadVideoDisplay","isRenderableVideoUrl","sprite","loadVideoSprite","texture","loadTexture","buildTextDisplay","isDataUrl","isHttp","res","loadImageTexture","urlKey","allowMp4Clip","allowVideoElement","spriteFromElement","loadVideoSpriteViaElement","spriteFromClip","loadVideoSpriteViaMP4Clip","isMp4ClipUnsupported","msg","relativeUs","revived","loadVideoEntry","ctx","refreshCanvasTexture","replacement","elementErr","relativeSec","updateVideoElementFrame","reuse","fromClip","total","frameWindow","getOpfsFile","dir","file","opfsFile","job","originFile","waitForMediaEvent","target","type","timeoutMs","resolve","reject","cleanup","onOk","onErr","mediaError","clip","MP4Clip","stream","controller","canvas","ext","kind","video","current","drift","driftThreshold","img","destroy","queued","running","pending","resolvePending","done","isOpfsFile","isReadableStream","normalizeInput","toClipSource","wrapStreamWithCleanup","finalize","reader","reason","concatVideos","inputs","onProgress","requestedWidth","requestedHeight","combinatorOpts","normalized","first","rest","firstSource","firstClip","combinator","Combinator","offset","addClip","OffscreenSprite","maxTime","ProtocolVideoClip","rendererOptions","renderer","emptyAudio","durationUs","clampedUs","copy","RESOURCE_TIMEOUT_MS","withTimeout","label","SegmentAudioClip","sourceClip","config","meta","playbackDurationUs","availableUs","relativeSourceUs","relativeTimelineUs","sourceUs","result","closeFrame","applyGain","clonedSource","volumeMultiplier","remainingUs","frame","maybeClose","chan","out","toUs","ms","createSegmentAudioConfig","fadeInMs","fadeOutMs","fetchReadable","timeoutId","response","createSegmentAudioSprite","createAudioSpriteFromInput","AudioClip","createProtocolAudioSprites","tasks","settled","sprites","destroySprites","composeProtocol","requestedFps","clipOptions","audioSprites","fps","resolvedAudioSprites","extra","destroyed"],"mappings":"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"}
|