@meframe/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/LICENSE +22 -0
- package/README.md +396 -0
- package/dist/Meframe.d.ts +82 -0
- package/dist/Meframe.d.ts.map +1 -0
- package/dist/Meframe.js +290 -0
- package/dist/Meframe.js.map +1 -0
- package/dist/_virtual/mp4box.all.js +5 -0
- package/dist/_virtual/mp4box.all.js.map +1 -0
- package/dist/cache/BatchWriter.d.ts +25 -0
- package/dist/cache/BatchWriter.d.ts.map +1 -0
- package/dist/cache/CacheManager.d.ts +115 -0
- package/dist/cache/CacheManager.d.ts.map +1 -0
- package/dist/cache/CacheManager.js +388 -0
- package/dist/cache/CacheManager.js.map +1 -0
- package/dist/cache/CacheStatsDecorator.d.ts +27 -0
- package/dist/cache/CacheStatsDecorator.d.ts.map +1 -0
- package/dist/cache/L2Cache.d.ts +39 -0
- package/dist/cache/L2Cache.d.ts.map +1 -0
- package/dist/cache/L2Cache.js +282 -0
- package/dist/cache/L2Cache.js.map +1 -0
- package/dist/cache/index.d.ts +7 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/l1/AudioL1Cache.d.ts +30 -0
- package/dist/cache/l1/AudioL1Cache.d.ts.map +1 -0
- package/dist/cache/l1/AudioL1Cache.js +306 -0
- package/dist/cache/l1/AudioL1Cache.js.map +1 -0
- package/dist/cache/l1/MixedAudioL1Cache.d.ts +13 -0
- package/dist/cache/l1/MixedAudioL1Cache.d.ts.map +1 -0
- package/dist/cache/l1/MixedAudioL1Cache.js +52 -0
- package/dist/cache/l1/MixedAudioL1Cache.js.map +1 -0
- package/dist/cache/l1/VideoL1Cache.d.ts +69 -0
- package/dist/cache/l1/VideoL1Cache.d.ts.map +1 -0
- package/dist/cache/l1/VideoL1Cache.js +318 -0
- package/dist/cache/l1/VideoL1Cache.js.map +1 -0
- package/dist/cache/l1/gop-utils.d.ts +10 -0
- package/dist/cache/l1/gop-utils.d.ts.map +1 -0
- package/dist/cache/l1/gop-utils.js +78 -0
- package/dist/cache/l1/gop-utils.js.map +1 -0
- package/dist/cache/l1/index.d.ts +4 -0
- package/dist/cache/l1/index.d.ts.map +1 -0
- package/dist/cache/l1/types.d.ts +17 -0
- package/dist/cache/l1/types.d.ts.map +1 -0
- package/dist/cache/types.d.ts +93 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/config/ConfigLoader.d.ts +69 -0
- package/dist/config/ConfigLoader.d.ts.map +1 -0
- package/dist/config/ConfigLoader.js +133 -0
- package/dist/config/ConfigLoader.js.map +1 -0
- package/dist/config/defaults.d.ts +125 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +191 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +6 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/presets.d.ts +32 -0
- package/dist/config/presets.d.ts.map +1 -0
- package/dist/config/presets.js +11 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/types.d.ts +199 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/validation.d.ts +19 -0
- package/dist/config/validation.d.ts.map +1 -0
- package/dist/config/validation.js +232 -0
- package/dist/config/validation.js.map +1 -0
- package/dist/controllers/PlaybackController.d.ts +55 -0
- package/dist/controllers/PlaybackController.d.ts.map +1 -0
- package/dist/controllers/PlaybackController.js +369 -0
- package/dist/controllers/PlaybackController.js.map +1 -0
- package/dist/controllers/PreRenderService.d.ts +34 -0
- package/dist/controllers/PreRenderService.d.ts.map +1 -0
- package/dist/controllers/PreRenderService.js +83 -0
- package/dist/controllers/PreRenderService.js.map +1 -0
- package/dist/controllers/PreRenderTaskQueue.d.ts +21 -0
- package/dist/controllers/PreRenderTaskQueue.d.ts.map +1 -0
- package/dist/controllers/PreviewHandle.d.ts +23 -0
- package/dist/controllers/PreviewHandle.d.ts.map +1 -0
- package/dist/controllers/PreviewHandle.js +39 -0
- package/dist/controllers/PreviewHandle.js.map +1 -0
- package/dist/controllers/index.d.ts +8 -0
- package/dist/controllers/index.d.ts.map +1 -0
- package/dist/controllers/types.d.ts +102 -0
- package/dist/controllers/types.d.ts.map +1 -0
- package/dist/event/EventBus.d.ts +42 -0
- package/dist/event/EventBus.d.ts.map +1 -0
- package/dist/event/EventBus.js +94 -0
- package/dist/event/EventBus.js.map +1 -0
- package/dist/event/events.d.ts +371 -0
- package/dist/event/events.d.ts.map +1 -0
- package/dist/event/events.js +71 -0
- package/dist/event/events.js.map +1 -0
- package/dist/event/index.d.ts +4 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/model/CompositionModel.d.ts +48 -0
- package/dist/model/CompositionModel.d.ts.map +1 -0
- package/dist/model/CompositionModel.js +197 -0
- package/dist/model/CompositionModel.js.map +1 -0
- package/dist/model/RcFrame.d.ts +34 -0
- package/dist/model/RcFrame.d.ts.map +1 -0
- package/dist/model/RcFrame.js +97 -0
- package/dist/model/RcFrame.js.map +1 -0
- package/dist/model/dirty-range.d.ts +5 -0
- package/dist/model/dirty-range.d.ts.map +1 -0
- package/dist/model/dirty-range.js +220 -0
- package/dist/model/dirty-range.js.map +1 -0
- package/dist/model/index.d.ts +7 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/patch.d.ts +5 -0
- package/dist/model/patch.d.ts.map +1 -0
- package/dist/model/patch.js +250 -0
- package/dist/model/patch.js.map +1 -0
- package/dist/model/types.d.ts +135 -0
- package/dist/model/types.d.ts.map +1 -0
- package/dist/model/types.js +5 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/validation.d.ts +15 -0
- package/dist/model/validation.d.ts.map +1 -0
- package/dist/model/validation.js +74 -0
- package/dist/model/validation.js.map +1 -0
- package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js +7046 -0
- package/dist/node_modules/.pnpm/mp4box@0.5.4/node_modules/mp4box/dist/mp4box.all.js.map +1 -0
- package/dist/orchestrator/ClipSessionManager.d.ts +75 -0
- package/dist/orchestrator/ClipSessionManager.d.ts.map +1 -0
- package/dist/orchestrator/ClipSessionManager.js +160 -0
- package/dist/orchestrator/ClipSessionManager.js.map +1 -0
- package/dist/orchestrator/CompositionPlanner.d.ts +55 -0
- package/dist/orchestrator/CompositionPlanner.d.ts.map +1 -0
- package/dist/orchestrator/CompositionPlanner.js +411 -0
- package/dist/orchestrator/CompositionPlanner.js.map +1 -0
- package/dist/orchestrator/Orchestrator.d.ts +59 -0
- package/dist/orchestrator/Orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/Orchestrator.js +390 -0
- package/dist/orchestrator/Orchestrator.js.map +1 -0
- package/dist/orchestrator/VideoClipSession.d.ts +64 -0
- package/dist/orchestrator/VideoClipSession.d.ts.map +1 -0
- package/dist/orchestrator/VideoClipSession.js +309 -0
- package/dist/orchestrator/VideoClipSession.js.map +1 -0
- package/dist/orchestrator/index.d.ts +5 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/types.d.ts +64 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/plugins/BackpressureMonitor.d.ts +33 -0
- package/dist/plugins/BackpressureMonitor.d.ts.map +1 -0
- package/dist/plugins/BackpressureMonitor.js +62 -0
- package/dist/plugins/BackpressureMonitor.js.map +1 -0
- package/dist/plugins/PluginManager.d.ts +37 -0
- package/dist/plugins/PluginManager.d.ts.map +1 -0
- package/dist/plugins/PluginManager.js +66 -0
- package/dist/plugins/PluginManager.js.map +1 -0
- package/dist/plugins/types.d.ts +60 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/stages/compose/AudioDucker.d.ts +59 -0
- package/dist/stages/compose/AudioDucker.d.ts.map +1 -0
- package/dist/stages/compose/AudioDucker.js +161 -0
- package/dist/stages/compose/AudioDucker.js.map +1 -0
- package/dist/stages/compose/AudioMixer.d.ts +29 -0
- package/dist/stages/compose/AudioMixer.d.ts.map +1 -0
- package/dist/stages/compose/AudioMixer.js +373 -0
- package/dist/stages/compose/AudioMixer.js.map +1 -0
- package/dist/stages/compose/FilterProcessor.d.ts +41 -0
- package/dist/stages/compose/FilterProcessor.d.ts.map +1 -0
- package/dist/stages/compose/FilterProcessor.js +226 -0
- package/dist/stages/compose/FilterProcessor.js.map +1 -0
- package/dist/stages/compose/GlobalAudioSession.d.ts +38 -0
- package/dist/stages/compose/GlobalAudioSession.d.ts.map +1 -0
- package/dist/stages/compose/GlobalAudioSession.js +122 -0
- package/dist/stages/compose/GlobalAudioSession.js.map +1 -0
- package/dist/stages/compose/LayerRenderer.d.ts +30 -0
- package/dist/stages/compose/LayerRenderer.d.ts.map +1 -0
- package/dist/stages/compose/LayerRenderer.js +215 -0
- package/dist/stages/compose/LayerRenderer.js.map +1 -0
- package/dist/stages/compose/OfflineAudioMixer.d.ts +14 -0
- package/dist/stages/compose/OfflineAudioMixer.d.ts.map +1 -0
- package/dist/stages/compose/OfflineAudioMixer.js +68 -0
- package/dist/stages/compose/OfflineAudioMixer.js.map +1 -0
- package/dist/stages/compose/TransitionProcessor.d.ts +30 -0
- package/dist/stages/compose/TransitionProcessor.d.ts.map +1 -0
- package/dist/stages/compose/TransitionProcessor.js +189 -0
- package/dist/stages/compose/TransitionProcessor.js.map +1 -0
- package/dist/stages/compose/VideoComposer.d.ts +30 -0
- package/dist/stages/compose/VideoComposer.d.ts.map +1 -0
- package/dist/stages/compose/VideoComposer.js +186 -0
- package/dist/stages/compose/VideoComposer.js.map +1 -0
- package/dist/stages/compose/audio-compose.worker.d.ts +79 -0
- package/dist/stages/compose/audio-compose.worker.d.ts.map +1 -0
- package/dist/stages/compose/audio-compose.worker.js +541 -0
- package/dist/stages/compose/audio-compose.worker.js.map +1 -0
- package/dist/stages/compose/instructions.d.ts +95 -0
- package/dist/stages/compose/instructions.d.ts.map +1 -0
- package/dist/stages/compose/types.d.ts +245 -0
- package/dist/stages/compose/types.d.ts.map +1 -0
- package/dist/stages/compose/video-compose.worker.d.ts +60 -0
- package/dist/stages/compose/video-compose.worker.d.ts.map +1 -0
- package/dist/stages/compose/video-compose.worker.js +369 -0
- package/dist/stages/compose/video-compose.worker.js.map +1 -0
- package/dist/stages/decode/AudioChunkDecoder.d.ts +41 -0
- package/dist/stages/decode/AudioChunkDecoder.d.ts.map +1 -0
- package/dist/stages/decode/AudioChunkDecoder.js +83 -0
- package/dist/stages/decode/AudioChunkDecoder.js.map +1 -0
- package/dist/stages/decode/BaseDecoder.d.ts +35 -0
- package/dist/stages/decode/BaseDecoder.d.ts.map +1 -0
- package/dist/stages/decode/BaseDecoder.js +130 -0
- package/dist/stages/decode/BaseDecoder.js.map +1 -0
- package/dist/stages/decode/VideoChunkDecoder.d.ts +54 -0
- package/dist/stages/decode/VideoChunkDecoder.d.ts.map +1 -0
- package/dist/stages/decode/VideoChunkDecoder.js +209 -0
- package/dist/stages/decode/VideoChunkDecoder.js.map +1 -0
- package/dist/stages/decode/decode.worker.d.ts +70 -0
- package/dist/stages/decode/decode.worker.d.ts.map +1 -0
- package/dist/stages/decode/decode.worker.js +436 -0
- package/dist/stages/decode/decode.worker.js.map +1 -0
- package/dist/stages/decode/index.d.ts +5 -0
- package/dist/stages/decode/index.d.ts.map +1 -0
- package/dist/stages/decode/types.d.ts +108 -0
- package/dist/stages/decode/types.d.ts.map +1 -0
- package/dist/stages/demux/MP3FrameParser.d.ts +33 -0
- package/dist/stages/demux/MP3FrameParser.d.ts.map +1 -0
- package/dist/stages/demux/MP3FrameParser.js +186 -0
- package/dist/stages/demux/MP3FrameParser.js.map +1 -0
- package/dist/stages/demux/MP4Demuxer.d.ts +45 -0
- package/dist/stages/demux/MP4Demuxer.d.ts.map +1 -0
- package/dist/stages/demux/MP4Demuxer.js +227 -0
- package/dist/stages/demux/MP4Demuxer.js.map +1 -0
- package/dist/stages/demux/aac-esds-extractor.d.ts +7 -0
- package/dist/stages/demux/aac-esds-extractor.d.ts.map +1 -0
- package/dist/stages/demux/audio-demux.worker.d.ts +51 -0
- package/dist/stages/demux/audio-demux.worker.d.ts.map +1 -0
- package/dist/stages/demux/audio-demux.worker.js +312 -0
- package/dist/stages/demux/audio-demux.worker.js.map +1 -0
- package/dist/stages/demux/types.d.ts +77 -0
- package/dist/stages/demux/types.d.ts.map +1 -0
- package/dist/stages/demux/video-demux.worker.d.ts +48 -0
- package/dist/stages/demux/video-demux.worker.d.ts.map +1 -0
- package/dist/stages/demux/video-demux.worker.js +173 -0
- package/dist/stages/demux/video-demux.worker.js.map +1 -0
- package/dist/stages/encode/AudioChunkEncoder.d.ts +21 -0
- package/dist/stages/encode/AudioChunkEncoder.d.ts.map +1 -0
- package/dist/stages/encode/AudioChunkEncoder.js +37 -0
- package/dist/stages/encode/AudioChunkEncoder.js.map +1 -0
- package/dist/stages/encode/BaseEncoder.d.ts +44 -0
- package/dist/stages/encode/BaseEncoder.d.ts.map +1 -0
- package/dist/stages/encode/BaseEncoder.js +164 -0
- package/dist/stages/encode/BaseEncoder.js.map +1 -0
- package/dist/stages/encode/EncoderPool.d.ts +28 -0
- package/dist/stages/encode/EncoderPool.d.ts.map +1 -0
- package/dist/stages/encode/VideoChunkEncoder.d.ts +26 -0
- package/dist/stages/encode/VideoChunkEncoder.d.ts.map +1 -0
- package/dist/stages/encode/VideoChunkEncoder.js +50 -0
- package/dist/stages/encode/VideoChunkEncoder.js.map +1 -0
- package/dist/stages/encode/encode.worker.d.ts +3 -0
- package/dist/stages/encode/encode.worker.d.ts.map +1 -0
- package/dist/stages/encode/encode.worker.js +318 -0
- package/dist/stages/encode/encode.worker.js.map +1 -0
- package/dist/stages/encode/index.d.ts +6 -0
- package/dist/stages/encode/index.d.ts.map +1 -0
- package/dist/stages/encode/types.d.ts +127 -0
- package/dist/stages/encode/types.d.ts.map +1 -0
- package/dist/stages/load/EventHandlers.d.ts +35 -0
- package/dist/stages/load/EventHandlers.d.ts.map +1 -0
- package/dist/stages/load/EventHandlers.js +65 -0
- package/dist/stages/load/EventHandlers.js.map +1 -0
- package/dist/stages/load/ResourceLoader.d.ts +36 -0
- package/dist/stages/load/ResourceLoader.d.ts.map +1 -0
- package/dist/stages/load/ResourceLoader.js +184 -0
- package/dist/stages/load/ResourceLoader.js.map +1 -0
- package/dist/stages/load/StreamFactory.d.ts +42 -0
- package/dist/stages/load/StreamFactory.d.ts.map +1 -0
- package/dist/stages/load/StreamFactory.js +201 -0
- package/dist/stages/load/StreamFactory.js.map +1 -0
- package/dist/stages/load/TaskManager.d.ts +50 -0
- package/dist/stages/load/TaskManager.d.ts.map +1 -0
- package/dist/stages/load/TaskManager.js +103 -0
- package/dist/stages/load/TaskManager.js.map +1 -0
- package/dist/stages/load/WindowByteRangeResolver.d.ts +47 -0
- package/dist/stages/load/WindowByteRangeResolver.d.ts.map +1 -0
- package/dist/stages/load/WindowByteRangeResolver.js +270 -0
- package/dist/stages/load/WindowByteRangeResolver.js.map +1 -0
- package/dist/stages/load/index.d.ts +11 -0
- package/dist/stages/load/index.d.ts.map +1 -0
- package/dist/stages/load/types.d.ts +177 -0
- package/dist/stages/load/types.d.ts.map +1 -0
- package/dist/stages/mux/MP4Muxer.d.ts +44 -0
- package/dist/stages/mux/MP4Muxer.d.ts.map +1 -0
- package/dist/stages/mux/MP4Muxer.js +262 -0
- package/dist/stages/mux/MP4Muxer.js.map +1 -0
- package/dist/stages/mux/OPFSWriter.d.ts +46 -0
- package/dist/stages/mux/OPFSWriter.d.ts.map +1 -0
- package/dist/stages/mux/index.d.ts +5 -0
- package/dist/stages/mux/index.d.ts.map +1 -0
- package/dist/stages/mux/mux.worker.d.ts +65 -0
- package/dist/stages/mux/mux.worker.d.ts.map +1 -0
- package/dist/stages/mux/mux.worker.js +219 -0
- package/dist/stages/mux/mux.worker.js.map +1 -0
- package/dist/stages/mux/types.d.ts +95 -0
- package/dist/stages/mux/types.d.ts.map +1 -0
- package/dist/stages/mux/utils.d.ts +32 -0
- package/dist/stages/mux/utils.d.ts.map +1 -0
- package/dist/stages/mux/utils.js +34 -0
- package/dist/stages/mux/utils.js.map +1 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/BackpressureAdapter.d.ts +26 -0
- package/dist/utils/BackpressureAdapter.d.ts.map +1 -0
- package/dist/utils/binary-search.d.ts +33 -0
- package/dist/utils/binary-search.d.ts.map +1 -0
- package/dist/utils/binary-search.js +62 -0
- package/dist/utils/binary-search.js.map +1 -0
- package/dist/utils/canvas-utils.d.ts +96 -0
- package/dist/utils/canvas-utils.d.ts.map +1 -0
- package/dist/utils/canvas-utils.js +58 -0
- package/dist/utils/canvas-utils.js.map +1 -0
- package/dist/utils/object-utils.d.ts +34 -0
- package/dist/utils/object-utils.d.ts.map +1 -0
- package/dist/utils/object-utils.js +22 -0
- package/dist/utils/object-utils.js.map +1 -0
- package/dist/utils/time-utils.d.ts +10 -0
- package/dist/utils/time-utils.d.ts.map +1 -0
- package/dist/utils/time-utils.js +60 -0
- package/dist/utils/time-utils.js.map +1 -0
- package/dist/worker/BaseWorker.d.ts +44 -0
- package/dist/worker/BaseWorker.d.ts.map +1 -0
- package/dist/worker/BaseWorker.js +98 -0
- package/dist/worker/BaseWorker.js.map +1 -0
- package/dist/worker/WorkerChannel.d.ts +105 -0
- package/dist/worker/WorkerChannel.d.ts.map +1 -0
- package/dist/worker/WorkerChannel.js +355 -0
- package/dist/worker/WorkerChannel.js.map +1 -0
- package/dist/worker/WorkerPool.d.ts +52 -0
- package/dist/worker/WorkerPool.d.ts.map +1 -0
- package/dist/worker/WorkerPool.js +124 -0
- package/dist/worker/WorkerPool.js.map +1 -0
- package/dist/worker/index.d.ts +11 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/transferable-helper.d.ts +89 -0
- package/dist/worker/transferable-helper.d.ts.map +1 -0
- package/dist/worker/transferable-helper.js +44 -0
- package/dist/worker/transferable-helper.js.map +1 -0
- package/dist/worker/types.d.ts +179 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +50 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/worker-event-whitelist.d.ts +23 -0
- package/dist/worker/worker-event-whitelist.d.ts.map +1 -0
- package/dist/worker/worker-retry.d.ts +36 -0
- package/dist/worker/worker-retry.d.ts.map +1 -0
- package/dist/worker/worker-retry.js +55 -0
- package/dist/worker/worker-retry.js.map +1 -0
- package/package.json +105 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Meframe } from '../Meframe';
|
|
2
|
+
import { CompositionModel } from '../model/CompositionModel';
|
|
3
|
+
|
|
4
|
+
export interface Plugin {
|
|
5
|
+
/** Plugin name */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Plugin version */
|
|
8
|
+
version: string;
|
|
9
|
+
/** Plugin description */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Dependencies on other plugins */
|
|
12
|
+
dependencies?: string[];
|
|
13
|
+
/** Install the plugin */
|
|
14
|
+
install(core: Meframe): void | Promise<void>;
|
|
15
|
+
/** Uninstall the plugin */
|
|
16
|
+
uninstall?(core: Meframe): void | Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export type PluginHook = 'beforeInit' | 'afterInit' | 'beforeDestroy' | 'afterDestroy' | 'beforeSetTree' | 'afterSetTree' | 'beforeApplyPatch' | 'afterApplyPatch' | 'beforePlay' | 'afterPlay' | 'beforePause' | 'afterPause' | 'beforeSeek' | 'afterSeek' | 'beforeExport' | 'afterExport' | 'exportProgress' | 'beforeDecode' | 'afterDecode' | 'beforeCompose' | 'afterCompose' | 'beforeEncode' | 'afterEncode' | 'cacheHit' | 'cacheMiss' | 'cacheEvict' | 'error' | 'warning';
|
|
19
|
+
export interface HookContext {
|
|
20
|
+
/** Hook name */
|
|
21
|
+
hook: PluginHook;
|
|
22
|
+
/** Timestamp */
|
|
23
|
+
timestamp: number;
|
|
24
|
+
/** Hook-specific data */
|
|
25
|
+
data?: unknown;
|
|
26
|
+
/** Cancel the operation (for 'before' hooks) */
|
|
27
|
+
cancel?: () => void;
|
|
28
|
+
/** Modify the data (for 'before' hooks) */
|
|
29
|
+
modify?: (newData: unknown) => void;
|
|
30
|
+
}
|
|
31
|
+
export interface PluginAPI {
|
|
32
|
+
/** Register a hook handler */
|
|
33
|
+
on(hook: PluginHook, handler: HookHandler): void;
|
|
34
|
+
/** Unregister a hook handler */
|
|
35
|
+
off(hook: PluginHook, handler: HookHandler): void;
|
|
36
|
+
/** Emit a custom event */
|
|
37
|
+
emit(event: string, data?: unknown): void;
|
|
38
|
+
/** Get core state */
|
|
39
|
+
getState(): unknown;
|
|
40
|
+
/** Get composition model */
|
|
41
|
+
getCompositionTree(): CompositionModel | null;
|
|
42
|
+
/** Get cache statistics */
|
|
43
|
+
getCacheStats(): unknown;
|
|
44
|
+
/** Log a message */
|
|
45
|
+
log(level: 'debug' | 'info' | 'warn' | 'error', message: string, data?: unknown): void;
|
|
46
|
+
}
|
|
47
|
+
export type HookHandler = (context: HookContext) => void | Promise<void>;
|
|
48
|
+
export interface PluginManager {
|
|
49
|
+
/** Register a plugin */
|
|
50
|
+
register(plugin: Plugin): void;
|
|
51
|
+
/** Unregister a plugin */
|
|
52
|
+
unregister(name: string): void;
|
|
53
|
+
/** Get registered plugins */
|
|
54
|
+
getPlugins(): Plugin[];
|
|
55
|
+
/** Check if a plugin is registered */
|
|
56
|
+
hasPlugin(name: string): boolean;
|
|
57
|
+
/** Execute hooks */
|
|
58
|
+
executeHook(hook: PluginHook, context: Partial<HookContext>): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { DuckingConfig, MixRequest } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AudioDucker - Automatic volume ducking for background music
|
|
5
|
+
*
|
|
6
|
+
* Ducking: Audio engineering technique where the volume of one audio source
|
|
7
|
+
* is automatically reduced when another audio source is present.
|
|
8
|
+
*
|
|
9
|
+
* Common use case: Reduce background music volume when voice/narration plays
|
|
10
|
+
* to improve speech intelligibility without completely muting the music.
|
|
11
|
+
*
|
|
12
|
+
* Key parameters:
|
|
13
|
+
* - Threshold: Level at which ducking triggers
|
|
14
|
+
* - Ratio: How much to reduce volume (e.g., 3:1 means reduce by 1/3)
|
|
15
|
+
* - Attack: How quickly volume reduces (typically 10-50ms)
|
|
16
|
+
* - Release: How quickly volume returns to normal (typically 100-500ms)
|
|
17
|
+
* - Hold: Time to maintain ducking after trigger ends
|
|
18
|
+
*/
|
|
19
|
+
export declare class AudioDucker {
|
|
20
|
+
private config;
|
|
21
|
+
private sampleRate;
|
|
22
|
+
constructor(sampleRate: number);
|
|
23
|
+
configure(config: DuckingConfig): void;
|
|
24
|
+
/**
|
|
25
|
+
* Analyze trigger tracks (voice) and generate ducking envelope
|
|
26
|
+
* Returns gain values (0-1) to apply to target tracks (BGM)
|
|
27
|
+
*/
|
|
28
|
+
generateDuckingEnvelope(tracks: MixRequest['tracks'], frameCount: number): Promise<Float32Array>;
|
|
29
|
+
/**
|
|
30
|
+
* Voice Activity Detection (VAD)
|
|
31
|
+
* Simple energy-based detection with smoothing
|
|
32
|
+
* More sophisticated implementations could use:
|
|
33
|
+
* - Zero-crossing rate (ZCR) for speech/music discrimination
|
|
34
|
+
* - Spectral centroid for voice frequency detection
|
|
35
|
+
* - Machine learning models for robust VAD
|
|
36
|
+
*/
|
|
37
|
+
private detectVoiceActivity;
|
|
38
|
+
/**
|
|
39
|
+
* Smooth voice activity detection to avoid choppy ducking
|
|
40
|
+
* Uses a simple moving average filter
|
|
41
|
+
*/
|
|
42
|
+
private smoothActivityDetection;
|
|
43
|
+
/**
|
|
44
|
+
* Apply ducking based on voice activity
|
|
45
|
+
* Implements attack/release envelope shaping
|
|
46
|
+
*/
|
|
47
|
+
private applyDuckingToEnvelope;
|
|
48
|
+
/**
|
|
49
|
+
* Apply ducking envelope to audio buffer
|
|
50
|
+
* This modulates the volume over time according to the envelope
|
|
51
|
+
*/
|
|
52
|
+
applyEnvelopeToVolume(baseVolume: number, envelope: Float32Array): Float32Array;
|
|
53
|
+
/**
|
|
54
|
+
* Calculate dynamic range to avoid over-compression
|
|
55
|
+
* Returns the difference between peak and RMS levels in dB
|
|
56
|
+
*/
|
|
57
|
+
calculateDynamicRange(envelope: Float32Array): number;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=AudioDucker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioDucker.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/AudioDucker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEzD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAI9B,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAItC;;;OAGG;IACG,uBAAuB,CAC3B,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,EAC5B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,CAAC;IAyBxB;;;;;;;OAOG;YACW,mBAAmB;IAwDjC;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IA4B/B;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAyC9B;;;OAGG;IACH,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY;IAQ/E;;;OAGG;IACH,qBAAqB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;CAiBtD"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
class AudioDucker {
|
|
2
|
+
config = null;
|
|
3
|
+
sampleRate;
|
|
4
|
+
constructor(sampleRate) {
|
|
5
|
+
this.sampleRate = sampleRate;
|
|
6
|
+
}
|
|
7
|
+
configure(config) {
|
|
8
|
+
this.config = config;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Analyze trigger tracks (voice) and generate ducking envelope
|
|
12
|
+
* Returns gain values (0-1) to apply to target tracks (BGM)
|
|
13
|
+
*/
|
|
14
|
+
async generateDuckingEnvelope(tracks, frameCount) {
|
|
15
|
+
if (!this.config?.enabled) {
|
|
16
|
+
return new Float32Array(frameCount).fill(1);
|
|
17
|
+
}
|
|
18
|
+
const envelope = new Float32Array(frameCount);
|
|
19
|
+
envelope.fill(1);
|
|
20
|
+
const triggerTracks = tracks.filter((t) => this.config.triggerTracks.includes(t.trackId));
|
|
21
|
+
if (triggerTracks.length === 0) {
|
|
22
|
+
return envelope;
|
|
23
|
+
}
|
|
24
|
+
for (const track of triggerTracks) {
|
|
25
|
+
const voiceActivity = await this.detectVoiceActivity(track.audioData);
|
|
26
|
+
this.applyDuckingToEnvelope(envelope, voiceActivity);
|
|
27
|
+
}
|
|
28
|
+
return envelope;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Voice Activity Detection (VAD)
|
|
32
|
+
* Simple energy-based detection with smoothing
|
|
33
|
+
* More sophisticated implementations could use:
|
|
34
|
+
* - Zero-crossing rate (ZCR) for speech/music discrimination
|
|
35
|
+
* - Spectral centroid for voice frequency detection
|
|
36
|
+
* - Machine learning models for robust VAD
|
|
37
|
+
*/
|
|
38
|
+
async detectVoiceActivity(audioData) {
|
|
39
|
+
const frameCount = audioData.numberOfFrames;
|
|
40
|
+
const activity = new Float32Array(frameCount);
|
|
41
|
+
const monoData = new Float32Array(frameCount);
|
|
42
|
+
const channelData = new Float32Array(frameCount);
|
|
43
|
+
for (let ch = 0; ch < audioData.numberOfChannels; ch++) {
|
|
44
|
+
audioData.copyTo(channelData, {
|
|
45
|
+
planeIndex: ch,
|
|
46
|
+
format: "f32-planar"
|
|
47
|
+
});
|
|
48
|
+
for (let i = 0; i < frameCount; i++) {
|
|
49
|
+
if (monoData && channelData) {
|
|
50
|
+
monoData[i] = (monoData[i] || 0) + (channelData[i] || 0) / audioData.numberOfChannels;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const windowSize = Math.floor(this.sampleRate * 0.02);
|
|
55
|
+
const hopSize = Math.floor(windowSize / 2);
|
|
56
|
+
for (let i = 0; i < frameCount; i += hopSize) {
|
|
57
|
+
const end = Math.min(i + windowSize, frameCount);
|
|
58
|
+
let energy = 0;
|
|
59
|
+
for (let j = i; j < end; j++) {
|
|
60
|
+
if (monoData && monoData[j] !== void 0) {
|
|
61
|
+
const sample = monoData[j];
|
|
62
|
+
if (sample !== void 0) {
|
|
63
|
+
energy += sample * sample;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
energy = Math.sqrt(energy / (end - i));
|
|
68
|
+
const threshold = 0.01;
|
|
69
|
+
const isVoice = energy > threshold;
|
|
70
|
+
for (let j = i; j < end; j++) {
|
|
71
|
+
activity[j] = isVoice ? 1 : 0;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return this.smoothActivityDetection(activity);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Smooth voice activity detection to avoid choppy ducking
|
|
78
|
+
* Uses a simple moving average filter
|
|
79
|
+
*/
|
|
80
|
+
smoothActivityDetection(activity) {
|
|
81
|
+
const smoothed = new Float32Array(activity.length);
|
|
82
|
+
const smoothWindow = Math.floor(this.sampleRate * 0.05);
|
|
83
|
+
for (let i = 0; i < activity.length; i++) {
|
|
84
|
+
let sum = 0;
|
|
85
|
+
let count = 0;
|
|
86
|
+
for (let j = Math.max(0, i - smoothWindow); j <= Math.min(activity.length - 1, i + smoothWindow); j++) {
|
|
87
|
+
if (activity && activity[j] !== void 0) {
|
|
88
|
+
const val = activity[j];
|
|
89
|
+
if (val !== void 0) {
|
|
90
|
+
sum += val;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
count++;
|
|
94
|
+
}
|
|
95
|
+
smoothed[i] = sum / count;
|
|
96
|
+
}
|
|
97
|
+
return smoothed;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Apply ducking based on voice activity
|
|
101
|
+
* Implements attack/release envelope shaping
|
|
102
|
+
*/
|
|
103
|
+
applyDuckingToEnvelope(envelope, voiceActivity) {
|
|
104
|
+
if (!this.config) return;
|
|
105
|
+
const duckingLevel = 1 - this.config.duckingLevel;
|
|
106
|
+
const attackSamples = Math.floor(this.config.attackTimeMs / 1e3 * this.sampleRate);
|
|
107
|
+
const releaseSamples = Math.floor(this.config.releaseTimeMs / 1e3 * this.sampleRate);
|
|
108
|
+
const lookAheadSamples = this.config.lookAheadMs ? Math.floor(this.config.lookAheadMs / 1e3 * this.sampleRate) : 0;
|
|
109
|
+
let currentGain = 1;
|
|
110
|
+
let releaseCounter = 0;
|
|
111
|
+
for (let i = 0; i < envelope.length; i++) {
|
|
112
|
+
const lookAheadIndex = Math.min(i + lookAheadSamples, voiceActivity.length - 1);
|
|
113
|
+
const activity = voiceActivity[lookAheadIndex];
|
|
114
|
+
if (activity !== void 0 && activity > 0.5) {
|
|
115
|
+
if (currentGain > duckingLevel) {
|
|
116
|
+
currentGain = Math.max(duckingLevel, currentGain - (1 - duckingLevel) / attackSamples);
|
|
117
|
+
} else {
|
|
118
|
+
currentGain = duckingLevel;
|
|
119
|
+
}
|
|
120
|
+
releaseCounter = 0;
|
|
121
|
+
} else if (currentGain < 1) {
|
|
122
|
+
releaseCounter++;
|
|
123
|
+
if (releaseCounter > releaseSamples * 0.1) {
|
|
124
|
+
currentGain = Math.min(1, currentGain + (1 - duckingLevel) / releaseSamples);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
envelope[i] = Math.min(envelope[i] || 1, currentGain);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Apply ducking envelope to audio buffer
|
|
132
|
+
* This modulates the volume over time according to the envelope
|
|
133
|
+
*/
|
|
134
|
+
applyEnvelopeToVolume(baseVolume, envelope) {
|
|
135
|
+
const result = new Float32Array(envelope.length);
|
|
136
|
+
for (let i = 0; i < envelope.length; i++) {
|
|
137
|
+
result[i] = baseVolume * (envelope[i] || 1);
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Calculate dynamic range to avoid over-compression
|
|
143
|
+
* Returns the difference between peak and RMS levels in dB
|
|
144
|
+
*/
|
|
145
|
+
calculateDynamicRange(envelope) {
|
|
146
|
+
let peak = 0;
|
|
147
|
+
let sumSquares = 0;
|
|
148
|
+
for (const value of envelope) {
|
|
149
|
+
peak = Math.max(peak, value);
|
|
150
|
+
sumSquares += value * value;
|
|
151
|
+
}
|
|
152
|
+
const rms = Math.sqrt(sumSquares / envelope.length);
|
|
153
|
+
const peakDb = 20 * Math.log10(peak);
|
|
154
|
+
const rmsDb = 20 * Math.log10(rms);
|
|
155
|
+
return peakDb - rmsDb;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
AudioDucker
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=AudioDucker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioDucker.js","sources":["../../../src/stages/compose/AudioDucker.ts"],"sourcesContent":["import type { DuckingConfig, MixRequest } from './types';\n\n/**\n * AudioDucker - Automatic volume ducking for background music\n *\n * Ducking: Audio engineering technique where the volume of one audio source\n * is automatically reduced when another audio source is present.\n *\n * Common use case: Reduce background music volume when voice/narration plays\n * to improve speech intelligibility without completely muting the music.\n *\n * Key parameters:\n * - Threshold: Level at which ducking triggers\n * - Ratio: How much to reduce volume (e.g., 3:1 means reduce by 1/3)\n * - Attack: How quickly volume reduces (typically 10-50ms)\n * - Release: How quickly volume returns to normal (typically 100-500ms)\n * - Hold: Time to maintain ducking after trigger ends\n */\nexport class AudioDucker {\n private config: DuckingConfig | null = null;\n private sampleRate: number;\n\n constructor(sampleRate: number) {\n this.sampleRate = sampleRate;\n }\n\n configure(config: DuckingConfig): void {\n this.config = config;\n }\n\n /**\n * Analyze trigger tracks (voice) and generate ducking envelope\n * Returns gain values (0-1) to apply to target tracks (BGM)\n */\n async generateDuckingEnvelope(\n tracks: MixRequest['tracks'],\n frameCount: number\n ): Promise<Float32Array> {\n if (!this.config?.enabled) {\n return new Float32Array(frameCount).fill(1.0);\n }\n\n // Initialize envelope with no ducking (gain = 1.0)\n const envelope = new Float32Array(frameCount);\n envelope.fill(1.0);\n\n // Find trigger tracks (typically voice/narration)\n const triggerTracks = tracks.filter((t) => this.config!.triggerTracks.includes(t.trackId));\n\n if (triggerTracks.length === 0) {\n return envelope;\n }\n\n // Analyze each trigger track for voice activity\n for (const track of triggerTracks) {\n const voiceActivity = await this.detectVoiceActivity(track.audioData);\n this.applyDuckingToEnvelope(envelope, voiceActivity);\n }\n\n return envelope;\n }\n\n /**\n * Voice Activity Detection (VAD)\n * Simple energy-based detection with smoothing\n * More sophisticated implementations could use:\n * - Zero-crossing rate (ZCR) for speech/music discrimination\n * - Spectral centroid for voice frequency detection\n * - Machine learning models for robust VAD\n */\n private async detectVoiceActivity(audioData: AudioData): Promise<Float32Array> {\n const frameCount = audioData.numberOfFrames;\n const activity = new Float32Array(frameCount);\n\n // Convert to mono for analysis\n const monoData = new Float32Array(frameCount);\n const channelData = new Float32Array(frameCount);\n\n for (let ch = 0; ch < audioData.numberOfChannels; ch++) {\n audioData.copyTo(channelData, {\n planeIndex: ch,\n format: 'f32-planar' as const,\n });\n\n for (let i = 0; i < frameCount; i++) {\n if (monoData && channelData) {\n monoData[i] = (monoData[i] || 0) + (channelData[i] || 0) / audioData.numberOfChannels;\n }\n }\n }\n\n // Energy calculation with windowing\n // Window size: 20ms is typical for speech analysis\n const windowSize = Math.floor(this.sampleRate * 0.02);\n const hopSize = Math.floor(windowSize / 2); // 50% overlap\n\n for (let i = 0; i < frameCount; i += hopSize) {\n const end = Math.min(i + windowSize, frameCount);\n\n // Calculate RMS energy in window\n let energy = 0;\n for (let j = i; j < end; j++) {\n if (monoData && monoData[j] !== undefined) {\n const sample = monoData[j];\n if (sample !== undefined) {\n energy += sample * sample;\n }\n }\n }\n energy = Math.sqrt(energy / (end - i));\n\n // Simple threshold-based VAD\n // Typical speech energy threshold: -40dB to -30dB\n const threshold = 0.01; // Approximately -40dB\n const isVoice = energy > threshold;\n\n // Fill activity array for this window\n for (let j = i; j < end; j++) {\n activity[j] = isVoice ? 1.0 : 0.0;\n }\n }\n\n // Smooth activity detection to avoid rapid changes\n return this.smoothActivityDetection(activity);\n }\n\n /**\n * Smooth voice activity detection to avoid choppy ducking\n * Uses a simple moving average filter\n */\n private smoothActivityDetection(activity: Float32Array): Float32Array {\n const smoothed = new Float32Array(activity.length);\n const smoothWindow = Math.floor(this.sampleRate * 0.05); // 50ms smoothing\n\n for (let i = 0; i < activity.length; i++) {\n let sum = 0;\n let count = 0;\n\n for (\n let j = Math.max(0, i - smoothWindow);\n j <= Math.min(activity.length - 1, i + smoothWindow);\n j++\n ) {\n if (activity && activity[j] !== undefined) {\n const val = activity[j];\n if (val !== undefined) {\n sum += val;\n }\n }\n count++;\n }\n\n smoothed[i] = sum / count;\n }\n\n return smoothed;\n }\n\n /**\n * Apply ducking based on voice activity\n * Implements attack/release envelope shaping\n */\n private applyDuckingToEnvelope(envelope: Float32Array, voiceActivity: Float32Array): void {\n if (!this.config) return;\n\n const duckingLevel = 1.0 - this.config.duckingLevel;\n const attackSamples = Math.floor((this.config.attackTimeMs / 1000) * this.sampleRate);\n const releaseSamples = Math.floor((this.config.releaseTimeMs / 1000) * this.sampleRate);\n const lookAheadSamples = this.config.lookAheadMs\n ? Math.floor((this.config.lookAheadMs / 1000) * this.sampleRate)\n : 0;\n\n let currentGain = 1.0;\n let releaseCounter = 0;\n\n for (let i = 0; i < envelope.length; i++) {\n // Look ahead for upcoming voice activity\n const lookAheadIndex = Math.min(i + lookAheadSamples, voiceActivity.length - 1);\n const activity = voiceActivity[lookAheadIndex];\n\n if (activity !== undefined && activity > 0.5) {\n // Voice detected - apply ducking with attack curve\n if (currentGain > duckingLevel) {\n // Attack phase - reduce gain\n currentGain = Math.max(duckingLevel, currentGain - (1.0 - duckingLevel) / attackSamples);\n } else {\n currentGain = duckingLevel;\n }\n releaseCounter = 0;\n } else if (currentGain < 1.0) {\n // No voice - apply release curve\n releaseCounter++;\n if (releaseCounter > releaseSamples * 0.1) {\n // Small hold time\n currentGain = Math.min(1.0, currentGain + (1.0 - duckingLevel) / releaseSamples);\n }\n }\n\n // Apply the calculated gain\n envelope[i] = Math.min(envelope[i] || 1, currentGain);\n }\n }\n\n /**\n * Apply ducking envelope to audio buffer\n * This modulates the volume over time according to the envelope\n */\n applyEnvelopeToVolume(baseVolume: number, envelope: Float32Array): Float32Array {\n const result = new Float32Array(envelope.length);\n for (let i = 0; i < envelope.length; i++) {\n result[i] = baseVolume * (envelope[i] || 1);\n }\n return result;\n }\n\n /**\n * Calculate dynamic range to avoid over-compression\n * Returns the difference between peak and RMS levels in dB\n */\n calculateDynamicRange(envelope: Float32Array): number {\n let peak = 0;\n let sumSquares = 0;\n\n for (const value of envelope) {\n peak = Math.max(peak, value);\n sumSquares += value * value;\n }\n\n const rms = Math.sqrt(sumSquares / envelope.length);\n\n // Convert to dB (20 * log10(ratio))\n const peakDb = 20 * Math.log10(peak);\n const rmsDb = 20 * Math.log10(rms);\n\n return peakDb - rmsDb;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { AudioComposeConfig, AudioTrack, AudioTrackConfig, MixRequest, MixResult } from './types';
|
|
2
|
+
import { AudioDucker } from './AudioDucker';
|
|
3
|
+
|
|
4
|
+
export declare class AudioMixer {
|
|
5
|
+
config: AudioComposeConfig;
|
|
6
|
+
private tracksMap;
|
|
7
|
+
constructor(config: AudioComposeConfig);
|
|
8
|
+
getConfig(): AudioComposeConfig;
|
|
9
|
+
updateConfig(update: Partial<AudioComposeConfig>): void;
|
|
10
|
+
get tracks(): AudioTrack[];
|
|
11
|
+
createMixStream(ducker?: AudioDucker): TransformStream<MixRequest, MixResult>;
|
|
12
|
+
mixTracks(request: MixRequest, precomputedFrameCount?: number): Promise<MixResult>;
|
|
13
|
+
addTrack(track: AudioTrack): void;
|
|
14
|
+
removeTrack(trackId: string): void;
|
|
15
|
+
updateTrack(trackId: string, patch: Partial<AudioTrack> & {
|
|
16
|
+
config?: Partial<AudioTrackConfig>;
|
|
17
|
+
}): void;
|
|
18
|
+
private mixTrackIntoOutput;
|
|
19
|
+
private buildGainEnvelope;
|
|
20
|
+
private extractChannels;
|
|
21
|
+
private limitAndMeasure;
|
|
22
|
+
private createAudioData;
|
|
23
|
+
private getFrameCount;
|
|
24
|
+
private getFadeSampleCount;
|
|
25
|
+
private getClipSampleCount;
|
|
26
|
+
private computeTrackStartFrame;
|
|
27
|
+
private getCurveValue;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=AudioMixer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AudioMixer.d.ts","sourceRoot":"","sources":["../../../src/stages/compose/AudioMixer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAEhB,UAAU,EACV,SAAS,EACV,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,qBAAa,UAAU;IACrB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,SAAS,CAAiC;gBAEtC,MAAM,EAAE,kBAAkB;IAItC,SAAS,IAAI,kBAAkB;IAI/B,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG,IAAI;IAIvD,IAAI,MAAM,IAAI,UAAU,EAAE,CAEzB;IAED,eAAe,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,eAAe,CAAC,UAAU,EAAE,SAAS,CAAC;IA+BvE,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IA0DxF,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAIjC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIlC,WAAW,CACT,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG;QAAE,MAAM,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAA;KAAE,GAClE,IAAI;IAaP,OAAO,CAAC,kBAAkB;IAsF1B,OAAO,CAAC,iBAAiB;IAiDzB,OAAO,CAAC,eAAe;IAsFvB,OAAO,CAAC,eAAe;IAkCvB,OAAO,CAAC,eAAe;IAoCvB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,kBAAkB;IAQ1B,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,aAAa;CActB"}
|