@meframe/core 0.1.9 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/AudioMixBlockCache.d.ts +18 -0
- package/dist/cache/AudioMixBlockCache.d.ts.map +1 -0
- package/dist/cache/AudioMixBlockCache.js +57 -0
- package/dist/cache/AudioMixBlockCache.js.map +1 -0
- package/dist/cache/CacheManager.js +0 -1
- package/dist/cache/CacheManager.js.map +1 -1
- package/dist/cache/l1/AudioL1Cache.d.ts +0 -7
- package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -1
- package/dist/cache/l1/AudioL1Cache.js +41 -40
- package/dist/cache/l1/AudioL1Cache.js.map +1 -1
- package/dist/controllers/PlaybackController.d.ts +0 -1
- package/dist/controllers/PlaybackController.d.ts.map +1 -1
- package/dist/controllers/PlaybackController.js +14 -25
- package/dist/controllers/PlaybackController.js.map +1 -1
- package/dist/controllers/PlaybackStateMachine.d.ts.map +1 -1
- package/dist/controllers/PlaybackStateMachine.js +2 -0
- package/dist/controllers/PlaybackStateMachine.js.map +1 -1
- package/dist/orchestrator/GlobalAudioSession.d.ts +26 -6
- package/dist/orchestrator/GlobalAudioSession.d.ts.map +1 -1
- package/dist/orchestrator/GlobalAudioSession.js +283 -93
- package/dist/orchestrator/GlobalAudioSession.js.map +1 -1
- package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -1
- package/dist/stages/compose/OfflineAudioMixer.js +4 -1
- package/dist/stages/compose/OfflineAudioMixer.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlaybackController.js","sources":["../../src/controllers/PlaybackController.ts"],"sourcesContent":["import type {\n IPlaybackController,\n PlaybackOptions,\n IEventBus,\n PreviewHandle,\n TimeUs,\n} from './types';\nimport {\n PlaybackActionType,\n PlaybackCommandType,\n PlaybackState,\n type OpToken,\n type PlaybackAction,\n type PlaybackCommand,\n} from './types';\nimport { MeframeEvent } from '../event/events';\nimport type { GlobalAudioSession } from '../orchestrator/GlobalAudioSession';\nimport type { Orchestrator } from '../orchestrator';\nimport type { RequestMode } from '../orchestrator/types';\nimport { WaiterReplacedError } from '../utils/errors';\nimport { VideoComposer } from '../stages/compose/VideoComposer';\nimport { isVideoClip } from '../model/types';\n\nimport { PlaybackStateMachine } from './PlaybackStateMachine';\n\n/**\n * Playback controller for preview\n * Internal implementation - not exposed directly to external consumers\n */\nexport class PlaybackController implements IPlaybackController, PreviewHandle {\n private orchestrator: Orchestrator;\n private eventBus: IEventBus;\n private canvas: HTMLCanvasElement | OffscreenCanvas;\n private videoComposer: VideoComposer | null = null;\n\n // Playback time (external)\n currentTimeUs: TimeUs = 0;\n private playbackRate = 1.0;\n private volume = 1.0;\n private loop = false;\n\n // Time base\n private rafId: number | null = null;\n private startTimeUs: TimeUs = 0; // AudioContext timeline origin (microseconds)\n\n // Frame stats\n private frameCount = 0;\n private lastFrameTime = 0;\n private fps = 0;\n\n // Audio\n private audioContext: AudioContext;\n private audioSession: GlobalAudioSession;\n private lastAudioScheduleTime = 0;\n private readonly AUDIO_SCHEDULE_INTERVAL = 100_000; // 100ms\n\n // State machine\n private fsm = new PlaybackStateMachine();\n\n // Unified window management for both video and audio\n private windowEnd: TimeUs = 0;\n private readonly WINDOW_DURATION = 3_000_000; // 3s decode window\n private readonly AUDIO_READY_PROBE_WINDOW = 500_000; // 500ms: gate buffering only for near-future audio\n private readonly PREHEAT_DISTANCE = 1_000_000; // 1s preheat trigger distance\n private preheatInProgress = false;\n\n constructor(orchestrator: Orchestrator, eventBus: IEventBus, options: PlaybackOptions) {\n this.orchestrator = orchestrator;\n this.audioSession = orchestrator.audioSession;\n this.eventBus = eventBus;\n this.canvas = options.canvas;\n this.audioContext = new AudioContext();\n\n const model = orchestrator.compositionModel;\n const width = model?.renderConfig?.width || this.canvas.width || 720;\n const height = model?.renderConfig?.height || this.canvas.height || 1280;\n\n this.videoComposer = new VideoComposer({\n width,\n height,\n fps: model?.fps || 30,\n backgroundColor: model?.renderConfig?.backgroundColor || '#000',\n externalCanvas: this.canvas,\n });\n\n if (options.startUs !== undefined) {\n this.currentTimeUs = options.startUs;\n }\n if (options.rate !== undefined) {\n this.playbackRate = options.rate;\n }\n if (options.loop !== undefined) {\n this.loop = options.loop;\n }\n\n this.setupEventListeners();\n\n if (options.autoStart) {\n this.play();\n }\n }\n\n async renderCover(): Promise<void> {\n await this.renderCurrentFrame(0, { mode: 'blocking' });\n }\n\n // ========= Public API =========\n\n play(): void {\n this.dispatch({ type: PlaybackActionType.Play });\n }\n\n pause(): void {\n this.dispatch({ type: PlaybackActionType.Pause });\n }\n\n stop(): void {\n this.dispatch({ type: PlaybackActionType.Stop });\n }\n\n async seek(timeUs: TimeUs): Promise<void> {\n const { done } = this.dispatch({\n type: PlaybackActionType.Seek,\n timeUs,\n durationUs: this.duration,\n });\n await done;\n }\n\n setRate(rate: number): void {\n const currentTimeUs = this.currentTimeUs;\n this.playbackRate = rate;\n\n // Keep currentTimeUs stable; update the time base for AudioContext clock mapping.\n this.startTimeUs = this.audioContext.currentTime * 1_000_000 - currentTimeUs / rate;\n this.audioSession.setPlaybackRate(this.playbackRate);\n\n this.eventBus.emit(MeframeEvent.PlaybackRateChange, { rate });\n }\n\n setVolume(volume: number): void {\n this.volume = Math.max(0, Math.min(1, volume));\n this.audioSession.setVolume(this.volume);\n this.eventBus.emit(MeframeEvent.PlaybackVolumeChange, { volume: this.volume });\n }\n\n setMute(muted: boolean): void {\n if (muted) {\n this.audioSession.stopPlayback();\n return;\n }\n if (this.fsm.snapshot.state === PlaybackState.Playing) {\n void this.audioSession.startPlayback(this.currentTimeUs, this.audioContext);\n }\n }\n\n setLoop(loop: boolean): void {\n this.loop = loop;\n }\n\n get duration(): TimeUs {\n return this.orchestrator.compositionModel?.durationUs ?? 0;\n }\n\n get isPlaying(): boolean {\n return this.fsm.snapshot.state === PlaybackState.Playing;\n }\n\n resume(): void {\n this.play();\n }\n\n on(event: string, handler: (payload: any) => void): void {\n this.eventBus.on(event as MeframeEvent, handler);\n }\n\n off(event: string, handler: (payload: any) => void): void {\n this.eventBus.off(event as MeframeEvent, handler);\n }\n\n // ========= State machine wiring =========\n\n private dispatch(action: PlaybackAction): { token: OpToken; done: Promise<void> } {\n const { token, commands } = this.fsm.dispatch(action, { currentTimeUs: this.currentTimeUs });\n const done = this.executeCommands(commands, token);\n return { token, done };\n }\n\n private executeCommands(commands: PlaybackCommand[], token: OpToken): Promise<void> {\n const maybe = this.executeSeq(commands, token, 0);\n return maybe ?? Promise.resolve();\n }\n\n private executeSeq(\n commands: PlaybackCommand[],\n token: OpToken,\n startIndex: number\n ): Promise<void> | void {\n for (let i = startIndex; i < commands.length; i++) {\n if (!this.isCurrentToken(token)) return;\n const maybe = this.executeCommand(commands[i]!, token);\n if (maybe) {\n return maybe.then(() => {\n if (!this.isCurrentToken(token)) return;\n const cont = this.executeSeq(commands, token, i + 1);\n return cont ?? Promise.resolve();\n });\n }\n }\n }\n\n private executePar(commands: PlaybackCommand[], token: OpToken): Promise<any> | void {\n const promises: Promise<void>[] = [];\n for (const c of commands) {\n if (!this.isCurrentToken(token)) return;\n const maybe = this.executeCommand(c, token);\n if (maybe) promises.push(maybe);\n }\n if (promises.length === 0) return;\n return Promise.all(promises);\n }\n\n private executeCommand(command: PlaybackCommand, token: OpToken): Promise<any> | void {\n if (!this.isCurrentToken(token)) return;\n\n switch (command.type) {\n case PlaybackCommandType.Seq:\n return this.executeSeq(command.commands, token, 0);\n case PlaybackCommandType.Par:\n return this.executePar(command.commands, token);\n case PlaybackCommandType.Try: {\n const handleError = (error: unknown): Promise<void> | void => {\n if (!this.isCurrentToken(token)) return;\n if (command.ignoreWaiterReplacedError && error instanceof WaiterReplacedError) return;\n if (command.logPrefix) console.error(command.logPrefix, error);\n const onErrorDone = command.onError ? this.dispatch(command.onError).done : undefined;\n const normalizeError = (e: unknown): Error => {\n if (e instanceof Error) return e;\n return new Error(typeof e === 'string' ? e : JSON.stringify(e));\n };\n const emit = () => {\n if (command.emitPlaybackError) {\n const err = normalizeError(error);\n // PlaybackError: direct playback channel error for advanced consumers.\n this.eventBus.emit(MeframeEvent.PlaybackError, err);\n // Error: generic error channel expected by higher-level wrappers (e.g. @meframe/axii).\n this.eventBus.emit(MeframeEvent.Error, {\n source: 'playback',\n error: err,\n context: {\n command: command.logPrefix,\n onError: command.onError?.type,\n },\n recoverable: false,\n });\n }\n };\n if (onErrorDone) {\n return onErrorDone.then(() => {\n emit();\n });\n }\n emit();\n };\n\n try {\n const maybe = this.executeCommand(command.command, token);\n if (maybe) {\n return maybe.catch(handleError);\n }\n return;\n } catch (error) {\n return handleError(error) ?? Promise.resolve();\n }\n }\n case PlaybackCommandType.Dispatch:\n return this.dispatch(command.action).done;\n case PlaybackCommandType.SetTime: {\n this.currentTimeUs = command.timeUs;\n return;\n }\n case PlaybackCommandType.SetFrozenTime:\n case PlaybackCommandType.SetWantsPlay:\n case PlaybackCommandType.SetState: {\n // managed inside fsm\n return;\n }\n case PlaybackCommandType.CancelRaf: {\n this.cancelRaf();\n return;\n }\n case PlaybackCommandType.StopAudio: {\n this.audioSession.stopPlayback();\n return;\n }\n case PlaybackCommandType.ResetAudioPlaybackStates: {\n this.audioSession.resetPlaybackStates();\n return;\n }\n case PlaybackCommandType.ResetAudioSession: {\n this.audioSession.reset();\n return;\n }\n case PlaybackCommandType.ClearCanvas: {\n this.clearCanvas();\n return;\n }\n case PlaybackCommandType.SetLastAudioScheduleTime: {\n this.lastAudioScheduleTime = command.timeUs;\n return;\n }\n case PlaybackCommandType.SetStartTimeBase: {\n this.startTimeUs = command.startTimeUs;\n return;\n }\n case PlaybackCommandType.SyncTimeBaseToAudioClock: {\n this.startTimeUs =\n this.audioContext.currentTime * 1_000_000 - command.timeUs / this.playbackRate;\n return;\n }\n case PlaybackCommandType.InitWindow: {\n this.initWindow(command.timeUs);\n return;\n }\n case PlaybackCommandType.SetCacheWindow: {\n this.orchestrator.cacheManager.setWindow(command.timeUs);\n return;\n }\n case PlaybackCommandType.Emit: {\n if (command.payload === undefined) {\n this.eventBus.emit(command.event as any);\n } else {\n this.eventBus.emit(command.event as any, command.payload);\n }\n return;\n }\n case PlaybackCommandType.RenderFrame: {\n return this.renderCurrentFrame(command.timeUs, {\n mode: command.mode,\n relativeTimeUs: command.relativeTimeUs,\n });\n }\n case PlaybackCommandType.MaybeRenderKeyframePreview: {\n return this.orchestrator.tryRenderKeyframe(command.timeUs).then((keyframeTimeUs) => {\n if (!this.isCurrentToken(token)) return;\n if (keyframeTimeUs === null) return;\n return this.orchestrator\n .getRenderState(command.timeUs, {\n mode: 'probe',\n relativeTimeUs: keyframeTimeUs,\n })\n .then((keyframeRenderState) => {\n if (!this.isCurrentToken(token)) return;\n if (!keyframeRenderState) return;\n return this.compose(command.timeUs, keyframeRenderState);\n });\n });\n }\n case PlaybackCommandType.EnsureAudio: {\n return this.audioSession.ensureAudioForTime(command.timeUs, {\n mode: command.mode,\n });\n }\n case PlaybackCommandType.GetFrame: {\n return this.orchestrator.getFrame(command.timeUs, {\n mode: command.mode,\n preheat: command.preheat,\n });\n }\n case PlaybackCommandType.StartAudioPlayback: {\n return this.audioSession.startPlayback(command.timeUs, this.audioContext);\n }\n case PlaybackCommandType.ProbeStartReady: {\n const audioWindowEnd = Math.min(\n this.duration,\n command.timeUs + this.AUDIO_READY_PROBE_WINDOW\n );\n\n const audioReady = this.audioSession.isAudioResourceWindowReady(\n command.timeUs,\n audioWindowEnd\n );\n const videoReady = this.isVideoResourceReadyAtTime(command.timeUs);\n\n if (audioReady && videoReady) return;\n\n // Kick background preparation (best-effort).\n if (!audioReady) {\n void this.audioSession.ensureAudioForTime(command.timeUs, { mode: 'probe' });\n }\n if (!videoReady) {\n void this.orchestrator.getFrame(command.timeUs, { mode: 'probe' });\n }\n\n // Enter buffering and bump token to cancel the remaining start sequence.\n this.dispatch({\n type: PlaybackActionType.EnterBuffering,\n timeUs: command.timeUs,\n bumpToken: true,\n reason: 'startup',\n });\n return;\n }\n case PlaybackCommandType.StartRafLoop: {\n this.startPlaybackLoop(token);\n return;\n }\n }\n }\n\n private cancelRaf(): void {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n }\n\n private isCurrentToken(token: OpToken): boolean {\n return token === this.fsm.snapshot.token;\n }\n\n private startPlaybackLoop(token: OpToken): void {\n this.rafId = requestAnimationFrame(() => {\n void this.onRafTick(token);\n });\n }\n\n private async onRafTick(token: OpToken): Promise<void> {\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n const candidateTimeUs =\n (this.audioContext.currentTime * 1_000_000 - this.startTimeUs) * this.playbackRate;\n this.dispatch({\n type: PlaybackActionType.ClockTick,\n candidateTimeUs,\n durationUs: this.duration,\n loop: this.loop,\n audioNowUs: this.audioContext.currentTime * 1_000_000,\n });\n\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n // Audio probe: if the audio window isn't ready, enter buffering (freeze timeline)\n // and kick background audio preparation.\n const audioWindowEnd = Math.min(\n this.duration,\n this.currentTimeUs + this.AUDIO_READY_PROBE_WINDOW\n );\n if (!this.audioSession.isAudioResourceWindowReady(this.currentTimeUs, audioWindowEnd)) {\n void this.audioSession.ensureAudioForTime(this.currentTimeUs, { mode: 'probe' });\n this.dispatch({ type: PlaybackActionType.EnterBuffering, timeUs: this.currentTimeUs });\n return;\n }\n\n // Throttle audio scheduling.\n if (this.currentTimeUs - this.lastAudioScheduleTime >= this.AUDIO_SCHEDULE_INTERVAL) {\n await this.audioSession.scheduleAudio(this.currentTimeUs, this.audioContext);\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) return;\n this.lastAudioScheduleTime = this.currentTimeUs;\n }\n\n const renderState = await this.orchestrator.getRenderState(this.currentTimeUs, {\n mode: 'probe',\n });\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n if (!renderState) {\n this.dispatch({ type: PlaybackActionType.EnterBuffering, timeUs: this.currentTimeUs });\n return;\n }\n\n await this.compose(this.currentTimeUs, renderState);\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) return;\n\n this.updateFps();\n this.frameCount++;\n\n // Unified cache window update.\n this.orchestrator.cacheManager.setWindow(this.currentTimeUs);\n\n this.checkAndPreheatWindow();\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) return;\n\n this.startPlaybackLoop(token);\n }\n\n private updateFps(): void {\n const now = performance.now();\n if (this.lastFrameTime > 0) {\n const deltaTime = now - this.lastFrameTime;\n const instantFps = 1000 / deltaTime;\n this.fps = this.fps > 0 ? this.fps * 0.9 + instantFps * 0.1 : instantFps;\n }\n this.lastFrameTime = now;\n }\n\n private initWindow(timeUs: TimeUs): void {\n this.windowEnd = timeUs + this.WINDOW_DURATION;\n this.preheatInProgress = false;\n this.orchestrator.cacheManager.setWindow(timeUs);\n }\n\n private checkAndPreheatWindow(): void {\n if (this.preheatInProgress || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n const distanceToWindowEnd = this.windowEnd - this.currentTimeUs;\n if (distanceToWindowEnd < 0) {\n this.initWindow(this.currentTimeUs);\n return;\n }\n\n if (distanceToWindowEnd > 0 && distanceToWindowEnd <= this.PREHEAT_DISTANCE) {\n void this.preheatNextWindow();\n }\n }\n\n async preheatNextWindow(): Promise<void> {\n if (this.preheatInProgress) return;\n\n this.preheatInProgress = true;\n try {\n const windowStart = this.currentTimeUs;\n const windowEnd = windowStart + this.WINDOW_DURATION;\n\n const clipsInWindow =\n this.orchestrator.compositionModel?.getClipsInRange(windowStart, windowEnd) ?? [];\n const preheatPromises: Promise<any>[] = [];\n\n for (const clip of clipsInWindow) {\n if (!isVideoClip(clip)) continue;\n\n const clipWindowStart = Math.max(0, windowStart - clip.startUs);\n const clipWindowEnd = Math.min(clip.durationUs, windowEnd - clip.startUs);\n if (clipWindowStart >= clipWindowEnd) continue;\n\n preheatPromises.push(\n this.orchestrator.preheatClipWindow(clip.id, clipWindowStart, clipWindowEnd, windowStart)\n );\n }\n\n // Non-blocking audio preheat.\n preheatPromises.push(this.audioSession.ensureAudioForTime(windowStart, { mode: 'blocking' }));\n\n await Promise.all(preheatPromises);\n this.windowEnd = windowEnd;\n } catch (error) {\n console.warn('[PlaybackController] Preheat failed:', error);\n } finally {\n this.preheatInProgress = false;\n }\n }\n\n private async renderCurrentFrame(\n timeUs: TimeUs,\n options: { mode: RequestMode; relativeTimeUs?: TimeUs }\n ): Promise<void> {\n if (!this.videoComposer) {\n console.error('[PlaybackController] VideoComposer not initialized');\n return;\n }\n\n const renderState = await this.orchestrator.getRenderState(timeUs, {\n mode: options.mode,\n relativeTimeUs: options.relativeTimeUs,\n });\n\n if (!renderState) {\n return;\n }\n\n await this.compose(timeUs, renderState);\n }\n\n private async compose(\n timeUs: TimeUs,\n renderState: { layers: any[]; transition?: any }\n ): Promise<void> {\n if (!this.videoComposer) return;\n await this.videoComposer.composeFrame({\n timeUs,\n layers: renderState.layers,\n transition: renderState.transition,\n });\n }\n\n private clearCanvas(): void {\n const ctx = this.canvas.getContext('2d') as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D\n | null;\n if (ctx && 'clearRect' in ctx) {\n ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n }\n\n // ========= Cleanup / event handlers =========\n\n dispose(): void {\n this.stop();\n this.eventBus.off(MeframeEvent.CacheCover, this.onCacheCover);\n this.eventBus.off(MeframeEvent.ModelSet, this.onModelSet);\n if (this.videoComposer) {\n this.videoComposer.dispose();\n this.videoComposer = null;\n }\n }\n\n private onCacheCover = (): void => {\n if (this.fsm.snapshot.state === PlaybackState.Idle && this.currentTimeUs === 0) {\n void this.renderCurrentFrame(0, { mode: 'blocking' });\n }\n };\n\n private onModelSet = (): void => {\n if (!this.videoComposer || !this.orchestrator.compositionModel) return;\n\n // Model switching cancels in-flight async chains, but must NOT enter buffering or reset time/state.\n // Buffering runs a long async sequence; if cancelled mid-way it can leave the FSM stuck.\n this.dispatch({ type: PlaybackActionType.ModelSet });\n\n const model = this.orchestrator.compositionModel;\n this.videoComposer.updateConfig({\n width: model.renderConfig?.width || 720,\n height: model.renderConfig?.height || 1280,\n fps: model.fps || 30,\n backgroundColor: model.renderConfig?.backgroundColor || '#000',\n });\n\n // Best-effort background preheat.\n void this.audioSession.ensureAudioForTime(this.currentTimeUs, { mode: 'blocking' });\n void this.renderCurrentFrame(this.currentTimeUs, { mode: 'blocking' });\n };\n\n private setupEventListeners(): void {\n this.eventBus.on(MeframeEvent.CacheCover, this.onCacheCover);\n this.eventBus.on(MeframeEvent.ModelSet, this.onModelSet);\n }\n\n private isVideoResourceReadyAtTime(timeUs: TimeUs): boolean {\n const model = this.orchestrator.compositionModel;\n if (!model) return true;\n const clip = model.getClipsAtTime(timeUs, model.mainTrackId)[0];\n if (!clip || !('resourceId' in clip) || typeof (clip as any).resourceId !== 'string')\n return true;\n const resourceId = (clip as any).resourceId as string;\n const resource = model.getResource(resourceId);\n return resource?.state === 'ready';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlaybackController.js","sources":["../../src/controllers/PlaybackController.ts"],"sourcesContent":["import type {\n IPlaybackController,\n PlaybackOptions,\n IEventBus,\n PreviewHandle,\n TimeUs,\n} from './types';\nimport {\n PlaybackActionType,\n PlaybackCommandType,\n PlaybackState,\n type OpToken,\n type PlaybackAction,\n type PlaybackCommand,\n} from './types';\nimport { MeframeEvent } from '../event/events';\nimport type { GlobalAudioSession } from '../orchestrator/GlobalAudioSession';\nimport type { Orchestrator } from '../orchestrator';\nimport type { RequestMode } from '../orchestrator/types';\nimport { WaiterReplacedError } from '../utils/errors';\nimport { VideoComposer } from '../stages/compose/VideoComposer';\nimport { isVideoClip } from '../model/types';\n\nimport { PlaybackStateMachine } from './PlaybackStateMachine';\n\n/**\n * Playback controller for preview\n * Internal implementation - not exposed directly to external consumers\n */\nexport class PlaybackController implements IPlaybackController, PreviewHandle {\n private orchestrator: Orchestrator;\n private eventBus: IEventBus;\n private canvas: HTMLCanvasElement | OffscreenCanvas;\n private videoComposer: VideoComposer | null = null;\n\n // Playback time (external)\n currentTimeUs: TimeUs = 0;\n private playbackRate = 1.0;\n private volume = 1.0;\n private loop = false;\n\n // Time base\n private rafId: number | null = null;\n private startTimeUs: TimeUs = 0; // AudioContext timeline origin (microseconds)\n\n // Frame stats\n private frameCount = 0;\n private lastFrameTime = 0;\n private fps = 0;\n\n // Audio\n private audioContext: AudioContext;\n private audioSession: GlobalAudioSession;\n private lastAudioScheduleTime = 0;\n private readonly AUDIO_SCHEDULE_INTERVAL = 250_000; // 250ms\n\n // State machine\n private fsm = new PlaybackStateMachine();\n\n // Unified window management for both video and audio\n private windowEnd: TimeUs = 0;\n private readonly WINDOW_DURATION = 3_000_000; // 3s decode window\n private readonly PREHEAT_DISTANCE = 1_000_000; // 1s preheat trigger distance\n private preheatInProgress = false;\n\n constructor(orchestrator: Orchestrator, eventBus: IEventBus, options: PlaybackOptions) {\n this.orchestrator = orchestrator;\n this.audioSession = orchestrator.audioSession;\n this.eventBus = eventBus;\n this.canvas = options.canvas;\n this.audioContext = new AudioContext();\n\n const model = orchestrator.compositionModel;\n const width = model?.renderConfig?.width || this.canvas.width || 720;\n const height = model?.renderConfig?.height || this.canvas.height || 1280;\n\n this.videoComposer = new VideoComposer({\n width,\n height,\n fps: model?.fps || 30,\n backgroundColor: model?.renderConfig?.backgroundColor || '#000',\n externalCanvas: this.canvas,\n });\n\n if (options.startUs !== undefined) {\n this.currentTimeUs = options.startUs;\n }\n if (options.rate !== undefined) {\n this.playbackRate = options.rate;\n }\n if (options.loop !== undefined) {\n this.loop = options.loop;\n }\n\n this.setupEventListeners();\n\n if (options.autoStart) {\n this.play();\n }\n }\n\n async renderCover(): Promise<void> {\n await this.renderCurrentFrame(0, { mode: 'blocking' });\n }\n\n // ========= Public API =========\n\n play(): void {\n this.dispatch({ type: PlaybackActionType.Play });\n }\n\n pause(): void {\n this.dispatch({ type: PlaybackActionType.Pause });\n }\n\n stop(): void {\n this.dispatch({ type: PlaybackActionType.Stop });\n }\n\n async seek(timeUs: TimeUs): Promise<void> {\n const { done } = this.dispatch({\n type: PlaybackActionType.Seek,\n timeUs,\n durationUs: this.duration,\n });\n await done;\n }\n\n setRate(rate: number): void {\n const currentTimeUs = this.currentTimeUs;\n this.playbackRate = rate;\n\n // Keep currentTimeUs stable; update the time base for AudioContext clock mapping.\n this.startTimeUs = this.audioContext.currentTime * 1_000_000 - currentTimeUs / rate;\n this.audioSession.setPlaybackRate(this.playbackRate);\n\n this.eventBus.emit(MeframeEvent.PlaybackRateChange, { rate });\n }\n\n setVolume(volume: number): void {\n this.volume = Math.max(0, Math.min(1, volume));\n this.audioSession.setVolume(this.volume);\n this.eventBus.emit(MeframeEvent.PlaybackVolumeChange, { volume: this.volume });\n }\n\n setMute(muted: boolean): void {\n if (muted) {\n this.audioSession.stopPlayback();\n return;\n }\n if (this.fsm.snapshot.state === PlaybackState.Playing) {\n void this.audioSession.startPlayback(this.currentTimeUs, this.audioContext);\n }\n }\n\n setLoop(loop: boolean): void {\n this.loop = loop;\n }\n\n get duration(): TimeUs {\n return this.orchestrator.compositionModel?.durationUs ?? 0;\n }\n\n get isPlaying(): boolean {\n return this.fsm.snapshot.state === PlaybackState.Playing;\n }\n\n resume(): void {\n this.play();\n }\n\n on(event: string, handler: (payload: any) => void): void {\n this.eventBus.on(event as MeframeEvent, handler);\n }\n\n off(event: string, handler: (payload: any) => void): void {\n this.eventBus.off(event as MeframeEvent, handler);\n }\n\n // ========= State machine wiring =========\n\n private dispatch(action: PlaybackAction): { token: OpToken; done: Promise<void> } {\n const { token, commands } = this.fsm.dispatch(action, { currentTimeUs: this.currentTimeUs });\n const done = this.executeCommands(commands, token);\n return { token, done };\n }\n\n private executeCommands(commands: PlaybackCommand[], token: OpToken): Promise<void> {\n const maybe = this.executeSeq(commands, token, 0);\n return maybe ?? Promise.resolve();\n }\n\n private executeSeq(\n commands: PlaybackCommand[],\n token: OpToken,\n startIndex: number\n ): Promise<void> | void {\n for (let i = startIndex; i < commands.length; i++) {\n if (!this.isCurrentToken(token)) return;\n const maybe = this.executeCommand(commands[i]!, token);\n if (maybe) {\n return maybe.then(() => {\n if (!this.isCurrentToken(token)) return;\n const cont = this.executeSeq(commands, token, i + 1);\n return cont ?? Promise.resolve();\n });\n }\n }\n }\n\n private executePar(commands: PlaybackCommand[], token: OpToken): Promise<any> | void {\n const promises: Promise<void>[] = [];\n for (const c of commands) {\n if (!this.isCurrentToken(token)) return;\n const maybe = this.executeCommand(c, token);\n if (maybe) promises.push(maybe);\n }\n if (promises.length === 0) return;\n return Promise.all(promises);\n }\n\n private executeCommand(command: PlaybackCommand, token: OpToken): Promise<any> | void {\n if (!this.isCurrentToken(token)) return;\n\n switch (command.type) {\n case PlaybackCommandType.Seq:\n return this.executeSeq(command.commands, token, 0);\n case PlaybackCommandType.Par:\n return this.executePar(command.commands, token);\n case PlaybackCommandType.Try: {\n const handleError = (error: unknown): Promise<void> | void => {\n if (!this.isCurrentToken(token)) return;\n if (command.ignoreWaiterReplacedError && error instanceof WaiterReplacedError) return;\n if (command.logPrefix) console.error(command.logPrefix, error);\n const onErrorDone = command.onError ? this.dispatch(command.onError).done : undefined;\n const normalizeError = (e: unknown): Error => {\n if (e instanceof Error) return e;\n return new Error(typeof e === 'string' ? e : JSON.stringify(e));\n };\n const emit = () => {\n if (command.emitPlaybackError) {\n const err = normalizeError(error);\n // PlaybackError: direct playback channel error for advanced consumers.\n this.eventBus.emit(MeframeEvent.PlaybackError, err);\n // Error: generic error channel expected by higher-level wrappers (e.g. @meframe/axii).\n this.eventBus.emit(MeframeEvent.Error, {\n source: 'playback',\n error: err,\n context: {\n command: command.logPrefix,\n onError: command.onError?.type,\n },\n recoverable: false,\n });\n }\n };\n if (onErrorDone) {\n return onErrorDone.then(() => {\n emit();\n });\n }\n emit();\n };\n\n try {\n const maybe = this.executeCommand(command.command, token);\n if (maybe) {\n return maybe.catch(handleError);\n }\n return;\n } catch (error) {\n return handleError(error) ?? Promise.resolve();\n }\n }\n case PlaybackCommandType.Dispatch:\n return this.dispatch(command.action).done;\n case PlaybackCommandType.SetTime: {\n this.currentTimeUs = command.timeUs;\n return;\n }\n case PlaybackCommandType.SetFrozenTime:\n case PlaybackCommandType.SetWantsPlay:\n case PlaybackCommandType.SetState: {\n // managed inside fsm\n return;\n }\n case PlaybackCommandType.CancelRaf: {\n this.cancelRaf();\n return;\n }\n case PlaybackCommandType.StopAudio: {\n this.audioSession.stopPlayback();\n return;\n }\n case PlaybackCommandType.ResetAudioPlaybackStates: {\n this.audioSession.resetPlaybackStates();\n return;\n }\n case PlaybackCommandType.ResetAudioSession: {\n this.audioSession.reset();\n return;\n }\n case PlaybackCommandType.ClearCanvas: {\n this.clearCanvas();\n return;\n }\n case PlaybackCommandType.SetLastAudioScheduleTime: {\n this.lastAudioScheduleTime = command.timeUs;\n return;\n }\n case PlaybackCommandType.SetStartTimeBase: {\n this.startTimeUs = command.startTimeUs;\n return;\n }\n case PlaybackCommandType.SyncTimeBaseToAudioClock: {\n this.startTimeUs =\n this.audioContext.currentTime * 1_000_000 - command.timeUs / this.playbackRate;\n return;\n }\n case PlaybackCommandType.InitWindow: {\n this.initWindow(command.timeUs);\n return;\n }\n case PlaybackCommandType.SetCacheWindow: {\n this.orchestrator.cacheManager.setWindow(command.timeUs);\n return;\n }\n case PlaybackCommandType.Emit: {\n if (command.payload === undefined) {\n this.eventBus.emit(command.event as any);\n } else {\n this.eventBus.emit(command.event as any, command.payload);\n }\n return;\n }\n case PlaybackCommandType.RenderFrame: {\n return this.renderCurrentFrame(command.timeUs, {\n mode: command.mode,\n relativeTimeUs: command.relativeTimeUs,\n });\n }\n case PlaybackCommandType.MaybeRenderKeyframePreview: {\n return this.orchestrator.tryRenderKeyframe(command.timeUs).then((keyframeTimeUs) => {\n if (!this.isCurrentToken(token)) return;\n if (keyframeTimeUs === null) return;\n return this.orchestrator\n .getRenderState(command.timeUs, {\n mode: 'probe',\n relativeTimeUs: keyframeTimeUs,\n })\n .then((keyframeRenderState) => {\n if (!this.isCurrentToken(token)) return;\n if (!keyframeRenderState) return;\n return this.compose(command.timeUs, keyframeRenderState);\n });\n });\n }\n case PlaybackCommandType.EnsureAudio: {\n return this.audioSession.ensureAudioForTime(command.timeUs, {\n mode: command.mode,\n });\n }\n case PlaybackCommandType.GetFrame: {\n return this.orchestrator.getFrame(command.timeUs, {\n mode: command.mode,\n preheat: command.preheat,\n });\n }\n case PlaybackCommandType.StartAudioPlayback: {\n return this.audioSession.startPlayback(command.timeUs, this.audioContext);\n }\n case PlaybackCommandType.ProbeStartReady: {\n const audioReady = this.audioSession.isPreviewMixBlockCached(command.timeUs);\n const videoReady = this.isVideoResourceReadyAtTime(command.timeUs);\n\n if (audioReady && videoReady) return;\n\n // Kick background preparation (best-effort).\n if (!audioReady) {\n void this.audioSession.ensureAudioForTime(command.timeUs, { mode: 'probe' });\n }\n if (!videoReady) {\n void this.orchestrator.getFrame(command.timeUs, { mode: 'probe' });\n }\n\n // Enter buffering and bump token to cancel the remaining start sequence.\n this.dispatch({\n type: PlaybackActionType.EnterBuffering,\n timeUs: command.timeUs,\n bumpToken: true,\n reason: 'startup',\n });\n return;\n }\n case PlaybackCommandType.StartRafLoop: {\n this.startPlaybackLoop(token);\n return;\n }\n }\n }\n\n private cancelRaf(): void {\n if (this.rafId !== null) {\n cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n }\n\n private isCurrentToken(token: OpToken): boolean {\n return token === this.fsm.snapshot.token;\n }\n\n private startPlaybackLoop(token: OpToken): void {\n this.rafId = requestAnimationFrame(() => {\n void this.onRafTick(token);\n });\n }\n\n private async onRafTick(token: OpToken): Promise<void> {\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n const candidateTimeUs =\n (this.audioContext.currentTime * 1_000_000 - this.startTimeUs) * this.playbackRate;\n this.dispatch({\n type: PlaybackActionType.ClockTick,\n candidateTimeUs,\n durationUs: this.duration,\n loop: this.loop,\n audioNowUs: this.audioContext.currentTime * 1_000_000,\n });\n\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n // Audio probe: if the audio window isn't ready, enter buffering (freeze timeline)\n // and kick background audio preparation.\n // Note: preview audio readiness is driven by 60s mix-block cache inside GlobalAudioSession.\n // We intentionally avoid additional resource-window probing here to prevent buffering oscillation.\n\n // Throttle audio scheduling.\n if (this.currentTimeUs - this.lastAudioScheduleTime >= this.AUDIO_SCHEDULE_INTERVAL) {\n // Fire-and-forget: GlobalAudioSession runs its own background scheduling loop.\n // We avoid awaiting here to keep the render loop responsive.\n void this.audioSession.scheduleAudio(this.currentTimeUs, this.audioContext);\n this.lastAudioScheduleTime = this.currentTimeUs;\n }\n\n // If we're close to the 60s block boundary and the next mixed block isn't ready yet,\n // enter buffering to avoid hard silence at the boundary.\n if (this.audioSession.shouldEnterBufferingForUpcomingPreviewAudio(this.currentTimeUs)) {\n // Best-effort preheat; buffering path will call EnsureAudio(blocking).\n void this.audioSession.ensureAudioForTime(this.currentTimeUs, { mode: 'probe' });\n this.dispatch({\n type: PlaybackActionType.EnterBuffering,\n timeUs: this.currentTimeUs,\n reason: 'audio',\n });\n return;\n }\n\n const renderState = await this.orchestrator.getRenderState(this.currentTimeUs, {\n mode: 'probe',\n });\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n if (!renderState) {\n this.dispatch({ type: PlaybackActionType.EnterBuffering, timeUs: this.currentTimeUs });\n return;\n }\n\n await this.compose(this.currentTimeUs, renderState);\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) return;\n\n this.updateFps();\n this.frameCount++;\n\n // Unified cache window update.\n this.orchestrator.cacheManager.setWindow(this.currentTimeUs);\n\n this.checkAndPreheatWindow();\n if (!this.isCurrentToken(token) || this.fsm.snapshot.state !== PlaybackState.Playing) return;\n\n this.startPlaybackLoop(token);\n }\n\n private updateFps(): void {\n const now = performance.now();\n if (this.lastFrameTime > 0) {\n const deltaTime = now - this.lastFrameTime;\n const instantFps = 1000 / deltaTime;\n this.fps = this.fps > 0 ? this.fps * 0.9 + instantFps * 0.1 : instantFps;\n }\n this.lastFrameTime = now;\n }\n\n private initWindow(timeUs: TimeUs): void {\n this.windowEnd = timeUs + this.WINDOW_DURATION;\n this.preheatInProgress = false;\n this.orchestrator.cacheManager.setWindow(timeUs);\n }\n\n private checkAndPreheatWindow(): void {\n if (this.preheatInProgress || this.fsm.snapshot.state !== PlaybackState.Playing) {\n return;\n }\n\n const distanceToWindowEnd = this.windowEnd - this.currentTimeUs;\n if (distanceToWindowEnd < 0) {\n this.initWindow(this.currentTimeUs);\n return;\n }\n\n if (distanceToWindowEnd > 0 && distanceToWindowEnd <= this.PREHEAT_DISTANCE) {\n void this.preheatNextWindow();\n }\n }\n\n async preheatNextWindow(): Promise<void> {\n if (this.preheatInProgress) return;\n\n this.preheatInProgress = true;\n try {\n const windowStart = this.currentTimeUs;\n const windowEnd = windowStart + this.WINDOW_DURATION;\n\n const clipsInWindow =\n this.orchestrator.compositionModel?.getClipsInRange(windowStart, windowEnd) ?? [];\n const preheatPromises: Promise<any>[] = [];\n\n for (const clip of clipsInWindow) {\n if (!isVideoClip(clip)) continue;\n\n const clipWindowStart = Math.max(0, windowStart - clip.startUs);\n const clipWindowEnd = Math.min(clip.durationUs, windowEnd - clip.startUs);\n if (clipWindowStart >= clipWindowEnd) continue;\n\n preheatPromises.push(\n this.orchestrator.preheatClipWindow(clip.id, clipWindowStart, clipWindowEnd, windowStart)\n );\n }\n\n // Audio preheat is handled inside GlobalAudioSession via mix-block scheduling & cache.\n\n await Promise.all(preheatPromises);\n this.windowEnd = windowEnd;\n } catch (error) {\n console.warn('[PlaybackController] Preheat failed:', error);\n } finally {\n this.preheatInProgress = false;\n }\n }\n\n private async renderCurrentFrame(\n timeUs: TimeUs,\n options: { mode: RequestMode; relativeTimeUs?: TimeUs }\n ): Promise<void> {\n if (!this.videoComposer) {\n console.error('[PlaybackController] VideoComposer not initialized');\n return;\n }\n\n const renderState = await this.orchestrator.getRenderState(timeUs, {\n mode: options.mode,\n relativeTimeUs: options.relativeTimeUs,\n });\n\n if (!renderState) {\n return;\n }\n\n await this.compose(timeUs, renderState);\n }\n\n private async compose(\n timeUs: TimeUs,\n renderState: { layers: any[]; transition?: any }\n ): Promise<void> {\n if (!this.videoComposer) return;\n await this.videoComposer.composeFrame({\n timeUs,\n layers: renderState.layers,\n transition: renderState.transition,\n });\n }\n\n private clearCanvas(): void {\n const ctx = this.canvas.getContext('2d') as\n | CanvasRenderingContext2D\n | OffscreenCanvasRenderingContext2D\n | null;\n if (ctx && 'clearRect' in ctx) {\n ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);\n }\n }\n\n // ========= Cleanup / event handlers =========\n\n dispose(): void {\n this.stop();\n this.eventBus.off(MeframeEvent.CacheCover, this.onCacheCover);\n this.eventBus.off(MeframeEvent.ModelSet, this.onModelSet);\n if (this.videoComposer) {\n this.videoComposer.dispose();\n this.videoComposer = null;\n }\n }\n\n private onCacheCover = (): void => {\n if (this.fsm.snapshot.state === PlaybackState.Idle && this.currentTimeUs === 0) {\n void this.renderCurrentFrame(0, { mode: 'blocking' });\n }\n };\n\n private onModelSet = (): void => {\n if (!this.videoComposer || !this.orchestrator.compositionModel) return;\n\n // Model switching cancels in-flight async chains, but must NOT enter buffering or reset time/state.\n // Buffering runs a long async sequence; if cancelled mid-way it can leave the FSM stuck.\n this.dispatch({ type: PlaybackActionType.ModelSet });\n\n const model = this.orchestrator.compositionModel;\n this.videoComposer.updateConfig({\n width: model.renderConfig?.width || 720,\n height: model.renderConfig?.height || 1280,\n fps: model.fps || 30,\n backgroundColor: model.renderConfig?.backgroundColor || '#000',\n });\n\n // Best-effort background audio preheat (non-blocking).\n void this.audioSession.ensureAudioForTime(this.currentTimeUs, { mode: 'probe' });\n void this.renderCurrentFrame(this.currentTimeUs, { mode: 'blocking' });\n };\n\n private setupEventListeners(): void {\n this.eventBus.on(MeframeEvent.CacheCover, this.onCacheCover);\n this.eventBus.on(MeframeEvent.ModelSet, this.onModelSet);\n }\n\n private isVideoResourceReadyAtTime(timeUs: TimeUs): boolean {\n const model = this.orchestrator.compositionModel;\n if (!model) return true;\n const clip = model.getClipsAtTime(timeUs, model.mainTrackId)[0];\n if (!clip || !('resourceId' in clip) || typeof (clip as any).resourceId !== 'string')\n return true;\n const resourceId = (clip as any).resourceId as string;\n const resource = model.getResource(resourceId);\n return resource?.state === 'ready';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlaybackStateMachine.d.ts","sourceRoot":"","sources":["../../src/controllers/PlaybackStateMachine.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,MAAM,EACZ,MAAM,SAAS,CAAC;AAEjB,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,KAAK,CAAc;IAE3B,IAAI,QAAQ,IAAI,uBAAuB,CAOtC;IAED,QAAQ,CACN,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,GAC7B;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,eAAe,EAAE,CAAA;KAAE;
|
|
1
|
+
{"version":3,"file":"PlaybackStateMachine.d.ts","sourceRoot":"","sources":["../../src/controllers/PlaybackStateMachine.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,MAAM,EACZ,MAAM,SAAS,CAAC;AAEjB,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAAqC;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,KAAK,CAAc;IAE3B,IAAI,QAAQ,IAAI,uBAAuB,CAOtC;IAED,QAAQ,CACN,MAAM,EAAE,cAAc,EACtB,GAAG,EAAE;QAAE,aAAa,EAAE,MAAM,CAAA;KAAE,GAC7B;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,eAAe,EAAE,CAAA;KAAE;CA4WnD"}
|
|
@@ -69,6 +69,7 @@ class PlaybackStateMachine {
|
|
|
69
69
|
type: PlaybackCommandType.Try,
|
|
70
70
|
logPrefix: "[PlaybackController] Failed to start playback:",
|
|
71
71
|
emitPlaybackError: true,
|
|
72
|
+
ignoreWaiterReplacedError: true,
|
|
72
73
|
onError: { type: PlaybackActionType.StartFailed, fallbackState },
|
|
73
74
|
command: {
|
|
74
75
|
type: PlaybackCommandType.Seq,
|
|
@@ -133,6 +134,7 @@ class PlaybackStateMachine {
|
|
|
133
134
|
type: PlaybackCommandType.Try,
|
|
134
135
|
logPrefix: "[PlaybackController] Seek error:",
|
|
135
136
|
emitPlaybackError: true,
|
|
137
|
+
ignoreWaiterReplacedError: true,
|
|
136
138
|
onError: { type: PlaybackActionType.Pause },
|
|
137
139
|
command: {
|
|
138
140
|
type: PlaybackCommandType.Seq,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlaybackStateMachine.js","sources":["../../src/controllers/PlaybackStateMachine.ts"],"sourcesContent":["import { MeframeEvent } from '../event/events';\nimport {\n PlaybackActionType,\n PlaybackCommandType,\n PlaybackState,\n type OpToken,\n type PlaybackAction,\n type PlaybackCommand,\n type PlaybackMachineSnapshot,\n type TimeUs,\n} from './types';\n\nexport class PlaybackStateMachine {\n private state: PlaybackState = PlaybackState.Idle;\n private wantsPlay = false;\n private frozenTimeUs: TimeUs | null = null;\n private token: OpToken = 0;\n\n get snapshot(): PlaybackMachineSnapshot {\n return {\n state: this.state,\n wantsPlay: this.wantsPlay,\n frozenTimeUs: this.frozenTimeUs,\n token: this.token,\n };\n }\n\n dispatch(\n action: PlaybackAction,\n ctx: { currentTimeUs: TimeUs }\n ): { token: OpToken; commands: PlaybackCommand[] } {\n const commands: PlaybackCommand[] = [];\n\n const bumpToken = () => {\n this.token++;\n return this.token;\n };\n\n const setState = (state: PlaybackState) => {\n this.state = state;\n commands.push({ type: PlaybackCommandType.SetState, state });\n };\n\n const setWantsPlay = (wantsPlay: boolean) => {\n this.wantsPlay = wantsPlay;\n commands.push({ type: PlaybackCommandType.SetWantsPlay, wantsPlay });\n };\n\n const setFrozenTime = (timeUs: TimeUs | null) => {\n this.frozenTimeUs = timeUs;\n commands.push({ type: PlaybackCommandType.SetFrozenTime, timeUs });\n };\n\n const setTime = (timeUs: TimeUs) => {\n commands.push({ type: PlaybackCommandType.SetTime, timeUs });\n };\n\n const clampTime = (timeUs: TimeUs, durationUs: TimeUs) => {\n // Timeline point queries are defined on [0, durationUs).\n // Seeking to durationUs would have no active clip and can cause persistent buffering.\n const maxTimeUs = durationUs > 0 ? durationUs - 1 : 0;\n return Math.max(0, Math.min(timeUs, maxTimeUs));\n };\n\n switch (action.type) {\n case PlaybackActionType.ModelSet: {\n bumpToken();\n // Cancel any in-flight async chains and leave the machine in a stable state.\n // Important: do NOT enter buffering here; buffering runs a long async sequence and can be\n // cancelled mid-way, leaving the state stuck in Buffering/Seeking.\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n setFrozenTime(null);\n\n if (\n this.state === PlaybackState.Playing ||\n this.state === PlaybackState.Buffering ||\n this.state === PlaybackState.Seeking\n ) {\n setState(PlaybackState.Paused);\n }\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.Play: {\n const token = bumpToken();\n const prevState = this.state;\n setWantsPlay(true);\n\n if (this.state === PlaybackState.Ended) {\n setTime(0);\n }\n\n if (this.state === PlaybackState.Playing) {\n return { token, commands };\n }\n\n // Set playing immediately; failures will rollback via START_FAILED.\n setState(PlaybackState.Playing);\n setFrozenTime(null);\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({ type: PlaybackCommandType.CancelRaf });\n\n const fallbackState =\n prevState === PlaybackState.Idle || prevState === PlaybackState.Ended\n ? PlaybackState.Idle\n : PlaybackState.Paused;\n\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Failed to start playback:',\n emitPlaybackError: true,\n onError: { type: PlaybackActionType.StartFailed, fallbackState },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.ProbeStartReady, timeUs: ctx.currentTimeUs },\n {\n type: PlaybackCommandType.RenderFrame,\n timeUs: ctx.currentTimeUs,\n mode: 'blocking',\n },\n { type: PlaybackCommandType.InitWindow, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartAudioPlayback, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.SyncTimeBaseToAudioClock, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartRafLoop },\n { type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPlay },\n ],\n },\n });\n return { token, commands };\n }\n\n case PlaybackActionType.Pause: {\n bumpToken();\n const prev = this.state;\n setWantsPlay(false);\n setFrozenTime(null);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n\n if (prev !== PlaybackState.Idle && prev !== PlaybackState.Ended) {\n setState(PlaybackState.Paused);\n }\n\n if (\n prev === PlaybackState.Playing ||\n prev === PlaybackState.Buffering ||\n prev === PlaybackState.Seeking\n ) {\n commands.push({ type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPause });\n }\n\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.Stop: {\n bumpToken();\n setWantsPlay(false);\n setFrozenTime(null);\n setState(PlaybackState.Idle);\n setTime(0);\n\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.ClearCanvas });\n commands.push({ type: PlaybackCommandType.ResetAudioSession });\n commands.push({ type: PlaybackCommandType.ResetAudioPlaybackStates });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({ type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackStop });\n\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.Seek: {\n const token = bumpToken();\n const previousState = this.state;\n const toUs = clampTime(action.timeUs, action.durationUs);\n\n setTime(toUs);\n setFrozenTime(toUs);\n setState(PlaybackState.Seeking);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Seek error:',\n emitPlaybackError: true,\n onError: { type: PlaybackActionType.Pause },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.MaybeRenderKeyframePreview, timeUs: toUs },\n {\n type: PlaybackCommandType.Par,\n commands: [\n { type: PlaybackCommandType.EnsureAudio, timeUs: toUs, mode: 'blocking' },\n {\n type: PlaybackCommandType.GetFrame,\n timeUs: toUs,\n mode: 'blocking',\n preheat: true,\n },\n ],\n },\n { type: PlaybackCommandType.InitWindow, timeUs: toUs },\n { type: PlaybackCommandType.RenderFrame, timeUs: toUs, mode: 'blocking' },\n {\n type: PlaybackCommandType.Dispatch,\n action: { type: PlaybackActionType.SeekResolved, previousState },\n },\n ],\n },\n });\n\n return { token, commands };\n }\n\n case PlaybackActionType.EnterBuffering: {\n const shouldBump = action.bumpToken ?? false;\n if (shouldBump) {\n bumpToken();\n }\n if (this.state !== PlaybackState.Playing) {\n return { token: this.token, commands };\n }\n // Do NOT bump token; buffering is part of the current playback operation.\n setFrozenTime(action.timeUs);\n setState(PlaybackState.Buffering);\n commands.push({ type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackBuffering });\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Buffering error:',\n emitPlaybackError: true,\n ignoreWaiterReplacedError: true,\n onError: { type: PlaybackActionType.Pause },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.SetCacheWindow, timeUs: action.timeUs },\n {\n type: PlaybackCommandType.Par,\n commands: [\n { type: PlaybackCommandType.GetFrame, timeUs: action.timeUs, mode: 'blocking' },\n {\n type: PlaybackCommandType.EnsureAudio,\n timeUs: action.timeUs,\n mode: 'blocking',\n },\n ],\n },\n {\n type: PlaybackCommandType.Dispatch,\n action: { type: PlaybackActionType.BufferingResolved, timeUs: action.timeUs },\n },\n ],\n },\n });\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.BufferingResolved: {\n if (this.state !== PlaybackState.Buffering) {\n return { token: this.token, commands };\n }\n setFrozenTime(null);\n if (this.wantsPlay) {\n setState(PlaybackState.Playing);\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Failed to start playback:',\n emitPlaybackError: true,\n onError: { type: PlaybackActionType.StartFailed, fallbackState: PlaybackState.Paused },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.RenderFrame, timeUs: action.timeUs, mode: 'blocking' },\n { type: PlaybackCommandType.InitWindow, timeUs: action.timeUs },\n { type: PlaybackCommandType.StartAudioPlayback, timeUs: action.timeUs },\n { type: PlaybackCommandType.SyncTimeBaseToAudioClock, timeUs: action.timeUs },\n { type: PlaybackCommandType.StartRafLoop },\n { type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPlay },\n ],\n },\n });\n } else {\n setState(PlaybackState.Paused);\n }\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.SeekResolved: {\n if (this.state !== PlaybackState.Seeking) {\n return { token: this.token, commands };\n }\n setFrozenTime(null);\n commands.push({\n type: PlaybackCommandType.Emit,\n event: MeframeEvent.PlaybackSeek,\n payload: { timeUs: ctx.currentTimeUs },\n });\n if (this.wantsPlay) {\n setState(PlaybackState.Playing);\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Failed to start playback:',\n emitPlaybackError: true,\n onError: { type: PlaybackActionType.StartFailed, fallbackState: PlaybackState.Paused },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n {\n type: PlaybackCommandType.RenderFrame,\n timeUs: ctx.currentTimeUs,\n mode: 'blocking',\n },\n { type: PlaybackCommandType.InitWindow, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartAudioPlayback, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.SyncTimeBaseToAudioClock, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartRafLoop },\n { type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPlay },\n ],\n },\n });\n } else {\n setState(\n action.previousState === PlaybackState.Idle ? PlaybackState.Idle : PlaybackState.Paused\n );\n }\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.StartFailed: {\n // Startup failed: leave a stable non-playing state and clear intent.\n setWantsPlay(false);\n setFrozenTime(null);\n setState(action.fallbackState);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.ClockTick: {\n if (this.state !== PlaybackState.Playing) {\n return { token: this.token, commands };\n }\n if (this.frozenTimeUs !== null) {\n return { token: this.token, commands };\n }\n\n const t = action.candidateTimeUs;\n\n if (t >= action.durationUs) {\n if (action.loop) {\n setTime(0);\n commands.push({\n type: PlaybackCommandType.SetStartTimeBase,\n startTimeUs: action.audioNowUs,\n });\n commands.push({ type: PlaybackCommandType.ResetAudioPlaybackStates });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({ type: PlaybackCommandType.InitWindow, timeUs: 0 });\n } else {\n setWantsPlay(false);\n setState(PlaybackState.Ended);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n setTime(0);\n commands.push({\n type: PlaybackCommandType.Emit,\n event: MeframeEvent.PlaybackEnded,\n payload: { timeUs: action.durationUs },\n });\n }\n return { token: this.token, commands };\n }\n\n setTime(t);\n commands.push({\n type: PlaybackCommandType.Emit,\n event: MeframeEvent.PlaybackTimeUpdate,\n payload: { timeUs: t },\n });\n return { token: this.token, commands };\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlaybackStateMachine.js","sources":["../../src/controllers/PlaybackStateMachine.ts"],"sourcesContent":["import { MeframeEvent } from '../event/events';\nimport {\n PlaybackActionType,\n PlaybackCommandType,\n PlaybackState,\n type OpToken,\n type PlaybackAction,\n type PlaybackCommand,\n type PlaybackMachineSnapshot,\n type TimeUs,\n} from './types';\n\nexport class PlaybackStateMachine {\n private state: PlaybackState = PlaybackState.Idle;\n private wantsPlay = false;\n private frozenTimeUs: TimeUs | null = null;\n private token: OpToken = 0;\n\n get snapshot(): PlaybackMachineSnapshot {\n return {\n state: this.state,\n wantsPlay: this.wantsPlay,\n frozenTimeUs: this.frozenTimeUs,\n token: this.token,\n };\n }\n\n dispatch(\n action: PlaybackAction,\n ctx: { currentTimeUs: TimeUs }\n ): { token: OpToken; commands: PlaybackCommand[] } {\n const commands: PlaybackCommand[] = [];\n\n const bumpToken = () => {\n this.token++;\n return this.token;\n };\n\n const setState = (state: PlaybackState) => {\n this.state = state;\n commands.push({ type: PlaybackCommandType.SetState, state });\n };\n\n const setWantsPlay = (wantsPlay: boolean) => {\n this.wantsPlay = wantsPlay;\n commands.push({ type: PlaybackCommandType.SetWantsPlay, wantsPlay });\n };\n\n const setFrozenTime = (timeUs: TimeUs | null) => {\n this.frozenTimeUs = timeUs;\n commands.push({ type: PlaybackCommandType.SetFrozenTime, timeUs });\n };\n\n const setTime = (timeUs: TimeUs) => {\n commands.push({ type: PlaybackCommandType.SetTime, timeUs });\n };\n\n const clampTime = (timeUs: TimeUs, durationUs: TimeUs) => {\n // Timeline point queries are defined on [0, durationUs).\n // Seeking to durationUs would have no active clip and can cause persistent buffering.\n const maxTimeUs = durationUs > 0 ? durationUs - 1 : 0;\n return Math.max(0, Math.min(timeUs, maxTimeUs));\n };\n\n switch (action.type) {\n case PlaybackActionType.ModelSet: {\n bumpToken();\n // Cancel any in-flight async chains and leave the machine in a stable state.\n // Important: do NOT enter buffering here; buffering runs a long async sequence and can be\n // cancelled mid-way, leaving the state stuck in Buffering/Seeking.\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n setFrozenTime(null);\n\n if (\n this.state === PlaybackState.Playing ||\n this.state === PlaybackState.Buffering ||\n this.state === PlaybackState.Seeking\n ) {\n setState(PlaybackState.Paused);\n }\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.Play: {\n const token = bumpToken();\n const prevState = this.state;\n setWantsPlay(true);\n\n if (this.state === PlaybackState.Ended) {\n setTime(0);\n }\n\n if (this.state === PlaybackState.Playing) {\n return { token, commands };\n }\n\n // Set playing immediately; failures will rollback via START_FAILED.\n setState(PlaybackState.Playing);\n setFrozenTime(null);\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({ type: PlaybackCommandType.CancelRaf });\n\n const fallbackState =\n prevState === PlaybackState.Idle || prevState === PlaybackState.Ended\n ? PlaybackState.Idle\n : PlaybackState.Paused;\n\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Failed to start playback:',\n emitPlaybackError: true,\n ignoreWaiterReplacedError: true,\n onError: { type: PlaybackActionType.StartFailed, fallbackState },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.ProbeStartReady, timeUs: ctx.currentTimeUs },\n {\n type: PlaybackCommandType.RenderFrame,\n timeUs: ctx.currentTimeUs,\n mode: 'blocking',\n },\n { type: PlaybackCommandType.InitWindow, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartAudioPlayback, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.SyncTimeBaseToAudioClock, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartRafLoop },\n { type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPlay },\n ],\n },\n });\n return { token, commands };\n }\n\n case PlaybackActionType.Pause: {\n bumpToken();\n const prev = this.state;\n setWantsPlay(false);\n setFrozenTime(null);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n\n if (prev !== PlaybackState.Idle && prev !== PlaybackState.Ended) {\n setState(PlaybackState.Paused);\n }\n\n if (\n prev === PlaybackState.Playing ||\n prev === PlaybackState.Buffering ||\n prev === PlaybackState.Seeking\n ) {\n commands.push({ type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPause });\n }\n\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.Stop: {\n bumpToken();\n setWantsPlay(false);\n setFrozenTime(null);\n setState(PlaybackState.Idle);\n setTime(0);\n\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.ClearCanvas });\n commands.push({ type: PlaybackCommandType.ResetAudioSession });\n commands.push({ type: PlaybackCommandType.ResetAudioPlaybackStates });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({ type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackStop });\n\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.Seek: {\n const token = bumpToken();\n const previousState = this.state;\n const toUs = clampTime(action.timeUs, action.durationUs);\n\n setTime(toUs);\n setFrozenTime(toUs);\n setState(PlaybackState.Seeking);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Seek error:',\n emitPlaybackError: true,\n ignoreWaiterReplacedError: true,\n onError: { type: PlaybackActionType.Pause },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.MaybeRenderKeyframePreview, timeUs: toUs },\n {\n type: PlaybackCommandType.Par,\n commands: [\n { type: PlaybackCommandType.EnsureAudio, timeUs: toUs, mode: 'blocking' },\n {\n type: PlaybackCommandType.GetFrame,\n timeUs: toUs,\n mode: 'blocking',\n preheat: true,\n },\n ],\n },\n { type: PlaybackCommandType.InitWindow, timeUs: toUs },\n { type: PlaybackCommandType.RenderFrame, timeUs: toUs, mode: 'blocking' },\n {\n type: PlaybackCommandType.Dispatch,\n action: { type: PlaybackActionType.SeekResolved, previousState },\n },\n ],\n },\n });\n\n return { token, commands };\n }\n\n case PlaybackActionType.EnterBuffering: {\n const shouldBump = action.bumpToken ?? false;\n if (shouldBump) {\n bumpToken();\n }\n if (this.state !== PlaybackState.Playing) {\n return { token: this.token, commands };\n }\n // Do NOT bump token; buffering is part of the current playback operation.\n setFrozenTime(action.timeUs);\n setState(PlaybackState.Buffering);\n commands.push({ type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackBuffering });\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Buffering error:',\n emitPlaybackError: true,\n ignoreWaiterReplacedError: true,\n onError: { type: PlaybackActionType.Pause },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.SetCacheWindow, timeUs: action.timeUs },\n {\n type: PlaybackCommandType.Par,\n commands: [\n { type: PlaybackCommandType.GetFrame, timeUs: action.timeUs, mode: 'blocking' },\n {\n type: PlaybackCommandType.EnsureAudio,\n timeUs: action.timeUs,\n mode: 'blocking',\n },\n ],\n },\n {\n type: PlaybackCommandType.Dispatch,\n action: { type: PlaybackActionType.BufferingResolved, timeUs: action.timeUs },\n },\n ],\n },\n });\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.BufferingResolved: {\n if (this.state !== PlaybackState.Buffering) {\n return { token: this.token, commands };\n }\n setFrozenTime(null);\n if (this.wantsPlay) {\n setState(PlaybackState.Playing);\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Failed to start playback:',\n emitPlaybackError: true,\n onError: { type: PlaybackActionType.StartFailed, fallbackState: PlaybackState.Paused },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n { type: PlaybackCommandType.RenderFrame, timeUs: action.timeUs, mode: 'blocking' },\n { type: PlaybackCommandType.InitWindow, timeUs: action.timeUs },\n { type: PlaybackCommandType.StartAudioPlayback, timeUs: action.timeUs },\n { type: PlaybackCommandType.SyncTimeBaseToAudioClock, timeUs: action.timeUs },\n { type: PlaybackCommandType.StartRafLoop },\n { type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPlay },\n ],\n },\n });\n } else {\n setState(PlaybackState.Paused);\n }\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.SeekResolved: {\n if (this.state !== PlaybackState.Seeking) {\n return { token: this.token, commands };\n }\n setFrozenTime(null);\n commands.push({\n type: PlaybackCommandType.Emit,\n event: MeframeEvent.PlaybackSeek,\n payload: { timeUs: ctx.currentTimeUs },\n });\n if (this.wantsPlay) {\n setState(PlaybackState.Playing);\n commands.push({\n type: PlaybackCommandType.Try,\n logPrefix: '[PlaybackController] Failed to start playback:',\n emitPlaybackError: true,\n onError: { type: PlaybackActionType.StartFailed, fallbackState: PlaybackState.Paused },\n command: {\n type: PlaybackCommandType.Seq,\n commands: [\n {\n type: PlaybackCommandType.RenderFrame,\n timeUs: ctx.currentTimeUs,\n mode: 'blocking',\n },\n { type: PlaybackCommandType.InitWindow, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartAudioPlayback, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.SyncTimeBaseToAudioClock, timeUs: ctx.currentTimeUs },\n { type: PlaybackCommandType.StartRafLoop },\n { type: PlaybackCommandType.Emit, event: MeframeEvent.PlaybackPlay },\n ],\n },\n });\n } else {\n setState(\n action.previousState === PlaybackState.Idle ? PlaybackState.Idle : PlaybackState.Paused\n );\n }\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.StartFailed: {\n // Startup failed: leave a stable non-playing state and clear intent.\n setWantsPlay(false);\n setFrozenTime(null);\n setState(action.fallbackState);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n return { token: this.token, commands };\n }\n\n case PlaybackActionType.ClockTick: {\n if (this.state !== PlaybackState.Playing) {\n return { token: this.token, commands };\n }\n if (this.frozenTimeUs !== null) {\n return { token: this.token, commands };\n }\n\n const t = action.candidateTimeUs;\n\n if (t >= action.durationUs) {\n if (action.loop) {\n setTime(0);\n commands.push({\n type: PlaybackCommandType.SetStartTimeBase,\n startTimeUs: action.audioNowUs,\n });\n commands.push({ type: PlaybackCommandType.ResetAudioPlaybackStates });\n commands.push({ type: PlaybackCommandType.SetLastAudioScheduleTime, timeUs: 0 });\n commands.push({ type: PlaybackCommandType.InitWindow, timeUs: 0 });\n } else {\n setWantsPlay(false);\n setState(PlaybackState.Ended);\n commands.push({ type: PlaybackCommandType.CancelRaf });\n commands.push({ type: PlaybackCommandType.StopAudio });\n setTime(0);\n commands.push({\n type: PlaybackCommandType.Emit,\n event: MeframeEvent.PlaybackEnded,\n payload: { timeUs: action.durationUs },\n });\n }\n return { token: this.token, commands };\n }\n\n setTime(t);\n commands.push({\n type: PlaybackCommandType.Emit,\n event: MeframeEvent.PlaybackTimeUpdate,\n payload: { timeUs: t },\n });\n return { token: this.token, commands };\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -29,17 +29,31 @@ export declare class GlobalAudioSession {
|
|
|
29
29
|
private volume;
|
|
30
30
|
private playbackRate;
|
|
31
31
|
private isPlaying;
|
|
32
|
-
private
|
|
33
|
-
private
|
|
34
|
-
private
|
|
35
|
-
private readonly
|
|
36
|
-
private readonly
|
|
32
|
+
private readonly PREVIEW_BLOCK_DURATION_US;
|
|
33
|
+
private readonly PREVIEW_BLOCK_CACHE_SIZE;
|
|
34
|
+
private readonly PREVIEW_SCHEDULE_AHEAD_SEC;
|
|
35
|
+
private readonly PREVIEW_BUFFER_GUARD_US;
|
|
36
|
+
private readonly PREVIEW_BLOCK_FADE_SEC;
|
|
37
|
+
private previewBlockCache;
|
|
38
|
+
private previewScheduleTask;
|
|
39
|
+
private previewScheduleToken;
|
|
40
|
+
private previewMixToken;
|
|
41
|
+
private previewNextBlockIndex;
|
|
42
|
+
private previewNextScheduleTime;
|
|
43
|
+
private previewFirstBlockOffsetUs;
|
|
44
|
+
private previewLastTimelineUs;
|
|
45
|
+
private previewLastStallWarnAt;
|
|
46
|
+
private previewScheduledSources;
|
|
47
|
+
private previewMixQueue;
|
|
37
48
|
constructor(deps: AudioSessionDeps);
|
|
49
|
+
private enqueuePreviewMix;
|
|
38
50
|
setModel(model: CompositionModel): void;
|
|
39
51
|
onAudioData(message: AudioDataMessage): void;
|
|
40
52
|
ensureAudioForTime(timeUs: TimeUs, options?: {
|
|
41
53
|
mode?: RequestMode;
|
|
42
54
|
}): Promise<void>;
|
|
55
|
+
isPreviewMixBlockCached(timeUs: TimeUs): boolean;
|
|
56
|
+
shouldEnterBufferingForUpcomingPreviewAudio(timeUs: TimeUs): boolean;
|
|
43
57
|
/**
|
|
44
58
|
* Fast readiness probe for preview playback.
|
|
45
59
|
*
|
|
@@ -68,6 +82,13 @@ export declare class GlobalAudioSession {
|
|
|
68
82
|
resetPlaybackStates(): void;
|
|
69
83
|
setVolume(volume: number): void;
|
|
70
84
|
setPlaybackRate(rate: number): void;
|
|
85
|
+
private startPreviewBlockScheduling;
|
|
86
|
+
private cancelPreviewBlockScheduling;
|
|
87
|
+
private realignPreviewSchedulingToTimeline;
|
|
88
|
+
private runPreviewBlockSchedulingLoop;
|
|
89
|
+
private getOrCreateMixedBlock;
|
|
90
|
+
private scheduleNextPreviewBlock;
|
|
91
|
+
private stopAllPreviewSources;
|
|
71
92
|
reset(): void;
|
|
72
93
|
/**
|
|
73
94
|
* Mix and encode audio for a specific segment (used by ExportScheduler)
|
|
@@ -83,7 +104,6 @@ export declare class GlobalAudioSession {
|
|
|
83
104
|
private exportEncoderWriter;
|
|
84
105
|
private startExportEncoderReader;
|
|
85
106
|
finalizeExportAudio(): Promise<void>;
|
|
86
|
-
private stopAllAudioSources;
|
|
87
107
|
/**
|
|
88
108
|
* Core method to ensure audio for all clips in a time range
|
|
89
109
|
* Unified implementation used by ensureAudioForTime, scheduleAudio, and export
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalAudioSession.d.ts","sourceRoot":"","sources":["../../src/orchestrator/GlobalAudioSession.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"GlobalAudioSession.d.ts","sourceRoot":"","sources":["../../src/orchestrator/GlobalAudioSession.ts"],"names":[],"mappings":"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"}
|