import type { RemoteParticipant } from '@livekit/rtc-node';
import { type AudioFrame, type LocalTrackPublication, type Participant, type RemoteTrackPublication, type Room, TrackPublishOptions } from '@livekit/rtc-node';
import { AudioOutput, TextOutput, type TimedString } from '../io.js';
export interface TranscriptionOutputOptions {
    /**
     * Whether expressive markup may be present in the text reaching this sink.
     *
     * Evaluated per chunk, because the session latches it on the first turn that injects
     * the markup guide — after this sink is constructed. Defaults to "never", so a session
     * that doesn't use expressive mode publishes its transcript untouched: the strip works
     * off the union of every provider's tag names, and an agent that legitimately writes
     * `<break time="1s"/>` should not have it silently deleted.
     */
    expressiveEnabled?: () => boolean;
}
declare abstract class BaseParticipantTranscriptionOutput extends TextOutput {
    protected room: Room;
    protected isDeltaStream: boolean;
    protected participantIdentity: string | null;
    protected trackId?: string;
    protected capturing: boolean;
    protected latestText: string;
    protected currentId: string;
    protected logger: import("pino").Logger;
    protected expressiveEnabled: () => boolean;
    constructor(room: Room, isDeltaStream: boolean, participant: Participant | string | null, options?: TranscriptionOutputOptions);
    setParticipant(participant: Participant | string | null): void;
    protected onTrackPublished: (track: RemoteTrackPublication, participant: RemoteParticipant) => void;
    protected onLocalTrackPublished: (track: LocalTrackPublication | undefined) => void;
    protected generateCurrentId(): string;
    protected resetState(): void;
    captureText(text: string | TimedString): Promise<void>;
    flush(): void;
    protected abstract handleCaptureText(text: string): Promise<void>;
    protected abstract handleFlush(): void;
}
export interface ParticipantTranscriptionOutputOptions extends TranscriptionOutputOptions {
    /** When true, each chunk sent on the `lk.transcription` datastream topic is serialized
     *  as a JSON object with `text`, and `start_time`/`end_time`/`confidence`/
     *  `start_time_offset` when the captured value is a TimedString. Each object is
     *  suffixed with a newline so subscribers can parse the stream line-by-line. */
    jsonFormat?: boolean;
}
export declare class ParticipantTranscriptionOutput extends BaseParticipantTranscriptionOutput {
    private writer;
    private flushTask;
    private jsonFormat;
    /**
     * Per-segment markup stripping: delta streams strip incrementally (buffering a tag split
     * across chunks); non-delta streams re-strip the full text each time and keep the latest
     * tags in {@link segmentTags} for the expression attribute.
     */
    private stripper;
    private segmentTags;
    constructor(room: Room, isDeltaStream: boolean, participant: Participant | string | null, options?: ParticipantTranscriptionOutputOptions);
    captureText(text: string | TimedString): Promise<void>;
    private encode;
    private publish;
    protected handleCaptureText(_text: string): Promise<void>;
    protected handleFlush(): void;
    protected resetState(): void;
    private createTextWriter;
    private flushTaskImpl;
}
export declare class ParticipantLegacyTranscriptionOutput extends BaseParticipantTranscriptionOutput {
    private pushedText;
    private flushTask;
    protected handleCaptureText(text: string): Promise<void>;
    /** The raw accumulation, with markup removed only when expressive could have written it. */
    private visibleText;
    protected handleFlush(): void;
    publishTranscription(id: string, text: string, final: boolean, signal?: AbortSignal): Promise<void>;
    protected resetState(): void;
}
export declare class ParalellTextOutput extends TextOutput {
    /** @internal */
    _sinks: TextOutput[];
    constructor(sinks: TextOutput[], nextInChain?: TextOutput);
    captureText(text: string | TimedString): Promise<void>;
    flush(): void;
}
export interface AudioOutputOptions {
    sampleRate: number;
    numChannels: number;
    trackPublishOptions: TrackPublishOptions;
    queueSizeMs?: number;
}
export declare class ParticipantAudioOutput extends AudioOutput {
    private room;
    private options;
    private audioSource;
    private publication?;
    private flushTask?;
    /** Duration of audio pushed to the source, in seconds */
    private pushedDuration;
    private sourcePushedDuration;
    private sourceDiscardedDuration;
    private interruptionGeneration;
    private forwardingCount;
    /** Resolved only while no capture is held or being submitted to AudioSource. */
    private forwardingIdleFuture;
    private startedFuture;
    private interruptedFuture;
    private firstFrameEmitted;
    /** Gate held closed while the output is paused; frame forwarding awaits it. */
    private playbackEnabledFuture;
    /**
     * The playhead sits at `sourcePushedDuration` minus what the source still holds; `dryAt` is
     * when the source runs out if nothing more is pushed, which dates a run that has ended.
     */
    private runOffset;
    private dryAt?;
    constructor(room: Room, options: AudioOutputOptions);
    pause(): void;
    resume(): void;
    get subscribed(): boolean;
    /** Report the open run, and begin the next past any audio that never played. */
    private reportRun;
    start(signal: AbortSignal): Promise<void>;
    captureFrame(frame: AudioFrame): Promise<void>;
    private waitForPlayoutTask;
    /**
     * Flush any buffered audio, marking the current playback/segment as complete
     */
    flush(): void;
    clearBuffer(): void;
    private publishTrack;
    close(): Promise<void>;
}
export {};
//# sourceMappingURL=_output.d.ts.map