z-web-audio-stream
Version:
iOS Safari-safe Web Audio streaming with separated download/storage optimization, instant playback, and memory management
158 lines • 5.77 kB
TypeScript
import { type DownloadStrategy, type DownloadProgress } from './DownloadManager.js';
export interface WebAudioManagerOptions {
workletPath?: string;
enableCache?: boolean;
maxCacheSize?: number;
onTimeUpdate?: (currentTime: number, duration: number) => void;
onEnded?: () => void;
onError?: (error: Error) => void;
onProgressiveLoadingStatus?: (status: 'STARTED' | 'PROGRESS' | 'COMPLETED' | 'FAILED', data?: any) => void;
enableInstantPlayback?: boolean;
instantPlaybackConfig?: InstantPlaybackConfig;
obfuscationKey?: string;
}
export interface InstantPlaybackConfig {
downloadStrategy?: Partial<DownloadStrategy>;
storageChunkSize?: number;
playbackChunkSize?: number;
maxInitialWaitTime?: number;
strategy?: 'auto' | 'always' | 'never';
enablePerformanceLogging?: boolean;
}
/**
* iOS Safari-safe Web Audio manager with progressive streaming
*
* Key features:
* - iOS-safe AudioContext initialization to fix pitch/speed issues
* - Memory-safe progressive loading to prevent page reloads
* - IndexedDB-based caching with Safari-specific retry logic
* - AudioWorklet-based playback with sample rate monitoring
* - Automatic cleanup and storage management
*/
export declare class WebAudioManager {
private audioContext;
private audioWorkletNode;
private gainNode;
private audioBuffers;
private currentTrackId;
private isInitialized;
private preloadQueue;
private chunkStore;
private onTimeUpdate?;
private onEnded?;
private onError?;
private onProgressiveLoadingStatus?;
private lastKnownPosition;
private positionRequestResolvers;
private iosSafariDetected;
private lastKnownSampleRate;
private sampleRateMonitorInterval;
private silentBuffer;
private readonly MAX_TRANSFER_SIZE;
private downloadManager;
private streamingAssembler;
private workletPath;
private enableCache;
private enableInstantPlayback;
private instantPlaybackConfig;
private obfuscationKey?;
private instantPlaybackSessions;
private defaultInstantConfig;
constructor(options?: WebAudioManagerOptions);
private isIOSSafari;
private initializeOnUserGesture;
private createIOSSafeAudioContext;
private playDummyBuffer;
private createSilentBuffer;
private startSampleRateMonitoring;
private handleSampleRateChange;
initialize(): Promise<void>;
private setupWorkletMessageHandling;
loadAudio(url: string, trackId: string, progressCallback?: (loaded: number, total: number) => void): Promise<AudioBuffer>;
play(trackId: string): Promise<void>;
loadAndPlay(url: string, trackId: string, name?: string): Promise<void>;
playInstantly(url: string, trackId: string, name: string, options?: {
forceInstant?: boolean;
onChunkLoaded?: (chunkIndex: number, totalChunks: number) => void;
onFullyLoaded?: () => void;
onDownloadProgress?: (progress: DownloadProgress) => void;
}): Promise<void>;
/**
* Start playback with the first assembled chunk
*/
private startPlaybackWithChunk;
/**
* Seamlessly replace the current buffer with a larger one containing more audio data
*/
private seamlesslyReplaceBuffer;
preloadAudio(url: string, trackId: string, name?: string): Promise<void>;
pause(): Promise<void>;
resume(): Promise<void>;
seek(time: number): Promise<void>;
setVolume(volume: number): void;
getCurrentTime(): number;
/**
* Get the duration of a loaded audio buffer
* @param trackId The track ID to get duration for
* @returns Duration in seconds, or null if not loaded
*/
getBufferDuration(trackId: string): number | null;
/**
* Check if audio for a specific track is fully loaded
* @param trackId The track ID to check
* @returns True if audio is loaded and ready for playback
*/
isAudioLoaded(trackId: string): Promise<boolean>;
/**
* Get a list of all cached tracks with metadata
* @returns Array of cached track information
*/
getCachedTracks(): Promise<Array<{
trackId: string;
name?: string;
duration?: number;
size: number;
lastAccessed: Date;
isLoaded: boolean;
}>>;
private shouldUseInstantPlayback;
private loadFirstChunk;
private checkRangeSupport;
private loadFirstChunkWithRangeRequest;
private loadFirstChunkWithProgressiveDownload;
private getFileSize;
private loadRemainingChunksWithRangeRequests;
private continueLoadingInBackground;
private updateSessionWithLargerBuffer;
private loadRemainingChunks;
private loadChunk;
private mergeAudioBuffers;
private replaceBufferSeamlessly;
private getCurrentPosition;
getInstantPlaybackMetrics(): {
enabled: boolean;
config: InstantPlaybackConfig;
activeSessions: number;
sessionMetrics: Array<{
trackId: string;
startTime: number;
isActive: boolean;
loadedChunks: number;
totalChunks: number;
}>;
};
getPlaybackStrategy(url: string, options?: {
estimatedFileSize?: number;
connectionSpeed?: 'slow' | 'medium' | 'fast';
deviceType?: 'mobile' | 'desktop';
}): {
strategy: 'instant' | 'progressive' | 'standard';
reasoning: string;
recommendedConfig?: Partial<InstantPlaybackConfig>;
};
enableInstantMode(config?: Partial<InstantPlaybackConfig>): void;
disableInstantMode(): void;
cleanup(): Promise<void>;
}
export declare function getWebAudioManager(options?: WebAudioManagerOptions): WebAudioManager;
//# sourceMappingURL=WebAudioManager.d.ts.map