import { Flame } from '../generated/driveningress/v1/driveningress';
import { Avatar } from './Avatar';
import { AnimationPlayer } from '../audio/AnimationPlayer';
import { AvatarState, ConnectionState, AvatarPlaybackMode } from '../types';
export declare class AvatarController {
    private networkLayer?;
    readonly playbackMode: AvatarPlaybackMode;
    protected avatar: Avatar;
    protected animationPlayer: AnimationPlayer | null;
    protected currentKeyframes: Flame[];
    protected pendingAudioChunks: Array<{
        data: Uint8Array;
        isLast: boolean;
    }>;
    protected isPlaying: boolean;
    protected isConnected: boolean;
    protected currentState: AvatarState;
    onConnectionState: ((state: ConnectionState) => void) | null;
    onAvatarState: ((state: AvatarState) => void) | null;
    onError: ((error: Error) => void) | null;
    private eventListeners;
    private renderCallback?;
    private transitionCompleteCallback?;
    private characterHandle;
    private playbackLoopId;
    private lastRenderedFrameIndex;
    private keyframesOffset;
    private readonly MAX_KEYFRAMES;
    private readonly KEYFRAMES_CLEANUP_THRESHOLD;
    private readonly MAX_PENDING_AUDIO_CHUNKS;
    constructor(avatar: Avatar, options?: {
        playbackMode?: AvatarPlaybackMode;
    });
    /**
     * Start service (network mode only)
     */
    start(): Promise<void>;
    /**
     * Send audio to server (network mode only)
     * Also cache to data layer for playback
     */
    send(audioData: ArrayBuffer, end?: boolean): void;
    /**
     * Close service (network mode only)
     */
    close(): void;
    /**
     * Start playback (external data mode)
     * Must call this method first with initial data to start playback
     */
    play(initialAudioChunks?: Array<{
        data: Uint8Array;
        isLast: boolean;
    }>, initialKeyframes?: Flame[]): Promise<void>;
    /**
     * Send audio data (external data mode)
     * Stream additional audio data after play()
     */
    sendAudioChunk(data: Uint8Array, isLast?: boolean): void;
    /**
     * Send animation keyframes (external data mode or network mode)
     * Stream additional animation data after play()
     */
    sendKeyframes(keyframes: Flame[]): void;
    /**
     * Pause playback (can be resumed later)
     * Pause audio playback and stop render loop, but preserve all state (keyframes, audio buffers, etc.)
     */
    pause(): void;
    /**
     * Resume playback (from paused state)
     * Resume audio playback and restart render loop
     * Animation will continue from paused frame (because animation time base comes from audio, will auto-sync)
     */
    resume(): Promise<void>;
    /**
     * Interrupt current playback
     */
    interrupt(): void;
    /**
     * Clear all data and resources
     */
    clear(): void;
    /**
     * Start streaming playback (internal implementation)
     */
    private startStreamingPlaybackInternal;
    /**
     * Playback loop: Calculate animation frame based on audio time, notify render layer to render
     */
    private startPlaybackLoop;
    /**
     * Stop playback loop
     */
    private stopPlaybackLoop;
    /**
     * Stop playback
     */
    protected stopPlayback(): void;
    /**
     * Clean up players
     */
    protected cleanupPlayers(): void;
    /**
     * Add audio chunk to buffer
     */
    private addAudioChunkToBuffer;
    /**
     * Event system
     */
    private registerEventListener;
    /**
     * Emit event
     */
    protected emit(event: string, data?: any): void;
}
//# sourceMappingURL=AvatarController.d.ts.map