import { DuplexOptions, Duplex } from 'stream';
import { Readable } from 'node:stream';

declare enum DataType {
    master = 0,
    string = 1,
    uint = 2,
    binary = 3,
    float = 4
}
declare type DataReturnType = (buf: Buffer) => string | number;
interface EBML {
    version?: number;
    readVersion?: number;
    maxIDLength?: number;
    maxSizeWidth?: number;
    docType?: string;
    docTypeVersion?: number;
    docTypeReadVersion?: number;
}
interface Seek {
    position?: number;
}
declare type SeekHead = Seek[];
interface Info {
    duration?: number;
    muxingApp?: string;
    writingApp?: string;
}
declare type Tracks = TracksEntry[];
interface TracksEntry {
    trackNumber?: number;
    trackType?: number;
    codecID?: string;
    audio?: Audio;
}
interface Audio {
    rate?: number;
    channels?: number;
    bitDepth?: number;
}
interface CuePoint {
    time?: number;
    track?: number;
    position?: number;
}
declare type Cues = CuePoint[];
interface Cluster {
    time?: number;
}
interface Segment {
    seekHead?: SeekHead;
    info?: Info;
    tracks?: Tracks;
    cues?: Cues;
    cluster?: Cluster;
}
interface ElementsData {
    name: string;
    type: DataType;
    return?: DataReturnType;
}
declare type ElementsDataType = {
    [key: string]: ElementsData;
};
declare const WebmElements: ElementsDataType;

interface OpusHandlerOptions {
    rate: 8000 | 12000 | 16000 | 24000 | 48000;
    channels: 1 | 2;
    frameSize: number;
}

declare class OpusHandler$1 {
    protected options: OpusHandlerOptions;
    private encoder;
    constructor(options: OpusHandlerOptions);
    encode(buf: Buffer): Buffer;
    decode(buf: Buffer): Buffer;
    encode_ctl(ctl: number, val: number): void;
    decode_ctl(ctl: number, val: number): void;
    delete(): void;
}

declare class OpusHandler {
    protected options: OpusHandlerOptions;
    private encoder;
    constructor(options: OpusHandlerOptions);
    encode(buf: Buffer): Buffer;
    decode(buf: Buffer): Buffer;
    encode_ctl(ctl: number, val: number): void;
    decode_ctl(ctl: number, val: number): void;
    delete(): void;
}

declare type OpusEncoder$1 = OpusHandler$1 | OpusHandler;

interface OpusTransformOptions extends OpusHandlerOptions {
    encoder?: 'play-opus' | 'opusscript';
    duplex?: DuplexOptions;
}
declare abstract class OpusDuplexStream extends Duplex {
    protected pcm_length: number;
    protected encoder: OpusEncoder$1;
    constructor(options: OpusTransformOptions);
    protected encode(buf: Buffer): Buffer;
    protected decode(buffer: Buffer): Buffer;
    private cleanup;
    _read(): void;
    _destroy(error: Error | null, callback: (error: Error | null) => void): void;
    abstract _write(chunk: Buffer, enc: BufferEncoding, next: (error?: Error | null) => void): void;
    _final(callback: (error?: Error | null) => void): void;
    abstract applyCTL(ctl: number, value: number): void;
    bitrate(bitrate: number): void;
    setFEC(enabled: boolean): void;
    setPLP(percentage: number): void;
}

declare class OpusEncoder extends OpusDuplexStream {
    private remaining;
    constructor(options: OpusTransformOptions);
    _write(chunk: Buffer, _: BufferEncoding, done: (error?: Error | null) => void): void;
    applyCTL(ctl: number, value: number): void;
}

declare class OpusDecoder extends OpusDuplexStream {
    opusHead?: Buffer;
    opusTags?: Buffer;
    constructor(options: OpusTransformOptions);
    _write(chunk: Buffer, _: BufferEncoding, done: (error?: Error | null) => void): void;
    applyCTL(ctl: number, value: number): void;
}

declare class OggDemuxer extends Duplex {
    private remaining?;
    private opus_head?;
    private ogg_head?;
    constructor(options?: DuplexOptions);
    _read(): void;
    _write(chunk: Buffer, _: BufferEncoding, done: (error?: Error) => void): void;
    private readOggPage;
    private readOggData;
    private readOggHead;
    _destroy(err: Error | null, callback: (error: Error | null) => void): void;
    _final(callback: (error?: Error) => void): void;
    _cleanup(): void;
}

declare class WebmHeader {
    ebml: EBML;
    segment: Segment;
    audioTrack: number;
    constructor();
    parse(ebmlID: ElementsData, chunk: Buffer): Error | undefined;
}

declare class WebmDemuxer extends Duplex {
    remaining?: Buffer;
    chunk?: Buffer;
    cursor: number;
    header: WebmHeader;
    headfound: boolean;
    private data_size;
    private data_length;
    constructor(options?: DuplexOptions);
    private get vint_length();
    private get vint_value();
    cleanup(): void;
    _read(): void;
    _write(chunk: Buffer, _: BufferEncoding, done: (error?: Error | null) => void): void;
    private readTag;
    private parseEbmlID;
    _destroy(error: Error | null, callback: (error: Error | null) => void): void;
    _final(callback: (error?: Error | null) => void): void;
}

interface FFmpegDownloadOptions {
    path?: string;
    debug?: boolean;
    force?: boolean;
}
interface FFmpegOptions {
    input?: string | Readable;
    args?: string[];
}
declare function ffmpeg(options?: FFmpegOptions): Promise<Readable>;
declare function ffmpeg_download(options?: FFmpegDownloadOptions): Promise<void>;
declare function initializeFFmpeg(preference?: "npx" | "global" | "local"): Promise<boolean>;

declare const _default: {
    OpusDecoder: typeof OpusDecoder;
    OggDemuxer: typeof OggDemuxer;
    OpusEncoder: typeof OpusEncoder;
    WebmDemuxer: typeof WebmDemuxer;
    WebmHeader: typeof WebmHeader;
    WebmElements: ElementsDataType;
    ffmpeg_download: typeof ffmpeg_download;
    ffmpeg: typeof ffmpeg;
    initializeFFmpeg: typeof initializeFFmpeg;
};

export { OggDemuxer, OpusDecoder, OpusEncoder, WebmDemuxer, WebmElements, WebmHeader, _default as default, ffmpeg, ffmpeg_download, initializeFFmpeg };
