{"version":3,"file":"index.cjs","sources":["../src/command-builder.ts","../src/parsers/version-parser.ts","../src/parsers/formats-parser.ts","../src/parsers/codecs-parser.ts","../src/parsers/metadata-parser.ts","../src/types/hardware.ts","../src/types/stream.ts","../src/utils/hardware-detection.ts","../src/utils/input-handler.ts","../src/types/codecs.ts","../src/types/formats.ts","../src/utils/conversion-helper.ts","../src/utils/filter-builder.ts","../src/utils/hardware-acceleration-helper.ts","../src/utils/command-generator.ts","../src/utils/progress-parser.ts","../src/errors/ffmpeg-errors.ts","../src/utils/execution-engine.ts","../src/utils/thumbnail-extractor.ts","../src/utils/trailer-generator.ts","../src/utils/screenshot-extractor.ts","../src/utils/concatenation.ts","../src/utils/multi-input-handler.ts","../src/ffmpeg.ts","../src/types/filters.ts","../src/types/enums.ts","../src/presets/index.ts"],"sourcesContent":["import type { FFmpegOptions } from './types/options';\n\nexport class CommandBuilder {\n  private args: string[] = [];\n\n  /**\n   * Add global options (before input)\n   */\n  addGlobalOptions(options: { overwrite?: boolean; hideOutput?: boolean }): this {\n    if (options.overwrite) {\n      this.args.push('-y');\n    }\n\n    if (options.hideOutput) {\n      this.args.push('-hide_banner', '-loglevel', 'error');\n    }\n\n    return this;\n  }\n\n  /**\n   * Add input file\n   */\n  addInput(inputPath: string): this {\n    this.args.push('-i', inputPath);\n    return this;\n  }\n\n  /**\n   * Add video codec\n   */\n  addVideoCodec(codec: string): this {\n    this.args.push('-c:v', codec);\n    return this;\n  }\n\n  /**\n   * Add audio codec\n   */\n  addAudioCodec(codec: string): this {\n    this.args.push('-c:a', codec);\n    return this;\n  }\n\n  /**\n   * Add video bitrate\n   */\n  addVideoBitrate(bitrate: string): this {\n    this.args.push('-b:v', bitrate);\n    return this;\n  }\n\n  /**\n   * Add audio bitrate\n   */\n  addAudioBitrate(bitrate: string): this {\n    this.args.push('-b:a', bitrate);\n    return this;\n  }\n\n  /**\n   * Add output format\n   */\n  addFormat(format: string): this {\n    this.args.push('-f', format);\n    return this;\n  }\n\n  /**\n   * Add FPS\n   */\n  addFps(fps: number): this {\n    this.args.push('-r', fps.toString());\n    return this;\n  }\n\n  /**\n   * Add video size/resolution\n   */\n  addSize(size: string): this {\n    this.args.push('-s', size);\n    return this;\n  }\n\n  /**\n   * Add aspect ratio\n   */\n  addAspectRatio(aspectRatio: string): this {\n    this.args.push('-aspect', aspectRatio);\n    return this;\n  }\n\n  /**\n   * Add duration (limit output duration)\n   */\n  addDuration(duration: number): this {\n    this.args.push('-t', duration.toString());\n    return this;\n  }\n\n  /**\n   * Add seek (start position)\n   */\n  addSeek(seek: number): this {\n    this.args.push('-ss', seek.toString());\n    return this;\n  }\n\n  /**\n   * Disable audio\n   */\n  disableAudio(): this {\n    this.args.push('-an');\n    return this;\n  }\n\n  /**\n   * Disable video\n   */\n  disableVideo(): this {\n    this.args.push('-vn');\n    return this;\n  }\n\n  /**\n   * Add custom arguments\n   */\n  addCustomArgs(customArgs: string[]): this {\n    this.args.push(...customArgs);\n    return this;\n  }\n\n  /**\n   * Add output file\n   */\n  addOutput(outputPath: string): this {\n    this.args.push(outputPath);\n    return this;\n  }\n\n  /**\n   * Build FFmpeg conversion command with options\n   */\n  buildConversionCommand(\n    inputPath: string,\n    outputPath: string,\n    options: FFmpegOptions = {}\n  ): string[] {\n    this.reset();\n\n    // Global options\n    this.addGlobalOptions({ overwrite: true });\n\n    // Input\n    this.addInput(inputPath);\n\n    // Video codec\n    if (options.videoCodec) {\n      this.addVideoCodec(options.videoCodec);\n    }\n\n    // Audio codec\n    if (options.audioCodec) {\n      this.addAudioCodec(options.audioCodec);\n    }\n\n    // Video bitrate\n    if (options.videoBitrate) {\n      this.addVideoBitrate(options.videoBitrate);\n    }\n\n    // Audio bitrate\n    if (options.audioBitrate) {\n      this.addAudioBitrate(options.audioBitrate);\n    }\n\n    // Format\n    if (options.format) {\n      this.addFormat(options.format);\n    }\n\n    // FPS\n    if (options.fps) {\n      this.addFps(options.fps);\n    }\n\n    // Size\n    if (options.size) {\n      this.addSize(options.size);\n    }\n\n    // Aspect ratio\n    if (options.aspectRatio) {\n      this.addAspectRatio(options.aspectRatio);\n    }\n\n    // Seek\n    if (options.seek) {\n      this.addSeek(options.seek);\n    }\n\n    // Duration\n    if (options.duration) {\n      this.addDuration(options.duration);\n    }\n\n    // No audio\n    if (options.noAudio) {\n      this.disableAudio();\n    }\n\n    // No video\n    if (options.noVideo) {\n      this.disableVideo();\n    }\n\n    // Output\n    this.addOutput(outputPath);\n\n    return this.build();\n  }\n\n  /**\n   * Build FFprobe command for metadata extraction\n   */\n  buildProbeCommand(inputPath: string): string[] {\n    this.reset();\n\n    return ['-v', 'quiet', '-print_format', 'json', '-show_format', '-show_streams', inputPath];\n  }\n\n  /**\n   * Build the command arguments array\n   */\n  build(): string[] {\n    return [...this.args];\n  }\n\n  /**\n   * Reset the builder\n   */\n  reset(): this {\n    this.args = [];\n    return this;\n  }\n\n  /**\n   * Get the command as a string (for display purposes)\n   */\n  toString(executable: string = 'ffmpeg'): string {\n    return `${executable} ${this.args.join(' ')}`;\n  }\n}\n","import type { FFmpegVersionInfo } from '../types/version';\n\nexport function parseVersion(output: string): FFmpegVersionInfo {\n  const lines = output.split('\\n');\n  const versionLine = lines[0];\n\n  // Parse version\n  const versionMatch = versionLine.match(/ffmpeg version ([^\\s]+)/);\n  const version = versionMatch ? versionMatch[1] : 'unknown';\n\n  // Parse copyright\n  const copyrightMatch = versionLine.match(/Copyright \\(c\\) (.+)/);\n  const copyright = copyrightMatch ? copyrightMatch[1] : '';\n\n  // Parse configuration\n  const configLines = lines.filter(line => line.trim().startsWith('--'));\n  const configuration = configLines.map(line => line.trim());\n\n  // Parse library versions\n  const libVersions: { [key: string]: string } = {};\n  const libLines = lines.filter(line => line.trim().match(/^lib\\w+\\s+\\d+\\./));\n  libLines.forEach(line => {\n    const match = line.trim().match(/^(lib\\w+)\\s+([\\d.]+)/);\n    if (match) {\n      libVersions[match[1]] = match[2];\n    }\n  });\n\n  return {\n    version,\n    copyright,\n    configuration,\n    libVersions,\n  };\n}\n","export function parseFormats(output: string): { demuxing: string[]; muxing: string[] } {\n  const lines = output.split('\\n');\n  const demuxing: string[] = [];\n  const muxing: string[] = [];\n\n  // Skip header lines\n  let startParsing = false;\n  for (const line of lines) {\n    if (line.includes('--')) {\n      startParsing = true;\n      continue;\n    }\n\n    if (!startParsing || !line.trim()) continue;\n\n    const match = line.match(/^\\s*([DE\\s]{2})\\s+(\\S+)/);\n    if (match) {\n      const flags = match[1];\n      const format = match[2];\n\n      if (flags.includes('D')) demuxing.push(format);\n      if (flags.includes('E')) muxing.push(format);\n    }\n  }\n\n  return { demuxing, muxing };\n}\n","export function parseEncoders(output: string): {\n  video: string[];\n  audio: string[];\n  subtitle: string[];\n} {\n  const lines = output.split('\\n');\n  const video: string[] = [];\n  const audio: string[] = [];\n  const subtitle: string[] = [];\n\n  let startParsing = false;\n  for (const line of lines) {\n    if (line.includes('------')) {\n      startParsing = true;\n      continue;\n    }\n\n    if (!startParsing || !line.trim()) continue;\n\n    const match = line.match(/^\\s*([VAS][.FXBD]{5})\\s+(\\S+)/);\n    if (match) {\n      const flags = match[1];\n      const codec = match[2];\n      const codecType = flags.charAt(0); // V, A, or S\n\n      if (codecType === 'V') {\n        video.push(codec);\n      } else if (codecType === 'A') {\n        audio.push(codec);\n      } else if (codecType === 'S') {\n        subtitle.push(codec);\n      }\n    }\n  }\n\n  return { video, audio, subtitle };\n}\n\nexport function parseDecoders(output: string): {\n  video: string[];\n  audio: string[];\n  subtitle: string[];\n} {\n  const lines = output.split('\\n');\n  const video: string[] = [];\n  const audio: string[] = [];\n  const subtitle: string[] = [];\n\n  let startParsing = false;\n  for (const line of lines) {\n    if (line.includes('------')) {\n      startParsing = true;\n      continue;\n    }\n\n    if (!startParsing || !line.trim()) continue;\n\n    const match = line.match(/^\\s*([VAS][.FXBD]{5})\\s+(\\S+)/);\n    if (match) {\n      const flags = match[1];\n      const codec = match[2];\n      const codecType = flags.charAt(0); // V, A, or S\n\n      if (codecType === 'V') {\n        video.push(codec);\n      } else if (codecType === 'A') {\n        audio.push(codec);\n      } else if (codecType === 'S') {\n        subtitle.push(codec);\n      }\n    }\n  }\n\n  return { video, audio, subtitle };\n}\n","import type {\n  MediaMetadata,\n  StreamMetadata,\n  FormatMetadata,\n  VideoMetadata,\n  ImageMetadata,\n} from '../types/metadata';\n\n/**\n * Parse FFprobe JSON output into MediaMetadata\n */\nexport function parseMediaMetadata(jsonOutput: string): MediaMetadata {\n  const data = JSON.parse(jsonOutput);\n\n  const format: FormatMetadata = {\n    filename: data.format.filename,\n    formatName: data.format.format_name,\n    formatLongName: data.format.format_long_name,\n    startTime: data.format.start_time,\n    duration: data.format.duration,\n    size: data.format.size,\n    bitRate: data.format.bit_rate,\n    probeScore: data.format.probe_score,\n    tags: data.format.tags || {},\n  };\n\n  const streams: StreamMetadata[] = (data.streams || []).map((stream: any) => ({\n    index: stream.index,\n    codecName: stream.codec_name,\n    codecLongName: stream.codec_long_name,\n    codecType: stream.codec_type,\n    codecTag: stream.codec_tag_string,\n\n    // Video specific\n    width: stream.width,\n    height: stream.height,\n    codedWidth: stream.coded_width,\n    codedHeight: stream.coded_height,\n    displayAspectRatio: stream.display_aspect_ratio,\n    pixelFormat: stream.pix_fmt,\n    frameRate: stream.r_frame_rate,\n    avgFrameRate: stream.avg_frame_rate,\n\n    // Audio specific\n    sampleRate: stream.sample_rate,\n    channels: stream.channels,\n    channelLayout: stream.channel_layout,\n    bitsPerSample: stream.bits_per_sample,\n\n    // Common\n    duration: stream.duration,\n    durationTs: stream.duration_ts,\n    startTime: stream.start_time,\n    startPts: stream.start_pts,\n    bitrate: stream.bit_rate,\n    tags: stream.tags || {},\n  }));\n\n  return { format, streams };\n}\n\n/**\n * Parse media metadata into VideoMetadata\n */\nexport function parseVideoMetadata(metadata: MediaMetadata): VideoMetadata {\n  const videoStreams = metadata.streams.filter(s => s.codecType === 'video');\n  const audioStreams = metadata.streams.filter(s => s.codecType === 'audio');\n  const subtitleStreams = metadata.streams.filter(s => s.codecType === 'subtitle');\n\n  if (videoStreams.length === 0) {\n    throw new Error('No video stream found in media file');\n  }\n\n  const primaryVideo = videoStreams[0];\n  const primaryAudio = audioStreams[0];\n\n  // Parse frame rate\n  let frameRate = 0;\n  if (primaryVideo.avgFrameRate) {\n    const [num, den] = primaryVideo.avgFrameRate.split('/').map(Number);\n    frameRate = den > 0 ? num / den : 0;\n  }\n\n  // Parse duration\n  const duration = parseFloat(metadata.format.duration || '0');\n\n  // Parse bitrate\n  const bitrate = parseInt(metadata.format.bitRate || '0', 10) / 1000; // Convert to kbps\n\n  // Parse size\n  const size = parseInt(metadata.format.size || '0', 10);\n\n  return {\n    format: metadata.format,\n    videoStreams,\n    audioStreams,\n    subtitleStreams,\n    duration,\n    width: primaryVideo.width || 0,\n    height: primaryVideo.height || 0,\n    frameRate,\n    videoCodec: primaryVideo.codecName,\n    audioCodec: primaryAudio?.codecName,\n    bitrate,\n    size,\n  };\n}\n\n/**\n * Parse media metadata into ImageMetadata\n */\nexport function parseImageMetadata(metadata: MediaMetadata): ImageMetadata {\n  const videoStreams = metadata.streams.filter(s => s.codecType === 'video');\n\n  if (videoStreams.length === 0) {\n    throw new Error('No image stream found in file');\n  }\n\n  const primaryStream = videoStreams[0];\n  const size = parseInt(metadata.format.size || '0', 10);\n\n  return {\n    format: metadata.format,\n    width: primaryStream.width || 0,\n    height: primaryStream.height || 0,\n    pixelFormat: primaryStream.pixelFormat || 'unknown',\n    codec: primaryStream.codecName,\n    size,\n  };\n}\n","export enum HardwareAcceleration {\n  CPU = 'cpu',\n  NVIDIA = 'nvidia',\n  INTEL = 'intel',\n  AMD = 'amd',\n  VAAPI = 'vaapi',\n  VIDEOTOOLBOX = 'videotoolbox',\n  V4L2 = 'v4l2',\n  ANY = 'any',\n}\n\nexport type HardwareAccelerationValue = HardwareAcceleration | string;\n\nexport interface HardwareAccelerationInfo {\n  type: HardwareAccelerationValue;\n  available: boolean;\n  encoders: string[];\n  decoders: string[];\n}\n\nexport const GPU_CODEC_PATTERNS = {\n  nvidia: ['_nvenc', '_cuvid'],\n  intel: ['_qsv'],\n  amd: ['_amf'],\n  vaapi: ['_vaapi'],\n  videotoolbox: ['_videotoolbox'],\n  v4l2: ['_v4l2m2m'],\n} as const;\n","export enum StreamType {\n  VIDEO = 'video',\n  AUDIO = 'audio',\n  SUBTITLE = 'subtitle',\n}\n\nexport type StreamTypeValue = StreamType | 'video' | 'audio' | 'subtitle';\n","import {\n  GPU_CODEC_PATTERNS,\n  HardwareAcceleration,\n  type HardwareAccelerationValue,\n} from '../types/hardware';\n\n/**\n * Check if a codec uses GPU acceleration\n */\nexport function isGPUCodec(codec: string): boolean {\n  return Object.values(GPU_CODEC_PATTERNS)\n    .flat()\n    .some(pattern => codec.includes(pattern));\n}\n\n/**\n * Check if a codec uses CPU\n */\nexport function isCPUCodec(codec: string): boolean {\n  return !isGPUCodec(codec);\n}\n\n/**\n * Detect which hardware acceleration type a codec uses\n */\nexport function detectHardwareType(codec: string): HardwareAccelerationValue {\n  for (const [type, patterns] of Object.entries(GPU_CODEC_PATTERNS)) {\n    if (patterns.some(pattern => codec.includes(pattern))) {\n      return type as HardwareAccelerationValue;\n    }\n  }\n  return HardwareAcceleration.CPU;\n}\n\n/**\n * Filter codecs by acceleration type\n */\nexport function filterCodecsByAcceleration(\n  codecs: string[],\n  acceleration: HardwareAccelerationValue\n): string[] {\n  const accelValue = typeof acceleration === 'string' ? acceleration : acceleration;\n\n  if (accelValue === HardwareAcceleration.ANY || accelValue === 'any') {\n    return codecs;\n  }\n\n  if (accelValue === HardwareAcceleration.CPU || accelValue === 'cpu') {\n    return codecs.filter(isCPUCodec);\n  }\n\n  const patterns = GPU_CODEC_PATTERNS[accelValue as keyof typeof GPU_CODEC_PATTERNS];\n  if (!patterns) {\n    return [];\n  }\n\n  return codecs.filter(codec => patterns.some(pattern => codec.includes(pattern)));\n}\n","import { writeFileSync, unlinkSync } from 'fs';\nimport { tmpdir } from 'os';\nimport { join } from 'path';\nimport type { InputSource, InputInfo } from '../types/input';\nimport type { ReadStream } from 'fs';\n\n/**\n * Determine the type of input source\n */\nexport function getInputType(input: InputSource): 'path' | 'buffer' | 'stream' {\n  if (typeof input === 'string') {\n    return 'path';\n  } else if (Buffer.isBuffer(input)) {\n    return 'buffer';\n  } else {\n    return 'stream';\n  }\n}\n\n/**\n * Convert input source to a file path that FFmpeg can use\n * For buffers and streams, creates a temporary file\n */\nexport async function prepareInput(input: InputSource): Promise<InputInfo> {\n  const type = getInputType(input);\n\n  if (type === 'path') {\n    return {\n      type: 'path',\n      source: input,\n    };\n  }\n\n  // Generate temporary file path\n  const tempPath = join(\n    tmpdir(),\n    `ffmpeg-${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`\n  );\n\n  if (type === 'buffer') {\n    // Write buffer to temporary file\n    writeFileSync(tempPath, input as Buffer);\n    return {\n      type: 'buffer',\n      source: input,\n      tempPath,\n    };\n  }\n\n  if (type === 'stream') {\n    // Write stream to temporary file\n    const stream = input as ReadStream;\n    return new Promise((resolve, reject) => {\n      const chunks: Buffer[] = [];\n\n      stream.on('data', chunk => {\n        chunks.push(Buffer.from(chunk));\n      });\n\n      stream.on('end', () => {\n        const buffer = Buffer.concat(chunks);\n        writeFileSync(tempPath, buffer);\n        resolve({\n          type: 'stream',\n          source: input,\n          tempPath,\n        });\n      });\n\n      stream.on('error', error => {\n        reject(error);\n      });\n    });\n  }\n\n  throw new Error(`Unsupported input type: ${typeof input}`);\n}\n\n/**\n * Clean up temporary file if it was created\n */\nexport function cleanupInput(inputInfo: InputInfo): void {\n  if (inputInfo.tempPath) {\n    try {\n      unlinkSync(inputInfo.tempPath);\n    } catch {\n      // Ignore cleanup errors\n    }\n  }\n}\n\n/**\n * Get the file path from InputInfo\n */\nexport function getInputPath(inputInfo: InputInfo): string {\n  return inputInfo.tempPath || (inputInfo.source as string);\n}\n","export enum VideoCodec {\n  // CPU Codecs\n  H264 = 'libx264',\n  H264_RGB = 'libx264rgb',\n  H265 = 'libx265',\n  VP8 = 'libvpx',\n  VP9 = 'libvpx-vp9',\n  AV1_LIBAOM = 'libaom-av1',\n  AV1_SVT = 'libsvtav1',\n  MPEG4 = 'mpeg4',\n  MPEG2 = 'mpeg2video',\n\n  // NVIDIA GPU Codecs\n  H264_NVENC = 'h264_nvenc',\n  HEVC_NVENC = 'hevc_nvenc',\n  AV1_NVENC = 'av1_nvenc',\n\n  // Intel QSV Codecs\n  H264_QSV = 'h264_qsv',\n  HEVC_QSV = 'hevc_qsv',\n  AV1_QSV = 'av1_qsv',\n\n  // AMD AMF Codecs\n  H264_AMF = 'h264_amf',\n  HEVC_AMF = 'hevc_amf',\n\n  // VAAPI Codecs\n  H264_VAAPI = 'h264_vaapi',\n  HEVC_VAAPI = 'hevc_vaapi',\n  VP8_VAAPI = 'vp8_vaapi',\n  VP9_VAAPI = 'vp9_vaapi',\n  AV1_VAAPI = 'av1_vaapi',\n\n  // VideoToolbox (macOS)\n  H264_VIDEOTOOLBOX = 'h264_videotoolbox',\n  HEVC_VIDEOTOOLBOX = 'hevc_videotoolbox',\n\n  // Copy (no re-encoding)\n  COPY = 'copy',\n}\n\nexport enum AudioCodec {\n  // Common Audio Codecs\n  AAC = 'aac',\n  MP3 = 'libmp3lame',\n  OPUS = 'libopus',\n  VORBIS = 'libvorbis',\n  FLAC = 'flac',\n  AC3 = 'ac3',\n  EAC3 = 'eac3',\n  DTS = 'dca',\n\n  // Copy (no re-encoding)\n  COPY = 'copy',\n}\n\nexport type VideoCodecValue = VideoCodec | string;\nexport type AudioCodecValue = AudioCodec | string;\n","export enum OutputFormat {\n  // Video Formats\n  MP4 = 'mp4',\n  WEBM = 'webm',\n  MKV = 'matroska',\n  AVI = 'avi',\n  MOV = 'mov',\n  FLV = 'flv',\n  MPEG = 'mpeg',\n  MPEGTS = 'mpegts',\n  OGV = 'ogg',\n\n  // Audio Formats\n  MP3 = 'mp3',\n  AAC = 'aac',\n  OGG = 'ogg',\n  OPUS = 'opus',\n  FLAC = 'flac',\n  WAV = 'wav',\n  M4A = 'm4a',\n\n  // Image Formats\n  GIF = 'gif',\n  APNG = 'apng',\n  PNG = 'image2',\n  JPEG = 'image2',\n}\n\nexport type OutputFormatValue = OutputFormat | string;\n","import type {\n  ConversionSuggestion,\n  ConversionCompatibility,\n  ConversionRecommendation,\n} from '../types/conversion';\nimport type { VideoMetadata } from '../types/metadata';\nimport { VideoCodec, AudioCodec } from '../types/codecs';\nimport { OutputFormat } from '../types/formats';\n\n/**\n * Format compatibility matrix\n * Maps source format to compatible target formats\n */\nconst FORMAT_COMPATIBILITY: Record<string, string[]> = {\n  mp4: ['mp4', 'webm', 'mkv', 'avi', 'mov', 'flv', 'ogv'],\n  webm: ['webm', 'mp4', 'mkv', 'ogv'],\n  mkv: ['mkv', 'mp4', 'webm', 'avi', 'mov'],\n  matroska: ['mkv', 'mp4', 'webm', 'avi', 'mov'],\n  avi: ['avi', 'mp4', 'mkv', 'mov'],\n  mov: ['mov', 'mp4', 'mkv', 'webm'],\n  flv: ['flv', 'mp4', 'mkv'],\n  ogv: ['ogv', 'webm', 'mkv'],\n};\n\n/**\n * Codec compatibility for direct copy (remuxing without transcoding)\n */\nexport const CODEC_CONTAINER_COMPATIBILITY: Record<string, string[]> = {\n  h264: ['mp4', 'mkv', 'mov', 'avi', 'flv', 'ts', 'm4v'],\n  hevc: ['mp4', 'mkv', 'mov', 'ts'],\n  vp8: ['webm', 'mkv'],\n  vp9: ['webm', 'mkv'],\n  av1: ['webm', 'mkv', 'mp4'],\n  mpeg4: ['mp4', 'avi', 'mkv', '3gp'],\n  aac: ['mp4', 'mov', 'mkv', 'flv', 'm4a'],\n  opus: ['webm', 'mkv', 'ogg'],\n  vorbis: ['webm', 'mkv', 'ogg'],\n  mp3: ['mp3', 'mp4', 'mkv', 'avi'],\n};\n\n/**\n * Generate conversion suggestions based on video metadata\n */\nexport function generateConversionSuggestions(\n  metadata: VideoMetadata,\n  availableFormats: { muxing: string[] },\n  availableCodecs: {\n    video: { encoders: string[] };\n    audio: { encoders: string[] };\n  }\n): ConversionSuggestion {\n  const currentFormat = metadata.format.formatName.split(',')[0];\n  const currentVideoCodec = metadata.videoCodec;\n  const currentAudioCodec = metadata.audioCodec;\n  const currentResolution = `${metadata.width}x${metadata.height}`;\n\n  // Get compatible formats based on current format\n  const baseCompatibleFormats =\n    FORMAT_COMPATIBILITY[currentFormat] || Object.keys(FORMAT_COMPATIBILITY);\n  const suggestedFormats = baseCompatibleFormats.filter(fmt =>\n    availableFormats.muxing.includes(fmt)\n  );\n\n  // Suggest video codecs (split by CPU/GPU)\n  const cpuCodecs = availableCodecs.video.encoders.filter(\n    codec =>\n      !codec.includes('_nvenc') &&\n      !codec.includes('_qsv') &&\n      !codec.includes('_amf') &&\n      !codec.includes('_vaapi') &&\n      !codec.includes('_v4l2m2m') &&\n      !codec.includes('_videotoolbox')\n  );\n\n  const gpuCodecs = availableCodecs.video.encoders.filter(\n    codec =>\n      codec.includes('_nvenc') ||\n      codec.includes('_qsv') ||\n      codec.includes('_amf') ||\n      codec.includes('_vaapi') ||\n      codec.includes('_videotoolbox')\n  );\n\n  // Suggest audio codecs\n  const suggestedAudioCodecs = availableCodecs.audio.encoders.filter(codec =>\n    ['aac', 'libmp3lame', 'libopus', 'libvorbis', 'flac', 'ac3'].some(common =>\n      codec.includes(common)\n    )\n  );\n\n  // Check if transcoding is possible\n  const canTranscode = cpuCodecs.length > 0 || gpuCodecs.length > 0;\n\n  // Check if remuxing is possible (changing container without re-encoding)\n  const codecContainers = CODEC_CONTAINER_COMPATIBILITY[currentVideoCodec] || [];\n  const canRemux = codecContainers.some(fmt => availableFormats.muxing.includes(fmt));\n\n  return {\n    currentFormat,\n    currentVideoCodec,\n    currentAudioCodec,\n    currentResolution,\n    suggestedFormats,\n    suggestedVideoCodecs: {\n      cpu: cpuCodecs,\n      gpu: gpuCodecs,\n    },\n    suggestedAudioCodecs,\n    canTranscode,\n    canRemux,\n  };\n}\n\n/**\n * Check compatibility between source and target configuration\n */\nexport function checkConversionCompatibility(\n  sourceVideoCodec: string,\n  sourceAudioCodec: string | undefined,\n  sourceFormat: string,\n  targetVideoCodec: string,\n  targetAudioCodec: string | undefined,\n  targetFormat: string\n): ConversionCompatibility {\n  const warnings: string[] = [];\n  let estimatedQuality: 'lossless' | 'high' | 'medium' | 'low' = 'high';\n\n  // Check if direct copy is possible (no transcoding needed)\n  const videoCodecMatch = sourceVideoCodec === targetVideoCodec || targetVideoCodec === 'copy';\n  const audioCodecMatch = sourceAudioCodec === targetAudioCodec || targetAudioCodec === 'copy';\n  const canDirectCopy = videoCodecMatch && audioCodecMatch;\n\n  // Determine if transcoding is required\n  const requiresTranscode = !canDirectCopy;\n\n  // Check format compatibility\n  const formatCompatible = FORMAT_COMPATIBILITY[sourceFormat]?.includes(targetFormat) ?? true;\n\n  // Estimate quality\n  if (canDirectCopy) {\n    estimatedQuality = 'lossless';\n  } else if (targetVideoCodec.includes('ffv1') || targetVideoCodec.includes('copy')) {\n    estimatedQuality = 'lossless';\n  } else if (\n    targetVideoCodec.includes('264') ||\n    targetVideoCodec.includes('265') ||\n    targetVideoCodec.includes('vp9')\n  ) {\n    estimatedQuality = 'high';\n  } else if (targetVideoCodec.includes('vp8') || targetVideoCodec.includes('mpeg4')) {\n    estimatedQuality = 'medium';\n  } else {\n    estimatedQuality = 'medium';\n  }\n\n  // Add warnings\n  if (requiresTranscode) {\n    warnings.push('Transcoding required - may lose quality');\n  }\n\n  if (!formatCompatible) {\n    warnings.push('Format combination may have compatibility issues');\n  }\n\n  if (sourceVideoCodec.includes('hevc') && targetFormat === 'avi') {\n    warnings.push('HEVC to AVI conversion may have limited support');\n  }\n\n  if (targetAudioCodec && sourceAudioCodec && !audioCodecMatch) {\n    warnings.push('Audio will be re-encoded');\n  }\n\n  return {\n    sourceFormat,\n    targetFormat,\n    sourceVideoCodec,\n    targetVideoCodec,\n    sourceAudioCodec,\n    targetAudioCodec,\n    compatible: true, // Most conversions are technically possible\n    requiresTranscode,\n    canDirectCopy,\n    estimatedQuality,\n    warnings,\n  };\n}\n\n/**\n * Get recommended conversion settings based on use case\n */\nexport function getConversionRecommendation(\n  _metadata: VideoMetadata,\n  useCase: 'web' | 'mobile' | 'quality' | 'size' | 'compatibility' = 'web'\n): ConversionRecommendation {\n  switch (useCase) {\n    case 'web':\n      // Optimize for web playback\n      return {\n        recommended: true,\n        format: OutputFormat.MP4,\n        videoCodec: VideoCodec.H264,\n        audioCodec: AudioCodec.AAC,\n        reason: 'Best browser compatibility and streaming support',\n        alternatives: [\n          {\n            format: OutputFormat.WEBM,\n            videoCodec: VideoCodec.VP9,\n            audioCodec: AudioCodec.OPUS,\n            reason: 'Modern browsers, better compression',\n          },\n          {\n            format: OutputFormat.MP4,\n            videoCodec: VideoCodec.H265,\n            audioCodec: AudioCodec.AAC,\n            reason: 'Better quality/size ratio, requires modern browsers',\n          },\n        ],\n      };\n\n    case 'mobile':\n      // Optimize for mobile devices\n      return {\n        recommended: true,\n        format: OutputFormat.MP4,\n        videoCodec: VideoCodec.H264,\n        audioCodec: AudioCodec.AAC,\n        reason: 'Universal mobile device support',\n        alternatives: [\n          {\n            format: OutputFormat.MP4,\n            videoCodec: VideoCodec.H264_VIDEOTOOLBOX,\n            audioCodec: AudioCodec.AAC,\n            reason: 'Hardware acceleration on iOS devices',\n          },\n        ],\n      };\n\n    case 'quality':\n      // Optimize for quality\n      return {\n        recommended: true,\n        format: OutputFormat.MKV,\n        videoCodec: VideoCodec.H265,\n        audioCodec: AudioCodec.FLAC,\n        reason: 'Best quality with efficient compression',\n        alternatives: [\n          {\n            format: OutputFormat.MP4,\n            videoCodec: VideoCodec.H265,\n            audioCodec: AudioCodec.AAC,\n            reason: 'High quality with better compatibility',\n          },\n          {\n            format: OutputFormat.WEBM,\n            videoCodec: VideoCodec.VP9,\n            audioCodec: AudioCodec.OPUS,\n            reason: 'Excellent quality, open format',\n          },\n        ],\n      };\n\n    case 'size':\n      // Optimize for file size\n      return {\n        recommended: true,\n        format: OutputFormat.WEBM,\n        videoCodec: VideoCodec.VP9,\n        audioCodec: AudioCodec.OPUS,\n        reason: 'Best compression efficiency',\n        alternatives: [\n          {\n            format: OutputFormat.MP4,\n            videoCodec: VideoCodec.H265,\n            audioCodec: AudioCodec.AAC,\n            reason: 'Excellent compression, better compatibility',\n          },\n        ],\n      };\n\n    case 'compatibility':\n      // Maximum compatibility\n      return {\n        recommended: true,\n        format: OutputFormat.MP4,\n        videoCodec: VideoCodec.H264,\n        audioCodec: AudioCodec.AAC,\n        reason: 'Works everywhere - maximum compatibility',\n        alternatives: [\n          {\n            format: OutputFormat.AVI,\n            videoCodec: VideoCodec.MPEG4,\n            audioCodec: AudioCodec.MP3,\n            reason: 'Legacy system support',\n          },\n        ],\n      };\n\n    default:\n      return {\n        recommended: true,\n        format: OutputFormat.MP4,\n        videoCodec: VideoCodec.H264,\n        audioCodec: AudioCodec.AAC,\n        reason: 'General purpose - good balance',\n        alternatives: [],\n      };\n  }\n}\n","import type {\n  VideoFilters,\n  AudioFilters,\n  ScaleFilter,\n  CropFilter,\n  PadFilter,\n  DeinterlaceFilter,\n  VideoDenoiseFilter,\n  SharpenFilter,\n  ColorFilter,\n  RotateFilter,\n  FlipFilter,\n  WatermarkFilter,\n  TextFilter,\n  FadeFilter,\n  VolumeFilter,\n  AudioDenoiseFilter,\n  EqualizerFilter,\n  TempoFilter,\n  PitchFilter,\n  FilterSpec,\n  UpscalingOptions,\n  DownscalingOptions,\n} from '../types/filters';\n\n/**\n * Build FFmpeg filter string from filter configuration\n */\nexport class FilterBuilder {\n  /**\n   * Build scale filter\n   */\n  static buildScaleFilter(scale: ScaleFilter): string {\n    const parts: string[] = [];\n\n    const width = scale.width ?? -1;\n    const height = scale.height ?? -1;\n    parts.push(`${width}:${height}`);\n\n    if (scale.algorithm) {\n      parts.push(`flags=${scale.algorithm}`);\n    }\n\n    if (scale.force_original_aspect_ratio) {\n      parts.push(`force_original_aspect_ratio=${scale.force_original_aspect_ratio}`);\n    }\n\n    if (scale.force_divisible_by) {\n      parts.push(`force_divisible_by=${scale.force_divisible_by}`);\n    }\n\n    return `scale=${parts.join(':')}`;\n  }\n\n  /**\n   * Build crop filter\n   */\n  static buildCropFilter(crop: CropFilter): string {\n    const w = crop.width;\n    const h = crop.height;\n    const x = crop.x ?? '(iw-w)/2'; // Center by default\n    const y = crop.y ?? '(ih-h)/2';\n\n    return `crop=${w}:${h}:${x}:${y}`;\n  }\n\n  /**\n   * Build pad filter\n   */\n  static buildPadFilter(pad: PadFilter): string {\n    const parts: string[] = [pad.width.toString(), pad.height.toString()];\n\n    if (pad.x !== undefined) parts.push(pad.x.toString());\n    if (pad.y !== undefined) parts.push(pad.y.toString());\n    if (pad.color) parts.push(pad.color);\n\n    return `pad=${parts.join(':')}`;\n  }\n\n  /**\n   * Build deinterlace filter\n   */\n  static buildDeinterlaceFilter(deinterlace: DeinterlaceFilter): string {\n    const mode = deinterlace.mode || 'yadif';\n    const parts: string[] = [];\n\n    if (deinterlace.parity) {\n      const parityMap = { tff: '0', bff: '1', auto: '-1' };\n      parts.push(parityMap[deinterlace.parity] || '-1');\n    }\n\n    if (deinterlace.deint) {\n      const deintMap = { all: '0', interlaced: '1' };\n      parts.push(deintMap[deinterlace.deint] || '0');\n    }\n\n    return parts.length > 0 ? `${mode}=${parts.join(':')}` : mode;\n  }\n\n  /**\n   * Build denoise filter\n   */\n  static buildDenoiseFilter(denoise: VideoDenoiseFilter): string {\n    const filter = denoise.filter || 'hqdn3d';\n    const parts: string[] = [];\n\n    if (denoise.luma_spatial !== undefined) parts.push(denoise.luma_spatial.toString());\n    if (denoise.chroma_spatial !== undefined) parts.push(denoise.chroma_spatial.toString());\n    if (denoise.luma_tmp !== undefined) parts.push(denoise.luma_tmp.toString());\n    if (denoise.chroma_tmp !== undefined) parts.push(denoise.chroma_tmp.toString());\n\n    return parts.length > 0 ? `${filter}=${parts.join(':')}` : filter;\n  }\n\n  /**\n   * Build sharpen (unsharp) filter\n   */\n  static buildSharpenFilter(sharpen: SharpenFilter): string {\n    const parts: string[] = [];\n\n    if (sharpen.luma_msize_x !== undefined) parts.push(`luma_msize_x=${sharpen.luma_msize_x}`);\n    if (sharpen.luma_msize_y !== undefined) parts.push(`luma_msize_y=${sharpen.luma_msize_y}`);\n    if (sharpen.luma_amount !== undefined) parts.push(`luma_amount=${sharpen.luma_amount}`);\n    if (sharpen.chroma_msize_x !== undefined)\n      parts.push(`chroma_msize_x=${sharpen.chroma_msize_x}`);\n    if (sharpen.chroma_msize_y !== undefined)\n      parts.push(`chroma_msize_y=${sharpen.chroma_msize_y}`);\n    if (sharpen.chroma_amount !== undefined) parts.push(`chroma_amount=${sharpen.chroma_amount}`);\n\n    return parts.length > 0 ? `unsharp=${parts.join(':')}` : 'unsharp';\n  }\n\n  /**\n   * Build color (eq) filter\n   */\n  static buildColorFilter(color: ColorFilter): string {\n    const parts: string[] = [];\n\n    if (color.brightness !== undefined) parts.push(`brightness=${color.brightness}`);\n    if (color.contrast !== undefined) parts.push(`contrast=${color.contrast}`);\n    if (color.saturation !== undefined) parts.push(`saturation=${color.saturation}`);\n    if (color.gamma !== undefined) parts.push(`gamma=${color.gamma}`);\n    if (color.gamma_r !== undefined) parts.push(`gamma_r=${color.gamma_r}`);\n    if (color.gamma_g !== undefined) parts.push(`gamma_g=${color.gamma_g}`);\n    if (color.gamma_b !== undefined) parts.push(`gamma_b=${color.gamma_b}`);\n\n    return `eq=${parts.join(':')}`;\n  }\n\n  /**\n   * Build rotate filter\n   */\n  static buildRotateFilter(rotate: RotateFilter): string {\n    const parts: string[] = [`a=${rotate.angle}`];\n\n    if (rotate.fillcolor) parts.push(`fillcolor=${rotate.fillcolor}`);\n    if (rotate.bilinear !== undefined) parts.push(`bilinear=${rotate.bilinear ? '1' : '0'}`);\n\n    return `rotate=${parts.join(':')}`;\n  }\n\n  /**\n   * Build flip filter\n   */\n  static buildFlipFilter(flip: FlipFilter): string {\n    const filters: string[] = [];\n\n    if (flip.horizontal) filters.push('hflip');\n    if (flip.vertical) filters.push('vflip');\n\n    return filters.join(',');\n  }\n\n  /**\n   * Build watermark (overlay) filter\n   */\n  static buildWatermarkFilter(watermark: WatermarkFilter): string {\n    const parts: string[] = [];\n\n    if (watermark.x !== undefined) parts.push(`x=${watermark.x}`);\n    if (watermark.y !== undefined) parts.push(`y=${watermark.y}`);\n\n    if (watermark.opacity !== undefined) {\n      // Need to use format and colorchannelmixer for opacity\n      return `overlay=${parts.join(':')}:format=auto:alpha=${watermark.opacity}`;\n    }\n\n    if (watermark.enable) parts.push(`enable='${watermark.enable}'`);\n\n    return `overlay=${parts.join(':')}`;\n  }\n\n  /**\n   * Build text (drawtext) filter\n   */\n  static buildTextFilter(text: TextFilter): string {\n    const parts: string[] = [`text='${text.text.replace(/'/g, \"\\\\'\")}'`];\n\n    if (text.fontfile) parts.push(`fontfile=${text.fontfile}`);\n    if (text.fontsize) parts.push(`fontsize=${text.fontsize}`);\n    if (text.fontcolor) parts.push(`fontcolor=${text.fontcolor}`);\n    if (text.x !== undefined) parts.push(`x=${text.x}`);\n    if (text.y !== undefined) parts.push(`y=${text.y}`);\n    if (text.shadowcolor) parts.push(`shadowcolor=${text.shadowcolor}`);\n    if (text.shadowx !== undefined) parts.push(`shadowx=${text.shadowx}`);\n    if (text.shadowy !== undefined) parts.push(`shadowy=${text.shadowy}`);\n    if (text.borderw !== undefined) parts.push(`borderw=${text.borderw}`);\n    if (text.bordercolor) parts.push(`bordercolor=${text.bordercolor}`);\n\n    return `drawtext=${parts.join(':')}`;\n  }\n\n  /**\n   * Build fade filter\n   */\n  static buildFadeFilter(fade: FadeFilter): string {\n    const parts: string[] = [`type=${fade.type}`];\n\n    if (fade.start_frame !== undefined) parts.push(`start_frame=${fade.start_frame}`);\n    if (fade.nb_frames !== undefined) parts.push(`nb_frames=${fade.nb_frames}`);\n    if (fade.start_time !== undefined) parts.push(`start_time=${fade.start_time}`);\n    if (fade.duration !== undefined) parts.push(`duration=${fade.duration}`);\n    if (fade.color) parts.push(`color=${fade.color}`);\n\n    return `fade=${parts.join(':')}`;\n  }\n\n  /**\n   * Build volume filter\n   */\n  static buildVolumeFilter(volume: VolumeFilter): string {\n    const parts: string[] = [`volume=${volume.volume}`];\n\n    if (volume.precision) parts.push(`precision=${volume.precision}`);\n\n    return parts.join(':');\n  }\n\n  /**\n   * Build audio denoise filter\n   */\n  static buildAudioDenoiseFilter(denoise: AudioDenoiseFilter): string {\n    const parts: string[] = [];\n\n    if (denoise.noise_reduction !== undefined) {\n      parts.push(`nr=${denoise.noise_reduction}`);\n    }\n\n    if (denoise.noise_type) {\n      parts.push(`nf=${denoise.noise_type}`);\n    }\n\n    return parts.length > 0 ? `afftdn=${parts.join(':')}` : 'afftdn';\n  }\n\n  /**\n   * Build equalizer filter\n   */\n  static buildEqualizerFilter(eq: EqualizerFilter): string {\n    const parts: string[] = [`f=${eq.frequency}`];\n\n    if (eq.width_type) parts.push(`t=${eq.width_type}`);\n    if (eq.width !== undefined) parts.push(`w=${eq.width}`);\n    if (eq.gain !== undefined) parts.push(`g=${eq.gain}`);\n\n    return `equalizer=${parts.join(':')}`;\n  }\n\n  /**\n   * Build tempo filter\n   */\n  static buildTempoFilter(tempo: TempoFilter): string {\n    return `atempo=${tempo.tempo}`;\n  }\n\n  /**\n   * Build pitch filter\n   */\n  static buildPitchFilter(pitch: PitchFilter): string {\n    return `asetrate=44100*2^(${pitch.pitch}/12),aresample=44100`;\n  }\n\n  /**\n   * Build upscaling filter chain\n   */\n  static buildUpscaleFilter(upscale: UpscalingOptions): string[] {\n    const filters: string[] = [];\n\n    // Denoise before scaling if requested\n    if (upscale.denoiseBeforeScale) {\n      filters.push('hqdn3d=4:3:6:4.5');\n    }\n\n    // Main scaling\n    const scaleFilter = `scale=${upscale.targetWidth}:${upscale.targetHeight}:flags=${upscale.algorithm}`;\n    filters.push(scaleFilter);\n\n    // Enhance sharpness after upscaling if requested\n    if (upscale.enhanceSharpness) {\n      const amount = upscale.sharpnessAmount || 1.0;\n      filters.push(`unsharp=5:5:${amount}:5:5:0.0`);\n    }\n\n    return filters;\n  }\n\n  /**\n   * Build downscaling filter chain\n   */\n  static buildDownscaleFilter(downscale: DownscalingOptions): string[] {\n    const filters: string[] = [];\n\n    // Deinterlace before downscaling if requested\n    if (downscale.deinterlace) {\n      filters.push('yadif=0:-1:0');\n    }\n\n    // Use high-quality algorithm for detail preservation\n    const algorithm = downscale.preserveDetails ? 'lanczos' : downscale.algorithm;\n\n    const scaleFilter = `scale=${downscale.targetWidth}:${downscale.targetHeight}:flags=${algorithm}`;\n    filters.push(scaleFilter);\n\n    return filters;\n  }\n\n  /**\n   * Build complete video filter chain\n   */\n  static buildVideoFilters(filters: VideoFilters): string {\n    const filterArray: string[] = [];\n\n    // Order matters for video filters!\n\n    // 1. Deinterlace first (if needed)\n    if (filters.deinterlace) {\n      filterArray.push(this.buildDeinterlaceFilter(filters.deinterlace));\n    }\n\n    // 2. Crop before scaling\n    if (filters.crop) {\n      filterArray.push(this.buildCropFilter(filters.crop));\n    }\n\n    // 3. Denoise before scaling\n    if (filters.denoise) {\n      filterArray.push(this.buildDenoiseFilter(filters.denoise));\n    }\n\n    // 4. Scale\n    if (filters.scale) {\n      filterArray.push(this.buildScaleFilter(filters.scale));\n    }\n\n    // 5. Pad after scaling\n    if (filters.pad) {\n      filterArray.push(this.buildPadFilter(filters.pad));\n    }\n\n    // 6. Color correction\n    if (filters.color) {\n      filterArray.push(this.buildColorFilter(filters.color));\n    }\n\n    // 7. Sharpen\n    if (filters.sharpen) {\n      filterArray.push(this.buildSharpenFilter(filters.sharpen));\n    }\n\n    // 8. Transformations\n    if (filters.rotate) {\n      filterArray.push(this.buildRotateFilter(filters.rotate));\n    }\n\n    if (filters.flip) {\n      const flipFilters = this.buildFlipFilter(filters.flip);\n      if (flipFilters) filterArray.push(flipFilters);\n    }\n\n    // 9. Text overlay\n    if (filters.text) {\n      filterArray.push(this.buildTextFilter(filters.text));\n    }\n\n    // 10. Fade effects\n    if (filters.fade) {\n      filterArray.push(this.buildFadeFilter(filters.fade));\n    }\n\n    // 11. Custom filters (last)\n    if (filters.custom) {\n      filterArray.push(...filters.custom);\n    }\n\n    return filterArray.join(',');\n  }\n\n  /**\n   * Build complete audio filter chain\n   */\n  static buildAudioFilters(filters: AudioFilters): string {\n    const filterArray: string[] = [];\n\n    // 1. Denoise first\n    if (filters.denoise) {\n      filterArray.push(this.buildAudioDenoiseFilter(filters.denoise));\n    }\n\n    // 2. Equalizer\n    if (filters.equalizer) {\n      filters.equalizer.forEach(eq => {\n        filterArray.push(this.buildEqualizerFilter(eq));\n      });\n    }\n\n    // 3. Tempo changes\n    if (filters.tempo) {\n      filterArray.push(this.buildTempoFilter(filters.tempo));\n    }\n\n    // 4. Pitch changes\n    if (filters.pitch) {\n      filterArray.push(this.buildPitchFilter(filters.pitch));\n    }\n\n    // 5. Volume (should be last before custom)\n    if (filters.volume) {\n      filterArray.push(this.buildVolumeFilter(filters.volume));\n    }\n\n    // 6. Custom filters (last)\n    if (filters.custom) {\n      filterArray.push(...filters.custom);\n    }\n\n    return filterArray.join(',');\n  }\n\n  /**\n   * Build complex filter graph\n   */\n  static buildComplexFilter(specs: FilterSpec[]): string {\n    return specs\n      .map(spec => {\n        const inputs = spec.inputs?.map(i => `[${i}]`).join('') || '';\n        const outputs = spec.outputs?.map(o => `[${o}]`).join('') || '';\n\n        let filter = spec.filter;\n        if (spec.options && Object.keys(spec.options).length > 0) {\n          const opts = Object.entries(spec.options)\n            .map(([k, v]) => `${k}=${v}`)\n            .join(':');\n          filter = `${filter}=${opts}`;\n        }\n\n        return `${inputs}${filter}${outputs}`;\n      })\n      .join(';');\n  }\n}\n","import { HardwareAcceleration, type HardwareAccelerationValue } from '../types/hardware';\nimport { VideoCodec, type VideoCodecValue } from '../types/codecs';\nimport { execSync } from 'child_process';\n\n/**\n * Hardware-accelerated codec mapping\n */\nexport const HARDWARE_CODEC_MAP: Record<string, Record<string, string>> = {\n  // NVIDIA NVENC\n  [HardwareAcceleration.NVIDIA]: {\n    h264: VideoCodec.H264_NVENC,\n    libx264: VideoCodec.H264_NVENC,\n    h265: VideoCodec.HEVC_NVENC,\n    libx265: VideoCodec.HEVC_NVENC,\n    hevc: VideoCodec.HEVC_NVENC,\n    av1: VideoCodec.AV1_NVENC,\n  },\n  nvenc: {\n    h264: VideoCodec.H264_NVENC,\n    libx264: VideoCodec.H264_NVENC,\n    h265: VideoCodec.HEVC_NVENC,\n    libx265: VideoCodec.HEVC_NVENC,\n    hevc: VideoCodec.HEVC_NVENC,\n    av1: VideoCodec.AV1_NVENC,\n  },\n  cuda: {\n    h264: VideoCodec.H264_NVENC,\n    libx264: VideoCodec.H264_NVENC,\n    h265: VideoCodec.HEVC_NVENC,\n    libx265: VideoCodec.HEVC_NVENC,\n    hevc: VideoCodec.HEVC_NVENC,\n    av1: VideoCodec.AV1_NVENC,\n  },\n\n  // Intel Quick Sync\n  [HardwareAcceleration.INTEL]: {\n    h264: VideoCodec.H264_QSV,\n    libx264: VideoCodec.H264_QSV,\n    h265: VideoCodec.HEVC_QSV,\n    libx265: VideoCodec.HEVC_QSV,\n    hevc: VideoCodec.HEVC_QSV,\n    av1: VideoCodec.AV1_QSV,\n    vp9: 'vp9_qsv',\n  },\n  qsv: {\n    h264: VideoCodec.H264_QSV,\n    libx264: VideoCodec.H264_QSV,\n    h265: VideoCodec.HEVC_QSV,\n    libx265: VideoCodec.HEVC_QSV,\n    hevc: VideoCodec.HEVC_QSV,\n    av1: VideoCodec.AV1_QSV,\n    vp9: 'vp9_qsv',\n  },\n\n  // AMD AMF\n  [HardwareAcceleration.AMD]: {\n    h264: VideoCodec.H264_AMF,\n    libx264: VideoCodec.H264_AMF,\n    h265: VideoCodec.HEVC_AMF,\n    libx265: VideoCodec.HEVC_AMF,\n    hevc: VideoCodec.HEVC_AMF,\n  },\n  amf: {\n    h264: VideoCodec.H264_AMF,\n    libx264: VideoCodec.H264_AMF,\n    h265: VideoCodec.HEVC_AMF,\n    libx265: VideoCodec.HEVC_AMF,\n    hevc: VideoCodec.HEVC_AMF,\n  },\n\n  // VAAPI (Linux)\n  [HardwareAcceleration.VAAPI]: {\n    h264: VideoCodec.H264_VAAPI,\n    libx264: VideoCodec.H264_VAAPI,\n    h265: VideoCodec.HEVC_VAAPI,\n    libx265: VideoCodec.HEVC_VAAPI,\n    hevc: VideoCodec.HEVC_VAAPI,\n    vp8: VideoCodec.VP8_VAAPI,\n    vp9: VideoCodec.VP9_VAAPI,\n    av1: VideoCodec.AV1_VAAPI,\n  },\n\n  // VideoToolbox (macOS)\n  [HardwareAcceleration.VIDEOTOOLBOX]: {\n    h264: VideoCodec.H264_VIDEOTOOLBOX,\n    libx264: VideoCodec.H264_VIDEOTOOLBOX,\n    h265: VideoCodec.HEVC_VIDEOTOOLBOX,\n    libx265: VideoCodec.HEVC_VIDEOTOOLBOX,\n    hevc: VideoCodec.HEVC_VIDEOTOOLBOX,\n  },\n};\n\n/**\n * Detect available hardware acceleration\n */\nexport function detectHardwareAcceleration(\n  ffmpegPath: string = 'ffmpeg'\n): HardwareAccelerationValue[] {\n  try {\n    const output = execSync(`${ffmpegPath} -hide_banner -hwaccels`, { encoding: 'utf-8' });\n    const lines = output.split('\\n');\n\n    const available: HardwareAccelerationValue[] = [];\n\n    for (const line of lines) {\n      const trimmed = line.trim().toLowerCase();\n\n      if (trimmed === 'cuda' || trimmed.includes('nvenc')) {\n        if (!available.includes(HardwareAcceleration.NVIDIA)) {\n          available.push(HardwareAcceleration.NVIDIA);\n        }\n      } else if (trimmed === 'qsv') {\n        available.push(HardwareAcceleration.INTEL);\n      } else if (trimmed === 'amf' || trimmed === 'd3d11va') {\n        if (!available.includes(HardwareAcceleration.AMD)) {\n          available.push(HardwareAcceleration.AMD);\n        }\n      } else if (trimmed === 'vaapi') {\n        available.push(HardwareAcceleration.VAAPI);\n      } else if (trimmed === 'videotoolbox') {\n        available.push(HardwareAcceleration.VIDEOTOOLBOX);\n      } else if (trimmed === 'dxva2') {\n        // Windows DirectX acceleration\n        available.push('dxva2' as HardwareAccelerationValue);\n      }\n    }\n\n    return available;\n  } catch {\n    return [];\n  }\n}\n\n/**\n * Get hardware-accelerated codec for a given CPU codec\n */\nexport function getHardwareCodec(\n  cpuCodec: VideoCodecValue,\n  acceleration: HardwareAccelerationValue\n): VideoCodecValue | null {\n  const codecMap = HARDWARE_CODEC_MAP[acceleration];\n  if (!codecMap) return null;\n\n  // Normalize codec name\n  const normalizedCodec = cpuCodec.toLowerCase().replace('lib', '');\n\n  return codecMap[normalizedCodec] || codecMap[cpuCodec] || null;\n}\n\n/**\n * Check if hardware acceleration is available\n */\nexport function isHardwareAccelerationAvailable(\n  acceleration: HardwareAccelerationValue,\n  ffmpegPath: string = 'ffmpeg'\n): boolean {\n  const available = detectHardwareAcceleration(ffmpegPath);\n  return available.includes(acceleration);\n}\n\n/**\n * Get best available hardware acceleration for current system\n */\nexport function getBestHardwareAcceleration(\n  ffmpegPath: string = 'ffmpeg'\n): HardwareAccelerationValue | null {\n  const available = detectHardwareAcceleration(ffmpegPath);\n\n  if (available.length === 0) {\n    return null;\n  }\n\n  // Priority order: NVIDIA > INTEL > AMD > VAAPI > VideoToolbox\n  const priority = [\n    HardwareAcceleration.NVIDIA,\n    HardwareAcceleration.INTEL,\n    HardwareAcceleration.AMD,\n    HardwareAcceleration.VAAPI,\n    HardwareAcceleration.VIDEOTOOLBOX,\n  ];\n\n  for (const hwAccel of priority) {\n    if (available.includes(hwAccel)) {\n      return hwAccel;\n    }\n  }\n\n  return available[0];\n}\n\n/**\n * Auto-select hardware acceleration and codec\n */\nexport function autoSelectHardwareEncoding(\n  desiredCodec: VideoCodecValue,\n  ffmpegPath: string = 'ffmpeg'\n): {\n  codec: VideoCodecValue;\n  acceleration?: HardwareAccelerationValue;\n  ffmpegHwaccel?: string; // Actual FFmpeg hwaccel flag value\n  isHardware: boolean;\n} {\n  // Map acceleration types to FFmpeg hwaccel names\n  const hwaccelMap: Record<string, string> = {\n    [HardwareAcceleration.NVIDIA]: 'cuda',\n    [HardwareAcceleration.INTEL]: 'qsv',\n    [HardwareAcceleration.AMD]: 'amf',\n    [HardwareAcceleration.VAAPI]: 'vaapi',\n    [HardwareAcceleration.VIDEOTOOLBOX]: 'videotoolbox',\n    [HardwareAcceleration.V4L2]: 'v4l2m2m',\n  };\n\n  // Try to find best hardware acceleration\n  const hwAccel = getBestHardwareAcceleration(ffmpegPath);\n\n  if (!hwAccel) {\n    // No hardware acceleration available\n    return {\n      codec: desiredCodec,\n      isHardware: false,\n    };\n  }\n\n  // Get hardware-accelerated version of codec\n  const hwCodec = getHardwareCodec(desiredCodec, hwAccel);\n\n  if (hwCodec) {\n    return {\n      codec: hwCodec,\n      acceleration: hwAccel,\n      ffmpegHwaccel: hwaccelMap[hwAccel] || hwAccel,\n      isHardware: true,\n    };\n  }\n\n  // Hardware acceleration available but codec not supported\n  return {\n    codec: desiredCodec,\n    isHardware: false,\n  };\n}\n\n/**\n * Get hardware acceleration info for display\n */\nexport function getHardwareAccelerationInfo(ffmpegPath: string = 'ffmpeg'): {\n  available: HardwareAccelerationValue[];\n  best: HardwareAccelerationValue | null;\n  capabilities: Record<HardwareAccelerationValue, string[]>;\n} {\n  const available = detectHardwareAcceleration(ffmpegPath);\n  const best = getBestHardwareAcceleration(ffmpegPath);\n  const capabilities: Record<string, string[]> = {};\n\n  // Get codecs for each hardware acceleration\n  available.forEach(hwAccel => {\n    capabilities[hwAccel] = Object.values(HARDWARE_CODEC_MAP[hwAccel] || {});\n  });\n\n  return {\n    available,\n    best,\n    capabilities: capabilities as Record<HardwareAccelerationValue, string[]>,\n  };\n}\n","import type {\n  ConversionConfig,\n  VideoConfig,\n  AudioConfig,\n  AdvancedOptions,\n} from '../types/conversion-config';\nimport { FilterBuilder } from './filter-builder';\nimport { autoSelectHardwareEncoding } from './hardware-acceleration-helper';\n\n/**\n * Generate FFmpeg command arguments from configuration\n */\nexport class CommandGenerator {\n  /**\n   * Generate complete FFmpeg command arguments\n   */\n  static generate(config: ConversionConfig, ffmpegPath: string = 'ffmpeg'): string[] {\n    const args: string[] = [];\n\n    // Global options\n    args.push('-hide_banner');\n\n    // Map our enum to FFmpeg hwaccel names\n    const hwAccelMap: Record<string, string> = {\n      nvidia: 'cuda',\n      intel: 'qsv',\n      amd: 'amf',\n      vaapi: 'vaapi',\n      videotoolbox: 'videotoolbox',\n      v4l2: 'v4l2m2m',\n    };\n\n    // Process hardware acceleration config\n    let hwAccelType: string | undefined;\n    let useHardwareCodec = false;\n\n    if (config.hardwareAcceleration) {\n      if (typeof config.hardwareAcceleration === 'string') {\n        // Simple: just the acceleration type\n        const mapped = hwAccelMap[config.hardwareAcceleration] || config.hardwareAcceleration;\n        hwAccelType = mapped;\n        useHardwareCodec = true;\n      } else if (config.hardwareAcceleration.enabled) {\n        // Advanced config\n        const accelType = config.hardwareAcceleration.type;\n        if (accelType) {\n          hwAccelType = hwAccelMap[accelType] || accelType;\n        }\n        useHardwareCodec = config.hardwareAcceleration.preferHardware !== false;\n      }\n    }\n\n    // Add hardware acceleration flag (must come before input)\n    if (hwAccelType) {\n      args.push('-hwaccel', hwAccelType);\n    }\n\n    // Auto-select hardware codec if enabled\n    let finalVideoConfig = config.video;\n    if (useHardwareCodec && config.video?.codec && !config.video.disabled) {\n      const hwSelection = autoSelectHardwareEncoding(config.video.codec, ffmpegPath);\n\n      if (hwSelection.isHardware) {\n        // Use hardware codec\n        finalVideoConfig = {\n          ...config.video,\n          codec: hwSelection.codec,\n        };\n\n        // Set hwaccel if not already set\n        if (!hwAccelType && hwSelection.ffmpegHwaccel) {\n          args.splice(2, 0, '-hwaccel', hwSelection.ffmpegHwaccel); // Insert after -hide_banner\n        }\n      } else if (\n        typeof config.hardwareAcceleration === 'object' &&\n        config.hardwareAcceleration.fallbackToCPU === false\n      ) {\n        // Hardware requested but not available, and no fallback allowed\n        throw new Error(\n          `Hardware acceleration requested but codec ${config.video.codec} is not available with hardware acceleration`\n        );\n      }\n    }\n\n    // Threading\n    if (config.options?.threads !== undefined) {\n      args.push('-threads', config.options.threads.toString());\n    }\n\n    // Input options\n    if (config.options?.inputOptions) {\n      args.push(...config.options.inputOptions);\n    }\n\n    // Timing (input seeking - faster but less accurate)\n    if (config.timing?.fastSeek && config.timing?.seek !== undefined) {\n      args.push('-ss', this.formatTime(config.timing.seek));\n    }\n\n    // Input file (should already be a path string after prepareInput in execution engine)\n    const inputPath = typeof config.input === 'string' ? config.input : 'pipe:0';\n    args.push('-i', inputPath);\n\n    // Timing (output seeking - slower but accurate)\n    if (config.timing && !config.timing.fastSeek) {\n      if (config.timing.seek !== undefined) {\n        args.push('-ss', this.formatTime(config.timing.seek));\n      }\n\n      if (config.timing.duration !== undefined) {\n        args.push('-t', this.formatTime(config.timing.duration));\n      } else if (config.timing.to !== undefined) {\n        args.push('-to', this.formatTime(config.timing.to));\n      }\n    }\n\n    // Video configuration (use potentially modified config with hardware codec)\n    if (finalVideoConfig) {\n      this.addVideoArgs(args, finalVideoConfig);\n    }\n\n    // Audio configuration\n    if (config.audio) {\n      this.addAudioArgs(args, config.audio);\n    }\n\n    // Format\n    if (config.format) {\n      args.push('-f', config.format);\n    }\n\n    // Complex filters (multi-stream)\n    if (config.complexFilters && config.complexFilters.length > 0) {\n      const complexFilter = FilterBuilder.buildComplexFilter(config.complexFilters);\n      args.push('-filter_complex', complexFilter);\n    }\n\n    // Advanced options\n    if (config.options) {\n      this.addAdvancedOptions(args, config.options);\n    }\n\n    // Output options\n    if (config.options?.outputOptions) {\n      args.push(...config.options.outputOptions);\n    }\n\n    // Output file\n    const output = typeof config.output === 'string' ? config.output : 'pipe:1';\n    args.push('-y', output); // -y to overwrite\n\n    return args;\n  }\n\n  /**\n   * Add video-related arguments\n   */\n  private static addVideoArgs(args: string[], video: VideoConfig): void {\n    // Disable video\n    if (video.disabled) {\n      args.push('-vn');\n      return;\n    }\n\n    // Codec\n    if (video.codec) {\n      args.push('-c:v', video.codec);\n    }\n\n    // Bitrate\n    if (video.bitrate) {\n      const bitrate = typeof video.bitrate === 'number' ? `${video.bitrate}` : video.bitrate;\n      args.push('-b:v', bitrate);\n    }\n\n    // Quality (CRF for h264/h265, -q:v for others)\n    if (video.quality !== undefined) {\n      if (video.codec?.includes('264') || video.codec?.includes('265')) {\n        args.push('-crf', video.quality.toString());\n      } else {\n        args.push('-q:v', video.quality.toString());\n      }\n    }\n\n    // FPS\n    if (video.fps) {\n      args.push('-r', video.fps.toString());\n    }\n\n    // Size (resolution)\n    if (video.size) {\n      const size = this.formatSize(video.size);\n      if (size) {\n        args.push('-s', size);\n      }\n    }\n\n    // Aspect ratio\n    if (video.aspectRatio) {\n      args.push('-aspect', video.aspectRatio.toString());\n    }\n\n    // Preset\n    if (video.preset) {\n      args.push('-preset', video.preset);\n    }\n\n    // Profile\n    if (video.profile) {\n      args.push('-profile:v', video.profile);\n    }\n\n    // Level\n    if (video.level) {\n      args.push('-level', video.level);\n    }\n\n    // Pixel format\n    if (video.pixelFormat) {\n      args.push('-pix_fmt', video.pixelFormat);\n    }\n\n    // Keyframe interval\n    if (video.keyframeInterval) {\n      args.push('-g', video.keyframeInterval.toString());\n    }\n\n    // B-frames\n    if (video.bframes !== undefined) {\n      args.push('-bf', video.bframes.toString());\n    }\n\n    // Reference frames\n    if (video.refs !== undefined) {\n      args.push('-refs', video.refs.toString());\n    }\n\n    // Frame limit\n    if (video.frames !== undefined) {\n      args.push('-frames:v', video.frames.toString());\n    }\n\n    // Loop (for GIFs mainly)\n    if (video.loop !== undefined) {\n      args.push('-loop', video.loop.toString());\n    }\n\n    // Filters\n    this.addVideoFilters(args, video);\n  }\n\n  /**\n   * Add video filters\n   */\n  private static addVideoFilters(args: string[], video: VideoConfig): void {\n    const filterParts: string[] = [];\n\n    // Upscaling\n    if (video.upscale) {\n      const upscaleFilters = FilterBuilder.buildUpscaleFilter(video.upscale);\n      filterParts.push(...upscaleFilters);\n    }\n\n    // Downscaling\n    if (video.downscale) {\n      const downscaleFilters = FilterBuilder.buildDownscaleFilter(video.downscale);\n      filterParts.push(...downscaleFilters);\n    }\n\n    // Standard filters\n    if (video.filters) {\n      const filterString = FilterBuilder.buildVideoFilters(video.filters);\n      if (filterString) {\n        filterParts.push(filterString);\n      }\n    }\n\n    // Combine all filters\n    if (filterParts.length > 0) {\n      args.push('-vf', filterParts.join(','));\n    }\n  }\n\n  /**\n   * Add audio-related arguments\n   */\n  private static addAudioArgs(args: string[], audio: AudioConfig): void {\n    // Disable audio\n    if (audio.disabled) {\n      args.push('-an');\n      return;\n    }\n\n    // Codec\n    if (audio.codec) {\n      args.push('-c:a', audio.codec);\n    }\n\n    // Bitrate\n    if (audio.bitrate) {\n      const bitrate = typeof audio.bitrate === 'number' ? `${audio.bitrate}` : audio.bitrate;\n      args.push('-b:a', bitrate);\n    }\n\n    // Quality\n    if (audio.quality !== undefined) {\n      args.push('-q:a', audio.quality.toString());\n    }\n\n    // Channels\n    if (audio.channels) {\n      args.push('-ac', audio.channels.toString());\n    }\n\n    // Sample rate\n    if (audio.frequency) {\n      args.push('-ar', audio.frequency.toString());\n    }\n\n    // Profile\n    if (audio.profile) {\n      args.push('-profile:a', audio.profile);\n    }\n\n    // Volume normalization\n    if (audio.volumeNormalization) {\n      args.push('-af', 'loudnorm');\n    }\n\n    // Filters\n    if (audio.filters) {\n      const filterString = FilterBuilder.buildAudioFilters(audio.filters);\n      if (filterString) {\n        // Combine with volume normalization if both are present\n        if (audio.volumeNormalization) {\n          const existingAf = args[args.indexOf('-af') + 1];\n          args[args.indexOf('-af') + 1] = `${existingAf},${filterString}`;\n        } else {\n          args.push('-af', filterString);\n        }\n      }\n    }\n  }\n\n  /**\n   * Add advanced options\n   */\n  private static addAdvancedOptions(args: string[], options: AdvancedOptions): void {\n    // Two-pass encoding\n    if (options.twoPass) {\n      const passlogfile = options.passlogfile || 'ffmpeg2pass';\n      args.push('-pass', '1', '-passlogfile', passlogfile);\n    }\n\n    // Metadata\n    if (options.metadata) {\n      Object.entries(options.metadata).forEach(([key, value]) => {\n        args.push('-metadata', `${key}=${value}`);\n      });\n    }\n\n    // Subtitles\n    if (options.subtitles) {\n      if (options.burnSubtitles) {\n        // Burn subtitles into video\n        args.push('-vf', `subtitles=${options.subtitles}`);\n      } else {\n        // Include as separate stream\n        args.push('-i', options.subtitles, '-c:s', 'mov_text');\n      }\n    }\n  }\n\n  /**\n   * Format time value (seconds or timestamp)\n   */\n  private static formatTime(time: string | number): string {\n    if (typeof time === 'string') {\n      return time; // Already formatted (e.g., '00:01:30')\n    }\n\n    // Convert seconds to HH:MM:SS format\n    const hours = Math.floor(time / 3600);\n    const minutes = Math.floor((time % 3600) / 60);\n    const seconds = time % 60;\n\n    return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;\n  }\n\n  /**\n   * Format size specification\n   */\n  private static formatSize(size: VideoConfig['size']): string | null {\n    if (!size) return null;\n\n    if (typeof size === 'string') {\n      return size; // Already formatted (e.g., '1920x1080', '50%')\n    }\n\n    if (typeof size === 'object') {\n      const w = size.width === '?' ? '-1' : size.width;\n      const h = size.height === '?' ? '-1' : size.height;\n      return `${w}x${h}`;\n    }\n\n    return null;\n  }\n\n  /**\n   * Generate command string for display/logging\n   */\n  static generateCommandString(config: ConversionConfig, ffmpegPath: string = 'ffmpeg'): string {\n    const args = this.generate(config);\n    return `${ffmpegPath} ${args.join(' ')}`;\n  }\n\n  /**\n   * Validate configuration before generation\n   */\n  static validate(config: ConversionConfig): { valid: boolean; errors: string[] } {\n    const errors: string[] = [];\n\n    // Check required fields\n    if (!config.input) {\n      errors.push('Input is required');\n    }\n\n    if (!config.output) {\n      errors.push('Output is required');\n    }\n\n    // Validate video config\n    if (config.video) {\n      if (config.video.upscale && config.video.downscale) {\n        errors.push('Cannot use both upscale and downscale');\n      }\n\n      if (config.video.upscale && config.video.size) {\n        errors.push('Cannot use both upscale and size');\n      }\n    }\n\n    // Validate timing\n    if (config.timing) {\n      if (config.timing.duration && config.timing.to) {\n        errors.push('Cannot use both duration and to');\n      }\n    }\n\n    return {\n      valid: errors.length === 0,\n      errors,\n    };\n  }\n}\n","import type { ProgressInfo } from '../types/conversion-config';\n\n/**\n * Parse FFmpeg progress output from stderr\n */\nexport class ProgressParser {\n  private duration: number = 0;\n\n  /**\n   * Set total duration for percentage calculation\n   */\n  setDuration(seconds: number): void {\n    this.duration = seconds;\n  }\n\n  /**\n   * Parse progress line from FFmpeg stderr\n   * Example: \"frame= 1234 fps= 30 q=28.0 size= 1024kB time=00:00:41.23 bitrate=203.5kbits/s speed=1.5x\"\n   */\n  parseProgress(line: string): ProgressInfo | null {\n    // FFmpeg progress lines typically contain \"time=\" and \"bitrate=\"\n    if (!line.includes('time=') || !line.includes('bitrate=')) {\n      return null;\n    }\n\n    const progress: Partial<ProgressInfo> = {};\n\n    // Parse frame number\n    const frameMatch = line.match(/frame=\\s*(\\d+)/);\n    if (frameMatch) {\n      progress.frames = parseInt(frameMatch[1]);\n    }\n\n    // Parse current FPS\n    const fpsMatch = line.match(/fps=\\s*([\\d.]+)/);\n    if (fpsMatch) {\n      progress.currentFps = parseFloat(fpsMatch[1]);\n    }\n\n    // Parse current bitrate\n    const bitrateMatch = line.match(/bitrate=\\s*([\\d.]+)kbits\\/s/);\n    if (bitrateMatch) {\n      progress.currentKbps = parseFloat(bitrateMatch[1]);\n    }\n\n    // Parse target size\n    const sizeMatch = line.match(/size=\\s*(\\d+)kB/);\n    if (sizeMatch) {\n      progress.targetSize = parseInt(sizeMatch[1]);\n    }\n\n    // Parse timemark\n    const timeMatch = line.match(/time=(\\d{2}:\\d{2}:\\d{2}.\\d{2})/);\n    if (timeMatch) {\n      progress.timemark = timeMatch[1];\n\n      // Calculate percentage if duration is known\n      if (this.duration > 0) {\n        const currentSeconds = this.parseTimemark(progress.timemark);\n        progress.percent = Math.min((currentSeconds / this.duration) * 100, 100);\n        progress.percent = Math.round(progress.percent * 100) / 100; // 2 decimal places\n      } else {\n        progress.percent = 0;\n      }\n    }\n\n    // Return null if we couldn't parse essential fields\n    if (!progress.frames && !progress.timemark) {\n      return null;\n    }\n\n    return progress as ProgressInfo;\n  }\n\n  /**\n   * Parse duration from FFmpeg metadata output\n   * Example: \"Duration: 00:05:30.25, start: 0.000000, bitrate: 1234 kb/s\"\n   */\n  parseDuration(line: string): number | null {\n    const durationMatch = line.match(/Duration:\\s*(\\d{2}):(\\d{2}):(\\d{2}\\.\\d{2})/);\n    if (durationMatch) {\n      const hours = parseInt(durationMatch[1]);\n      const minutes = parseInt(durationMatch[2]);\n      const seconds = parseFloat(durationMatch[3]);\n\n      const totalSeconds = hours * 3600 + minutes * 60 + seconds;\n      this.setDuration(totalSeconds);\n      return totalSeconds;\n    }\n    return null;\n  }\n\n  /**\n   * Convert timemark string to seconds\n   */\n  private parseTimemark(timemark: string): number {\n    const parts = timemark.split(':');\n    if (parts.length !== 3) return 0;\n\n    const hours = parseInt(parts[0]);\n    const minutes = parseInt(parts[1]);\n    const seconds = parseFloat(parts[2]);\n\n    return hours * 3600 + minutes * 60 + seconds;\n  }\n\n  /**\n   * Check if line indicates encoding has started\n   */\n  isEncodingStart(line: string): boolean {\n    return (\n      line.includes('Press [q] to stop') || line.includes('frame=') || line.includes('encoder')\n    );\n  }\n\n  /**\n   * Check if line indicates error\n   */\n  isError(line: string): boolean {\n    const errorPatterns = [\n      'error',\n      'invalid',\n      'failed',\n      'cannot',\n      'unable to',\n      'does not contain',\n      'no such file',\n      'permission denied',\n    ];\n\n    const lowerLine = line.toLowerCase();\n    return errorPatterns.some(pattern => lowerLine.includes(pattern));\n  }\n\n  /**\n   * Extract codec information from FFmpeg output\n   */\n  parseCodecInfo(line: string): { video?: string; audio?: string } | null {\n    const info: { video?: string; audio?: string } = {};\n\n    // Parse video codec: \"Stream #0:0: Video: h264 (High), yuv420p, 1920x1080\"\n    const videoMatch = line.match(/Video:\\s*([^,\\s]+)/);\n    if (videoMatch) {\n      info.video = videoMatch[1];\n    }\n\n    // Parse audio codec: \"Stream #0:1: Audio: aac (LC), 48000 Hz, stereo\"\n    const audioMatch = line.match(/Audio:\\s*([^,\\s]+)/);\n    if (audioMatch) {\n      info.audio = audioMatch[1];\n    }\n\n    return Object.keys(info).length > 0 ? info : null;\n  }\n}\n","/**\n * Base class for all FFmpeg-related errors\n */\nexport class FFmpegError extends Error {\n  constructor(\n    message: string,\n    public readonly code?: string\n  ) {\n    super(message);\n    this.name = 'FFmpegError';\n    Object.setPrototypeOf(this, FFmpegError.prototype);\n  }\n}\n\n/**\n * Thrown when FFmpeg binary is not found or not accessible\n */\nexport class FFmpegNotFoundError extends FFmpegError {\n  constructor(path: string) {\n    super(`FFmpeg binary not found at: ${path}`, 'FFMPEG_NOT_FOUND');\n    this.name = 'FFmpegNotFoundError';\n    Object.setPrototypeOf(this, FFmpegNotFoundError.prototype);\n  }\n}\n\n/**\n * Thrown when FFprobe binary is not found or not accessible\n */\nexport class FFprobeNotFoundError extends FFmpegError {\n  constructor(path: string) {\n    super(`FFprobe binary not found at: ${path}`, 'FFPROBE_NOT_FOUND');\n    this.name = 'FFprobeNotFoundError';\n    Object.setPrototypeOf(this, FFprobeNotFoundError.prototype);\n  }\n}\n\n/**\n * Thrown when FFmpeg command execution fails\n */\nexport class FFmpegExecutionError extends FFmpegError {\n  constructor(\n    message: string,\n    public readonly command?: string,\n    public readonly stderr?: string\n  ) {\n    super(message, 'EXECUTION_FAILED');\n    this.name = 'FFmpegExecutionError';\n    Object.setPrototypeOf(this, FFmpegExecutionError.prototype);\n  }\n}\n\n/**\n * Thrown when a codec is not supported\n */\nexport class CodecNotSupportedError extends FFmpegError {\n  constructor(\n    public readonly codec: string,\n    public readonly type: 'video' | 'audio' | 'subtitle',\n    public readonly operation: 'encode' | 'decode'\n  ) {\n    super(`Codec '${codec}' is not supported for ${operation}ing ${type}`, 'CODEC_NOT_SUPPORTED');\n    this.name = 'CodecNotSupportedError';\n    Object.setPrototypeOf(this, CodecNotSupportedError.prototype);\n  }\n}\n\n/**\n * Thrown when a format is not supported\n */\nexport class FormatNotSupportedError extends FFmpegError {\n  constructor(\n    public readonly format: string,\n    public readonly operation: 'mux' | 'demux'\n  ) {\n    super(`Format '${format}' is not supported for ${operation}ing`, 'FORMAT_NOT_SUPPORTED');\n    this.name = 'FormatNotSupportedError';\n    Object.setPrototypeOf(this, FormatNotSupportedError.prototype);\n  }\n}\n\n/**\n * Thrown when input file is invalid or not found\n */\nexport class InvalidInputError extends FFmpegError {\n  constructor(\n    public readonly inputPath: string,\n    reason: string\n  ) {\n    super(`Invalid input file '${inputPath}': ${reason}`, 'INVALID_INPUT');\n    this.name = 'InvalidInputError';\n    Object.setPrototypeOf(this, InvalidInputError.prototype);\n  }\n}\n\n/**\n * Thrown when output configuration is invalid\n */\nexport class InvalidOutputError extends FFmpegError {\n  constructor(\n    public readonly outputPath: string,\n    reason: string\n  ) {\n    super(`Invalid output configuration for '${outputPath}': ${reason}`, 'INVALID_OUTPUT');\n    this.name = 'InvalidOutputError';\n    Object.setPrototypeOf(this, InvalidOutputError.prototype);\n  }\n}\n\n/**\n * Thrown when hardware acceleration is not available\n */\nexport class HardwareAccelerationError extends FFmpegError {\n  constructor(public readonly accelerationType: string) {\n    super(\n      `Hardware acceleration '${accelerationType}' is not available`,\n      'HARDWARE_ACCEL_NOT_AVAILABLE'\n    );\n    this.name = 'HardwareAccelerationError';\n    Object.setPrototypeOf(this, HardwareAccelerationError.prototype);\n  }\n}\n","import { spawn, ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\nimport type {\n  ConversionConfig,\n  ConversionCallbacks,\n  ProgressInfo,\n} from '../types/conversion-config';\nimport { CommandGenerator } from './command-generator';\nimport { ProgressParser } from './progress-parser';\nimport { prepareInput, cleanupInput, getInputPath } from './input-handler';\nimport { FFmpegExecutionError } from '../errors/ffmpeg-errors';\n\n/**\n * FFmpeg execution engine with progress tracking\n */\nexport class ExecutionEngine extends EventEmitter {\n  private process: ChildProcess | null = null;\n  private progressParser: ProgressParser;\n  private ffmpegPath: string;\n  private killed: boolean = false;\n\n  constructor(ffmpegPath: string = 'ffmpeg') {\n    super();\n    this.ffmpegPath = ffmpegPath;\n    this.progressParser = new ProgressParser();\n  }\n\n  /**\n   * Execute FFmpeg conversion with progress tracking\n   */\n  async execute(config: ConversionConfig, callbacks?: ConversionCallbacks): Promise<void> {\n    return new Promise(async (resolve, reject) => {\n      try {\n        // Validate config\n        const validation = CommandGenerator.validate(config);\n        if (!validation.valid) {\n          throw new Error(`Invalid configuration: ${validation.errors.join(', ')}`);\n        }\n\n        // Prepare input (handle Buffer/Stream)\n        const inputInfo = await prepareInput(config.input);\n        const inputPath = getInputPath(inputInfo);\n\n        // Generate command arguments\n        const args = CommandGenerator.generate({\n          ...config,\n          input: inputPath,\n        });\n\n        // Emit/callback start event\n        const commandString = `${this.ffmpegPath} ${args.join(' ')}`;\n        this.emit('start', commandString);\n        callbacks?.onStart?.(commandString);\n\n        // Spawn FFmpeg process\n        this.process = spawn(this.ffmpegPath, args);\n        this.killed = false;\n\n        // Collect stderr for progress and errors\n        let stderrData = '';\n\n        // Handle stdout (usually not used, but capture just in case)\n        this.process.stdout?.on('data', (_data: Buffer) => {\n          // FFmpeg outputs to stderr, not stdout usually\n        });\n\n        // Handle stderr (progress and errors)\n        this.process.stderr?.on('data', (data: Buffer) => {\n          const text = data.toString();\n          stderrData += text;\n\n          // Parse each line\n          const lines = text.split('\\n');\n          lines.forEach(line => {\n            if (!line.trim()) return;\n\n            // Parse duration from metadata\n            this.progressParser.parseDuration(line);\n\n            // Parse progress\n            const progress = this.progressParser.parseProgress(line);\n            if (progress) {\n              this.emit('progress', progress);\n              callbacks?.onProgress?.(progress);\n            }\n\n            // Check for errors\n            if (this.progressParser.isError(line)) {\n              // Don't emit error yet, wait for process exit\n              // Some \"errors\" are just warnings\n            }\n          });\n        });\n\n        // Handle process exit\n        this.process.on('close', (code: number | null) => {\n          // Cleanup temporary files\n          if (inputInfo.tempPath) {\n            cleanupInput(inputInfo);\n          }\n\n          // Check if process was killed by user\n          if (this.killed) {\n            const error = new FFmpegExecutionError(\n              'Conversion was cancelled',\n              commandString,\n              'Process killed by user'\n            );\n            this.emit('error', error);\n            callbacks?.onError?.(error);\n            reject(error);\n            return;\n          }\n\n          // Check exit code\n          if (code === 0) {\n            // Success\n            this.emit('end');\n            callbacks?.onEnd?.();\n            resolve();\n          } else {\n            // Error\n            const error = new FFmpegExecutionError(\n              `FFmpeg process exited with code ${code}`,\n              commandString,\n              stderrData\n            );\n            this.emit('error', error);\n            callbacks?.onError?.(error);\n            reject(error);\n          }\n\n          this.process = null;\n        });\n\n        // Handle process errors\n        this.process.on('error', (err: Error) => {\n          // Cleanup temporary files\n          if (inputInfo.tempPath) {\n            cleanupInput(inputInfo);\n          }\n\n          const error = new FFmpegExecutionError(\n            `Failed to start FFmpeg: ${err.message}`,\n            commandString\n          );\n          this.emit('error', error);\n          callbacks?.onError?.(error);\n          reject(error);\n        });\n\n        // Note: Streams are already written to tempPath by prepareInput\n      } catch (err) {\n        const error =\n          err instanceof Error\n            ? new FFmpegExecutionError(err.message)\n            : new FFmpegExecutionError('Unknown error during execution');\n\n        this.emit('error', error);\n        callbacks?.onError?.(error);\n        reject(error);\n      }\n    });\n  }\n\n  /**\n   * Execute and return output as Buffer\n   */\n  async executeToBuffer(\n    config: Omit<ConversionConfig, 'output'>,\n    callbacks?: ConversionCallbacks\n  ): Promise<Buffer> {\n    return new Promise(async (resolve, reject) => {\n      const chunks: Buffer[] = [];\n\n      // Configure to output to pipe\n      const pipeConfig: ConversionConfig = {\n        ...config,\n        output: 'pipe:1',\n      };\n\n      try {\n        // Validate and generate command\n        const validation = CommandGenerator.validate(pipeConfig);\n        if (!validation.valid) {\n          throw new Error(`Invalid configuration: ${validation.errors.join(', ')}`);\n        }\n\n        const inputInfo = await prepareInput(config.input);\n        const inputPath = getInputPath(inputInfo);\n        const args = CommandGenerator.generate({\n          ...pipeConfig,\n          input: inputPath,\n        });\n\n        const commandString = `${this.ffmpegPath} ${args.join(' ')}`;\n        this.emit('start', commandString);\n        callbacks?.onStart?.(commandString);\n\n        // Spawn process\n        this.process = spawn(this.ffmpegPath, args);\n        this.killed = false;\n\n        // Collect stdout (actual video data)\n        this.process.stdout?.on('data', (data: Buffer) => {\n          chunks.push(data);\n        });\n\n        // Handle stderr (progress)\n        let stderrData = '';\n        this.process.stderr?.on('data', (data: Buffer) => {\n          const text = data.toString();\n          stderrData += text;\n\n          const lines = text.split('\\n');\n          lines.forEach(line => {\n            if (!line.trim()) return;\n\n            this.progressParser.parseDuration(line);\n            const progress = this.progressParser.parseProgress(line);\n            if (progress) {\n              this.emit('progress', progress);\n              callbacks?.onProgress?.(progress);\n            }\n          });\n        });\n\n        // Handle completion\n        this.process.on('close', (code: number | null) => {\n          if (inputInfo.tempPath) {\n            cleanupInput(inputInfo);\n          }\n\n          if (this.killed) {\n            reject(new FFmpegExecutionError('Conversion was cancelled'));\n            return;\n          }\n\n          if (code === 0) {\n            const buffer = Buffer.concat(chunks);\n            this.emit('end');\n            callbacks?.onEnd?.();\n            resolve(buffer);\n          } else {\n            const error = new FFmpegExecutionError(\n              `FFmpeg process exited with code ${code}`,\n              commandString,\n              stderrData\n            );\n            this.emit('error', error);\n            callbacks?.onError?.(error);\n            reject(error);\n          }\n\n          this.process = null;\n        });\n\n        // Handle errors\n        this.process.on('error', (err: Error) => {\n          if (inputInfo.tempPath) {\n            cleanupInput(inputInfo);\n          }\n\n          const error = new FFmpegExecutionError(\n            `Failed to start FFmpeg: ${err.message}`,\n            commandString\n          );\n          reject(error);\n        });\n\n        // Note: Streams are already written to tempPath by prepareInput\n      } catch (err) {\n        const error =\n          err instanceof Error\n            ? new FFmpegExecutionError(err.message)\n            : new FFmpegExecutionError('Unknown error');\n        reject(error);\n      }\n    });\n  }\n\n  /**\n   * Cancel running conversion\n   */\n  cancel(): void {\n    if (this.process && !this.killed) {\n      this.killed = true;\n\n      // Send 'q' to FFmpeg for graceful shutdown\n      this.process.stdin?.write('q');\n\n      // If it doesn't respond in 2 seconds, force kill\n      setTimeout(() => {\n        if (this.process) {\n          this.process.kill('SIGKILL');\n        }\n      }, 2000);\n    }\n  }\n\n  /**\n   * Check if conversion is running\n   */\n  isRunning(): boolean {\n    return this.process !== null && !this.killed;\n  }\n}\n\n/**\n * Batch execution engine for multiple conversions\n */\nexport class BatchExecutionEngine {\n  private ffmpegPath: string;\n\n  constructor(ffmpegPath: string = 'ffmpeg') {\n    this.ffmpegPath = ffmpegPath;\n  }\n\n  /**\n   * Execute multiple conversions sequentially\n   */\n  async executeBatch(\n    configs: ConversionConfig[],\n    callbacks?: {\n      onProgress?: (index: number, progress: ProgressInfo) => void;\n      onFileComplete?: (index: number) => void;\n      onFileError?: (index: number, error: Error) => void;\n      onComplete?: () => void;\n    }\n  ): Promise<void> {\n    for (let i = 0; i < configs.length; i++) {\n      const config = configs[i];\n      const engine = new ExecutionEngine(this.ffmpegPath);\n\n      try {\n        await engine.execute(config, {\n          onProgress: progress => {\n            callbacks?.onProgress?.(i, progress);\n          },\n        });\n\n        callbacks?.onFileComplete?.(i);\n      } catch (error) {\n        callbacks?.onFileError?.(i, error as Error);\n        // Continue with next file even if one fails\n      }\n    }\n\n    callbacks?.onComplete?.();\n  }\n\n  /**\n   * Execute multiple conversions in parallel\n   */\n  async executeBatchParallel(\n    configs: ConversionConfig[],\n    maxConcurrent: number = 2,\n    callbacks?: {\n      onProgress?: (index: number, progress: ProgressInfo) => void;\n      onFileComplete?: (index: number) => void;\n      onFileError?: (index: number, error: Error) => void;\n      onComplete?: () => void;\n    }\n  ): Promise<void> {\n    const results: Promise<void>[] = [];\n    const executing: Promise<void>[] = [];\n\n    for (let i = 0; i < configs.length; i++) {\n      const config = configs[i];\n      const engine = new ExecutionEngine(this.ffmpegPath);\n\n      const promise = engine\n        .execute(config, {\n          onProgress: progress => {\n            callbacks?.onProgress?.(i, progress);\n          },\n        })\n        .then(() => {\n          callbacks?.onFileComplete?.(i);\n        })\n        .catch(error => {\n          callbacks?.onFileError?.(i, error);\n        });\n\n      results.push(promise);\n      executing.push(promise);\n\n      // Remove from executing when done\n      promise.finally(() => {\n        executing.splice(executing.indexOf(promise), 1);\n      });\n\n      // Wait if we've hit max concurrent\n      if (executing.length >= maxConcurrent) {\n        await Promise.race(executing);\n      }\n    }\n\n    // Wait for all to complete\n    await Promise.all(results);\n    callbacks?.onComplete?.();\n  }\n}\n","import { spawn } from 'child_process';\nimport { existsSync, mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport type { ThumbnailConfig, ThumbnailResult } from '../types/thumbnail';\nimport { prepareInput, cleanupInput, getInputPath } from './input-handler';\nimport { FFmpegExecutionError } from '../errors/ffmpeg-errors';\n\n/**\n * Extract thumbnails from video\n */\nexport class ThumbnailExtractor {\n  constructor(private ffmpegPath: string = 'ffmpeg') {}\n\n  /**\n   * Extract thumbnails based on configuration\n   */\n  async extract(config: ThumbnailConfig): Promise<ThumbnailResult> {\n    // Prepare input\n    const inputInfo = await prepareInput(config.input);\n    const inputPath = getInputPath(inputInfo);\n\n    try {\n      let result: ThumbnailResult;\n\n      switch (config.strategy) {\n        case 'time':\n          result = await this.extractByTime(inputPath, config);\n          break;\n        case 'count':\n          result = await this.extractByCount(inputPath, config);\n          break;\n        case 'interval':\n          result = await this.extractByInterval(inputPath, config);\n          break;\n        case 'scene':\n          result = await this.extractByScene(inputPath, config);\n          break;\n        case 'quality':\n          result = await this.extractBestQuality(inputPath, config);\n          break;\n        default:\n          throw new Error(`Unknown strategy: ${config.strategy}`);\n      }\n\n      return result;\n    } finally {\n      if (inputInfo.tempPath) {\n        cleanupInput(inputInfo);\n      }\n    }\n  }\n\n  /**\n   * Extract thumbnails at specific times\n   */\n  private async extractByTime(\n    inputPath: string,\n    config: ThumbnailConfig\n  ): Promise<ThumbnailResult> {\n    if (!config.times || config.times.length === 0) {\n      throw new Error('times array required for time-based extraction');\n    }\n\n    const files: string[] = [];\n    const timestamps: number[] = [];\n\n    // Ensure output directory exists\n    mkdirSync(dirname(config.output), { recursive: true });\n\n    for (let i = 0; i < config.times.length; i++) {\n      const time = config.times[i];\n      const timeStr = typeof time === 'number' ? this.formatTime(time) : time;\n      const outputFile = config.output.includes('%d')\n        ? config.output.replace('%d', (i + 1).toString())\n        : config.output.replace(/\\.(\\w+)$/, `-${i + 1}.$1`);\n\n      await this.extractSingleFrame(inputPath, timeStr, outputFile, config);\n      files.push(outputFile);\n      timestamps.push(typeof time === 'number' ? time : this.parseTime(time));\n    }\n\n    return { files, count: files.length, timestamps };\n  }\n\n  /**\n   * Extract N thumbnails evenly distributed\n   */\n  private async extractByCount(\n    inputPath: string,\n    config: ThumbnailConfig\n  ): Promise<ThumbnailResult> {\n    if (!config.count || config.count < 1) {\n      throw new Error('count required for count-based extraction');\n    }\n\n    // Get video duration\n    const duration = await this.getVideoDuration(inputPath);\n\n    const skipFirst = config.skipFirst || 0;\n    const skipLast = config.skipLast || 0;\n    const usableDuration = duration - skipFirst - skipLast;\n\n    // Calculate evenly distributed times\n    const times: number[] = [];\n    for (let i = 0; i < config.count; i++) {\n      const position = skipFirst + (usableDuration / (config.count + 1)) * (i + 1);\n      times.push(position);\n    }\n\n    return this.extractByTime(inputPath, { ...config, times, strategy: 'time' });\n  }\n\n  /**\n   * Extract thumbnails at regular intervals\n   */\n  private async extractByInterval(\n    inputPath: string,\n    config: ThumbnailConfig\n  ): Promise<ThumbnailResult> {\n    if (!config.interval || config.interval <= 0) {\n      throw new Error('interval required for interval-based extraction');\n    }\n\n    const duration = await this.getVideoDuration(inputPath);\n    const skipFirst = config.skipFirst || 0;\n    const skipLast = config.skipLast || 0;\n\n    const times: number[] = [];\n    for (let t = skipFirst; t < duration - skipLast; t += config.interval) {\n      times.push(t);\n    }\n\n    return this.extractByTime(inputPath, { ...config, times, strategy: 'time' });\n  }\n\n  /**\n   * Extract thumbnails on scene changes\n   */\n  private async extractByScene(\n    inputPath: string,\n    config: ThumbnailConfig\n  ): Promise<ThumbnailResult> {\n    const threshold = config.sceneThreshold || 0.4;\n\n    // Use FFmpeg scene detection filter to find scenes\n    // Then extract first frame of each scene\n    const outputPattern = config.output.includes('%d')\n      ? config.output\n      : config.output.replace(/\\.(\\w+)$/, '-%d.$1');\n\n    mkdirSync(dirname(config.output), { recursive: true });\n\n    const args = [\n      '-hide_banner',\n      '-i',\n      inputPath,\n      '-vf',\n      `select='gt(scene,${threshold})',showinfo`,\n      '-vsync',\n      'vfr',\n    ];\n\n    if (config.size) {\n      const size =\n        typeof config.size === 'string'\n          ? config.size\n          : `${config.size.width}x${config.size.height}`;\n      args.push('-s', size);\n    }\n\n    if (config.quality) {\n      args.push('-q:v', config.quality.toString());\n    }\n\n    args.push(outputPattern);\n\n    await this.runFFmpeg(args);\n\n    // Count generated files\n    const files = this.getGeneratedFiles(outputPattern);\n\n    return {\n      files,\n      count: files.length,\n      timestamps: [], // Would need to parse from showinfo output\n    };\n  }\n\n  /**\n   * Extract best quality frames\n   */\n  private async extractBestQuality(\n    inputPath: string,\n    config: ThumbnailConfig\n  ): Promise<ThumbnailResult> {\n    const count = config.count || 5;\n\n    // Use thumbnail filter to select best frames\n    const outputPattern = config.output.includes('%d')\n      ? config.output\n      : config.output.replace(/\\.(\\w+)$/, '-%d.$1');\n\n    mkdirSync(dirname(config.output), { recursive: true });\n\n    const args = ['-hide_banner', '-i', inputPath, '-vf', `thumbnail=${count}`, '-vsync', 'vfr'];\n\n    if (config.size) {\n      const size =\n        typeof config.size === 'string'\n          ? config.size\n          : `${config.size.width}x${config.size.height}`;\n      args.push('-s', size);\n    }\n\n    args.push('-frames:v', count.toString());\n    args.push(outputPattern);\n\n    await this.runFFmpeg(args);\n\n    const files = this.getGeneratedFiles(outputPattern);\n\n    return {\n      files,\n      count: files.length,\n      timestamps: [],\n    };\n  }\n\n  /**\n   * Extract a single frame at specified time\n   */\n  private async extractSingleFrame(\n    inputPath: string,\n    time: string,\n    output: string,\n    config: ThumbnailConfig\n  ): Promise<void> {\n    mkdirSync(dirname(output), { recursive: true });\n\n    const args = ['-hide_banner', '-ss', time, '-i', inputPath, '-vframes', '1'];\n\n    if (config.size) {\n      const size =\n        typeof config.size === 'string'\n          ? config.size\n          : `${config.size.width}x${config.size.height}`;\n      args.push('-s', size);\n    }\n\n    if (config.quality) {\n      args.push('-q:v', config.quality.toString());\n    }\n\n    args.push('-y', output);\n\n    await this.runFFmpeg(args);\n  }\n\n  /**\n   * Get video duration using ffprobe\n   */\n  private async getVideoDuration(inputPath: string): Promise<number> {\n    return new Promise((resolve, reject) => {\n      const ffprobe = this.ffmpegPath.replace('ffmpeg', 'ffprobe');\n      const args = [\n        '-v',\n        'error',\n        '-show_entries',\n        'format=duration',\n        '-of',\n        'default=noprint_wrappers=1:nokey=1',\n        inputPath,\n      ];\n\n      const process = spawn(ffprobe, args);\n      let output = '';\n\n      process.stdout.on('data', (data: Buffer) => {\n        output += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve(parseFloat(output.trim()));\n        } else {\n          reject(new Error('Failed to get video duration'));\n        }\n      });\n    });\n  }\n\n  /**\n   * Run FFmpeg command\n   */\n  private async runFFmpeg(args: string[]): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const process = spawn(this.ffmpegPath, args);\n      let stderr = '';\n\n      process.stderr?.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve();\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              `Thumbnail extraction failed`,\n              `${this.ffmpegPath} ${args.join(' ')}`,\n              stderr\n            )\n          );\n        }\n      });\n\n      process.on('error', err => {\n        reject(new FFmpegExecutionError(`Failed to start FFmpeg: ${err.message}`));\n      });\n    });\n  }\n\n  /**\n   * Get list of generated files from pattern\n   */\n  private getGeneratedFiles(pattern: string): string[] {\n    const files: string[] = [];\n    let i = 1;\n\n    while (true) {\n      const file = pattern.replace('%d', i.toString());\n      if (existsSync(file)) {\n        files.push(file);\n        i++;\n      } else {\n        break;\n      }\n    }\n\n    return files;\n  }\n\n  /**\n   * Format time in seconds to HH:MM:SS\n   */\n  private formatTime(seconds: number): string {\n    const h = Math.floor(seconds / 3600);\n    const m = Math.floor((seconds % 3600) / 60);\n    const s = seconds % 60;\n    return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\n  }\n\n  /**\n   * Parse time string to seconds\n   */\n  private parseTime(time: string): number {\n    const parts = time.split(':').map(Number);\n    if (parts.length === 3) {\n      return parts[0] * 3600 + parts[1] * 60 + parts[2];\n    }\n    return 0;\n  }\n}\n","import { spawn } from 'child_process';\nimport { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';\nimport { tmpdir } from 'os';\nimport { join, dirname } from 'path';\nimport type { TrailerConfig, TrailerResult, TrailerSegment } from '../types/thumbnail';\nimport { prepareInput, cleanupInput, getInputPath } from './input-handler';\nimport { FFmpegExecutionError } from '../errors/ffmpeg-errors';\n\n/**\n * Generate video trailers from longer videos\n */\nexport class TrailerGenerator {\n  constructor(private ffmpegPath: string = 'ffmpeg') {}\n\n  /**\n   * Generate trailer based on configuration\n   */\n  async generate(config: TrailerConfig): Promise<TrailerResult> {\n    // Prepare input\n    const inputInfo = await prepareInput(config.input);\n    const inputPath = getInputPath(inputInfo);\n\n    try {\n      let segments: TrailerSegment[];\n\n      switch (config.strategy) {\n        case 'segments':\n          segments = await this.selectBySegments(inputPath, config);\n          break;\n        case 'duration':\n          segments = await this.selectByDuration(inputPath, config);\n          break;\n        case 'scenes':\n          segments = await this.selectByScenes(inputPath, config);\n          break;\n        case 'highlights':\n          segments = await this.selectByHighlights(inputPath, config);\n          break;\n        default:\n          throw new Error(`Unknown strategy: ${config.strategy}`);\n      }\n\n      // Ensure total duration doesn't exceed max\n      segments = this.trimToMaxDuration(segments, config.maxDuration);\n\n      // Generate trailer from segments\n      const output = await this.createTrailer(inputPath, segments, config);\n\n      const totalDuration = segments.reduce((sum, s) => sum + s.duration, 0);\n\n      return {\n        output,\n        duration: totalDuration,\n        segments,\n      };\n    } finally {\n      if (inputInfo.tempPath) {\n        cleanupInput(inputInfo);\n      }\n    }\n  }\n\n  /**\n   * Select segments by count\n   */\n  private async selectBySegments(\n    inputPath: string,\n    config: TrailerConfig\n  ): Promise<TrailerSegment[]> {\n    const count = config.segmentCount || 3;\n    const duration = await this.getVideoDuration(inputPath);\n    const segmentDuration = config.segmentDuration || 5;\n\n    const selection = config.selection || 'distributed';\n    const segments: TrailerSegment[] = [];\n\n    switch (selection) {\n      case 'beginning':\n        // Take segments from the beginning\n        for (let i = 0; i < count; i++) {\n          segments.push({\n            startTime: i * (segmentDuration + 1),\n            duration: segmentDuration,\n            reason: 'Beginning segment',\n          });\n        }\n        break;\n\n      case 'middle':\n        // Take segments from the middle\n        const middleStart = (duration - count * segmentDuration) / 2;\n        for (let i = 0; i < count; i++) {\n          segments.push({\n            startTime: middleStart + i * (segmentDuration + 1),\n            duration: segmentDuration,\n            reason: 'Middle segment',\n          });\n        }\n        break;\n\n      case 'end':\n        // Take segments from the end\n        const endStart = duration - count * (segmentDuration + 1);\n        for (let i = 0; i < count; i++) {\n          segments.push({\n            startTime: Math.max(0, endStart + i * (segmentDuration + 1)),\n            duration: segmentDuration,\n            reason: 'End segment',\n          });\n        }\n        break;\n\n      case 'distributed':\n      default:\n        // Evenly distribute across video\n        const interval = duration / (count + 1);\n        for (let i = 0; i < count; i++) {\n          segments.push({\n            startTime: interval * (i + 1),\n            duration: Math.min(segmentDuration, duration - interval * (i + 1)),\n            reason: `Distributed segment ${i + 1}/${count}`,\n          });\n        }\n        break;\n    }\n\n    return segments;\n  }\n\n  /**\n   * Select segments by total duration\n   */\n  private async selectByDuration(\n    inputPath: string,\n    config: TrailerConfig\n  ): Promise<TrailerSegment[]> {\n    const segmentDuration = config.segmentDuration || 5;\n    const maxDuration = config.maxDuration;\n\n    // Calculate how many segments we can fit\n    const segmentCount = Math.floor(maxDuration / segmentDuration);\n\n    return this.selectBySegments(inputPath, {\n      ...config,\n      segmentCount,\n      strategy: 'segments',\n    });\n  }\n\n  /**\n   * Select segments based on scene changes\n   */\n  private async selectByScenes(\n    inputPath: string,\n    config: TrailerConfig\n  ): Promise<TrailerSegment[]> {\n    const threshold = config.sceneDetection?.threshold || 0.4;\n    const minDuration = config.sceneDetection?.minSceneDuration || 2;\n\n    // Detect scenes using FFmpeg\n    const sceneTimestamps = await this.detectScenes(inputPath, threshold);\n\n    // Filter scenes by minimum duration and select best ones\n    const segments: TrailerSegment[] = [];\n\n    for (let i = 0; i < sceneTimestamps.length - 1; i++) {\n      const startTime = sceneTimestamps[i];\n      const endTime = sceneTimestamps[i + 1];\n      const duration = endTime - startTime;\n\n      if (duration >= minDuration) {\n        segments.push({\n          startTime,\n          duration: Math.min(duration, config.segmentDuration || 5),\n          score: 1.0,\n          reason: 'Scene change detected',\n        });\n      }\n    }\n\n    // Limit to max duration\n    return this.trimToMaxDuration(segments, config.maxDuration);\n  }\n\n  /**\n   * Select highlight segments (high motion or loud audio)\n   */\n  private async selectByHighlights(\n    inputPath: string,\n    config: TrailerConfig\n  ): Promise<TrailerSegment[]> {\n    // For now, use distributed strategy\n    // TODO: Implement motion/audio analysis\n    return this.selectBySegments(inputPath, {\n      ...config,\n      segmentCount: config.segmentCount || 3,\n      selection: 'distributed',\n      strategy: 'segments',\n    });\n  }\n\n  /**\n   * Detect scene changes and return timestamps\n   */\n  private async detectScenes(inputPath: string, threshold: number): Promise<number[]> {\n    // Use ffmpeg to detect scenes\n    const args = [\n      '-hide_banner',\n      '-i',\n      inputPath,\n      '-vf',\n      `select='gt(scene,${threshold})',showinfo`,\n      '-f',\n      'null',\n      '-',\n    ];\n\n    return new Promise((resolve, reject) => {\n      const process = spawn(this.ffmpegPath, args);\n      let stderr = '';\n\n      process.stderr?.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0 || code === 255) {\n          // 255 is normal for null output\n          // Parse timestamps from showinfo output\n          const timestamps = this.parseSceneTimestamps(stderr);\n          resolve(timestamps);\n        } else {\n          reject(new Error('Scene detection failed'));\n        }\n      });\n    });\n  }\n\n  /**\n   * Parse scene timestamps from FFmpeg showinfo output\n   */\n  private parseSceneTimestamps(output: string): number[] {\n    const timestamps: number[] = [0]; // Always include start\n    const regex = /pts_time:([\\d.]+)/g;\n    let match;\n\n    while ((match = regex.exec(output)) !== null) {\n      timestamps.push(parseFloat(match[1]));\n    }\n\n    return timestamps;\n  }\n\n  /**\n   * Trim segments to fit within max duration\n   */\n  private trimToMaxDuration(segments: TrailerSegment[], maxDuration: number): TrailerSegment[] {\n    const trimmed: TrailerSegment[] = [];\n    let currentDuration = 0;\n\n    for (const segment of segments) {\n      const remainingTime = maxDuration - currentDuration;\n\n      if (remainingTime <= 0) break;\n\n      if (segment.duration <= remainingTime) {\n        trimmed.push(segment);\n        currentDuration += segment.duration;\n      } else {\n        // Include partial segment\n        trimmed.push({\n          ...segment,\n          duration: remainingTime,\n        });\n        break;\n      }\n    }\n\n    return trimmed;\n  }\n\n  /**\n   * Create trailer from selected segments\n   */\n  private async createTrailer(\n    inputPath: string,\n    segments: TrailerSegment[],\n    config: TrailerConfig\n  ): Promise<string> {\n    // Create concat file for FFmpeg\n    const concatFile = join(tmpdir(), `trailer-${Date.now()}.txt`);\n    const segmentFiles: string[] = [];\n\n    try {\n      // Extract each segment to temporary file\n      for (let i = 0; i < segments.length; i++) {\n        const segment = segments[i];\n        const segmentFile = join(tmpdir(), `trailer-segment-${Date.now()}-${i}.mp4`);\n\n        await this.extractSegment(inputPath, segment, segmentFile, config);\n        segmentFiles.push(segmentFile);\n      }\n\n      // Create concat file\n      const concatContent = segmentFiles.map(f => `file '${f}'`).join('\\n');\n      writeFileSync(concatFile, concatContent);\n\n      // Concatenate segments\n      mkdirSync(dirname(config.output), { recursive: true });\n\n      const args = ['-hide_banner', '-f', 'concat', '-safe', '0', '-i', concatFile];\n\n      // Add transitions if enabled\n      if (config.transitions?.enabled) {\n        const transType = config.transitions.type || 'fade';\n        const transDuration = config.transitions.duration || 0.5;\n\n        if (transType === 'fade') {\n          // Add crossfade between segments\n          args.push(\n            '-vf',\n            `fade=t=in:st=0:d=${transDuration},fade=t=out:st=${segments[0].duration - transDuration}:d=${transDuration}`\n          );\n        }\n      }\n\n      // Video codec settings\n      if (config.video?.codec) {\n        args.push('-c:v', config.video.codec);\n      } else {\n        args.push('-c:v', 'copy'); // Copy if no codec specified\n      }\n\n      if (config.video?.bitrate) {\n        args.push('-b:v', config.video.bitrate);\n      }\n\n      if (config.video?.size) {\n        args.push('-s', config.video.size);\n      }\n\n      if (config.video?.fps) {\n        args.push('-r', config.video.fps.toString());\n      }\n\n      // Audio handling\n      if (config.audio?.enabled !== false) {\n        if (config.audio?.music) {\n          // Add background music\n          args.push('-i', config.audio.music);\n          const musicVol = config.audio.musicVolume || 0.3;\n          args.push(\n            '-filter_complex',\n            `[1:a]volume=${musicVol}[music];[0:a][music]amix=inputs=2:duration=first[a]`\n          );\n          args.push('-map', '0:v', '-map', '[a]');\n        } else if (config.audio?.normalize) {\n          args.push('-af', 'loudnorm');\n        } else {\n          args.push('-c:a', 'copy');\n        }\n      } else {\n        args.push('-an');\n      }\n\n      args.push('-y', config.output);\n\n      await this.runFFmpeg(args);\n\n      return config.output;\n    } finally {\n      // Cleanup temporary files\n      if (existsSync(concatFile)) {\n        unlinkSync(concatFile);\n      }\n\n      segmentFiles.forEach(file => {\n        if (existsSync(file)) {\n          try {\n            unlinkSync(file);\n          } catch {\n            // Ignore\n          }\n        }\n      });\n    }\n  }\n\n  /**\n   * Extract a single segment\n   */\n  private async extractSegment(\n    inputPath: string,\n    segment: TrailerSegment,\n    output: string,\n    config: TrailerConfig\n  ): Promise<void> {\n    const args = [\n      '-hide_banner',\n      '-ss',\n      this.formatTime(segment.startTime),\n      '-i',\n      inputPath,\n      '-t',\n      this.formatTime(segment.duration),\n      '-c:v',\n      config.video?.codec || 'libx264',\n      '-c:a',\n      'aac',\n      '-y',\n      output,\n    ];\n\n    // Add fade in/out if enabled\n    if (config.audio?.fadeInOut) {\n      const fadeDur = 0.5;\n      args.push(\n        '-af',\n        `afade=t=in:st=0:d=${fadeDur},afade=t=out:st=${segment.duration - fadeDur}:d=${fadeDur}`\n      );\n    }\n\n    await this.runFFmpeg(args);\n  }\n\n  /**\n   * Get video duration\n   */\n  private async getVideoDuration(inputPath: string): Promise<number> {\n    return new Promise((resolve, reject) => {\n      const ffprobe = this.ffmpegPath.replace('ffmpeg', 'ffprobe');\n      const args = [\n        '-v',\n        'error',\n        '-show_entries',\n        'format=duration',\n        '-of',\n        'default=noprint_wrappers=1:nokey=1',\n        inputPath,\n      ];\n\n      const process = spawn(ffprobe, args);\n      let output = '';\n\n      process.stdout.on('data', (data: Buffer) => {\n        output += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve(parseFloat(output.trim()));\n        } else {\n          reject(new Error('Failed to get video duration'));\n        }\n      });\n    });\n  }\n\n  /**\n   * Run FFmpeg command\n   */\n  private async runFFmpeg(args: string[]): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const process = spawn(this.ffmpegPath, args);\n      let stderr = '';\n\n      process.stderr?.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve();\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              `Trailer generation failed`,\n              `${this.ffmpegPath} ${args.join(' ')}`,\n              stderr\n            )\n          );\n        }\n      });\n\n      process.on('error', err => {\n        reject(new FFmpegExecutionError(`Failed to start FFmpeg: ${err.message}`));\n      });\n    });\n  }\n\n  /**\n   * Format time in seconds to HH:MM:SS\n   */\n  private formatTime(seconds: number): string {\n    const h = Math.floor(seconds / 3600);\n    const m = Math.floor((seconds % 3600) / 60);\n    const s = seconds % 60;\n    return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toFixed(2).padStart(5, '0')}`;\n  }\n}\n","import { spawn } from 'child_process';\nimport { mkdirSync } from 'fs';\nimport { dirname, join } from 'path';\nimport type { ScreenshotConfig, ScreenshotsConfig, ScreenshotResult } from '../types/screenshot';\nimport { prepareInput, cleanupInput, getInputPath } from './input-handler';\nimport { FilterBuilder } from './filter-builder';\nimport { FFmpegExecutionError } from '../errors/ffmpeg-errors';\n\n/**\n * Extract screenshots from video\n */\nexport class ScreenshotExtractor {\n  constructor(private ffmpegPath: string = 'ffmpeg') {}\n\n  /**\n   * Extract single screenshot\n   */\n  async extractOne(config: ScreenshotConfig): Promise<string> {\n    const inputInfo = await prepareInput(config.input);\n    const inputPath = getInputPath(inputInfo);\n\n    try {\n      const output = Array.isArray(config.output) ? config.output[0] : config.output;\n      mkdirSync(dirname(output), { recursive: true });\n\n      const args = ['-hide_banner'];\n\n      // Seek to time (before input for speed)\n      if (config.time !== undefined) {\n        const timeStr =\n          typeof config.time === 'number' ? this.formatTime(config.time) : config.time;\n        args.push('-ss', timeStr);\n      }\n\n      args.push('-i', inputPath);\n\n      // Frame number (if specified instead of time)\n      if (config.frame !== undefined) {\n        args.push('-vf', `select='eq(n,${config.frame})'`, '-vframes', '1');\n      } else {\n        args.push('-vframes', '1');\n      }\n\n      // Size\n      if (config.size) {\n        const size =\n          typeof config.size === 'string'\n            ? config.size\n            : `${config.size.width}x${config.size.height}`;\n        args.push('-s', size);\n      }\n\n      // Aspect ratio\n      if (config.aspectRatio) {\n        args.push('-aspect', config.aspectRatio);\n      }\n\n      // Quality\n      if (config.quality) {\n        args.push('-q:v', config.quality.toString());\n      }\n\n      // Filters\n      if (config.filters) {\n        const filterString = FilterBuilder.buildVideoFilters(config.filters);\n        if (filterString) {\n          // Combine with frame selection if needed\n          if (config.frame !== undefined) {\n            const existingVf = args[args.indexOf('-vf') + 1];\n            args[args.indexOf('-vf') + 1] = `${existingVf},${filterString}`;\n          } else {\n            args.push('-vf', filterString);\n          }\n        }\n      }\n\n      args.push('-y', output);\n\n      await this.runFFmpeg(args);\n\n      return output;\n    } finally {\n      if (inputInfo.tempPath) {\n        cleanupInput(inputInfo);\n      }\n    }\n  }\n\n  /**\n   * Extract multiple screenshots\n   */\n  async extractMultiple(config: ScreenshotsConfig): Promise<ScreenshotResult> {\n    const inputInfo = await prepareInput(config.input);\n    const inputPath = getInputPath(inputInfo);\n\n    try {\n      const folder = config.folder || '.';\n      const filename = config.filename || 'screenshot-%i.jpg';\n\n      mkdirSync(folder, { recursive: true });\n\n      let timestamps: number[] = [];\n\n      // Determine timestamps\n      if (config.timestamps) {\n        timestamps = config.timestamps.map(t => (typeof t === 'number' ? t : this.parseTime(t)));\n      } else if (config.count) {\n        // Get video duration and distribute evenly\n        const duration = await this.getVideoDuration(inputPath);\n        const interval = duration / (config.count + 1);\n        for (let i = 1; i <= config.count; i++) {\n          timestamps.push(interval * i);\n        }\n      } else if (config.interval) {\n        // Get duration and create timestamps at intervals\n        const duration = await this.getVideoDuration(inputPath);\n        for (let t = 0; t < duration; t += config.interval) {\n          timestamps.push(t);\n        }\n      } else {\n        throw new Error('Must specify timestamps, count, or interval');\n      }\n\n      // Extract each screenshot\n      const files: string[] = [];\n\n      for (let i = 0; i < timestamps.length; i++) {\n        const time = timestamps[i];\n        const outputFile = join(folder, filename.replace('%i', (i + 1).toString()));\n\n        const args = [\n          '-hide_banner',\n          '-ss',\n          this.formatTime(time),\n          '-i',\n          inputPath,\n          '-vframes',\n          '1',\n        ];\n\n        if (config.size) {\n          const size =\n            typeof config.size === 'string'\n              ? config.size\n              : `${config.size.width}x${config.size.height}`;\n          args.push('-s', size);\n        }\n\n        if (config.quality) {\n          args.push('-q:v', config.quality.toString());\n        }\n\n        if (config.filters) {\n          const filterString = FilterBuilder.buildVideoFilters(config.filters);\n          if (filterString) {\n            args.push('-vf', filterString);\n          }\n        }\n\n        args.push('-y', outputFile);\n\n        await this.runFFmpeg(args);\n        files.push(outputFile);\n      }\n\n      return {\n        files,\n        count: files.length,\n        timestamps,\n      };\n    } finally {\n      if (inputInfo.tempPath) {\n        cleanupInput(inputInfo);\n      }\n    }\n  }\n\n  /**\n   * Get video duration\n   */\n  private async getVideoDuration(inputPath: string): Promise<number> {\n    return new Promise((resolve, reject) => {\n      const ffprobe = this.ffmpegPath.replace('ffmpeg', 'ffprobe');\n      const process = spawn(ffprobe, [\n        '-v',\n        'error',\n        '-show_entries',\n        'format=duration',\n        '-of',\n        'default=noprint_wrappers=1:nokey=1',\n        inputPath,\n      ]);\n\n      let output = '';\n      process.stdout.on('data', (data: Buffer) => {\n        output += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve(parseFloat(output.trim()));\n        } else {\n          reject(new Error('Failed to get duration'));\n        }\n      });\n    });\n  }\n\n  /**\n   * Run FFmpeg command\n   */\n  private async runFFmpeg(args: string[]): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const process = spawn(this.ffmpegPath, args);\n      let stderr = '';\n\n      process.stderr?.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve();\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              'Screenshot extraction failed',\n              `${this.ffmpegPath} ${args.join(' ')}`,\n              stderr\n            )\n          );\n        }\n      });\n\n      process.on('error', err => {\n        reject(new FFmpegExecutionError(`Failed to start FFmpeg: ${err.message}`));\n      });\n    });\n  }\n\n  /**\n   * Format time\n   */\n  private formatTime(seconds: number): string {\n    const h = Math.floor(seconds / 3600);\n    const m = Math.floor((seconds % 3600) / 60);\n    const s = seconds % 60;\n    return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${s.toFixed(2).padStart(5, '0')}`;\n  }\n\n  /**\n   * Parse time string\n   */\n  private parseTime(time: string): number {\n    const parts = time.split(':').map(Number);\n    if (parts.length === 3) {\n      return parts[0] * 3600 + parts[1] * 60 + parts[2];\n    }\n    return 0;\n  }\n}\n","import { spawn } from 'child_process';\nimport { writeFileSync, unlinkSync, mkdirSync, existsSync } from 'fs';\nimport { tmpdir } from 'os';\nimport { join, dirname } from 'path';\nimport type { ConcatenationConfig, ConcatenationResult, MergeConfig } from '../types/concat';\nimport { prepareInput, cleanupInput, getInputPath } from './input-handler';\nimport { FFmpegExecutionError } from '../errors/ffmpeg-errors';\n\n/**\n * Video concatenation and merging\n */\nexport class Concatenation {\n  constructor(private ffmpegPath: string = 'ffmpeg') {}\n\n  /**\n   * Concatenate multiple videos\n   */\n  async concatenate(config: ConcatenationConfig): Promise<ConcatenationResult> {\n    const inputInfos = await Promise.all(\n      (Array.isArray(config.inputs[0]) ? config.inputs : config.inputs).map((input: any) =>\n        prepareInput(typeof input === 'object' && input.source ? input.source : input)\n      )\n    );\n\n    try {\n      const method = config.method || 'concat';\n\n      if (method === 'concat') {\n        return await this.simpleConcatenate(inputInfos, config);\n      } else {\n        return await this.complexConcatenate(inputInfos, config);\n      }\n    } finally {\n      inputInfos.forEach(info => {\n        if (info.tempPath) {\n          cleanupInput(info);\n        }\n      });\n    }\n  }\n\n  /**\n   * Simple concatenation (same codec, no re-encoding)\n   */\n  private async simpleConcatenate(\n    inputInfos: any[],\n    config: ConcatenationConfig\n  ): Promise<ConcatenationResult> {\n    // Create concat demuxer file\n    const concatFile = join(tmpdir(), `concat-${Date.now()}.txt`);\n\n    try {\n      const inputPaths = inputInfos.map(info => getInputPath(info));\n      // Use absolute paths in concat file\n      const { resolve } = await import('path');\n      const absolutePaths = inputPaths.map(p => resolve(p));\n      const concatContent = absolutePaths.map(path => `file '${path}'`).join('\\n');\n      writeFileSync(concatFile, concatContent);\n\n      mkdirSync(dirname(config.output), { recursive: true });\n\n      const args = [\n        '-hide_banner',\n        '-f',\n        'concat',\n        '-safe',\n        '0',\n        '-i',\n        concatFile,\n        '-c',\n        'copy', // No re-encoding\n        '-y',\n        config.output,\n      ];\n\n      await this.runFFmpeg(args);\n\n      const duration = await this.getVideoDuration(config.output);\n\n      return {\n        output: config.output,\n        duration,\n        inputCount: inputPaths.length,\n      };\n    } finally {\n      if (existsSync(concatFile)) {\n        unlinkSync(concatFile);\n      }\n    }\n  }\n\n  /**\n   * Complex concatenation (with re-encoding, normalization, transitions)\n   */\n  private async complexConcatenate(\n    inputInfos: any[],\n    config: ConcatenationConfig\n  ): Promise<ConcatenationResult> {\n    const inputPaths = inputInfos.map(info => getInputPath(info));\n\n    mkdirSync(dirname(config.output), { recursive: true });\n\n    const args = ['-hide_banner'];\n\n    // Add all inputs\n    inputPaths.forEach(path => {\n      args.push('-i', path);\n    });\n\n    // Build filter graph for concatenation\n    if (config.normalize?.enabled || config.transitions?.enabled) {\n      // Complex concatenation with filters\n      const filterParts: string[] = [];\n\n      // Normalize each input if needed\n      if (config.normalize?.enabled && config.normalize.video?.size) {\n        const size = config.normalize.video.size;\n        inputPaths.forEach((_, i) => {\n          filterParts.push(`[${i}:v]scale=${size},setsar=1[v${i}]`);\n        });\n      } else {\n        // Just label the streams\n        inputPaths.forEach((_, i) => {\n          filterParts.push(`[${i}:v]null[v${i}]`);\n        });\n      }\n\n      // Concatenate with transitions\n      if (config.transitions?.enabled) {\n        const transDur = config.transitions.duration || 0.5;\n        const transType = config.transitions.type || 'fade';\n\n        // Build xfade filter chain\n        let result = '[v0]';\n        for (let i = 1; i < inputPaths.length; i++) {\n          const offset = i * 10; // Approximate offset\n          result = `${result}[v${i}]xfade=transition=${transType}:duration=${transDur}:offset=${offset}`;\n          if (i < inputPaths.length - 1) {\n            result += `[vt${i}];[vt${i}]`;\n          }\n        }\n        filterParts.push(result);\n      } else {\n        // Simple concat\n        const videoInputs = inputPaths.map((_, i) => `[v${i}]`).join('');\n        filterParts.push(`${videoInputs}concat=n=${inputPaths.length}:v=1:a=0[outv]`);\n\n        // Audio concat\n        const audioInputs = inputPaths.map((_, i) => `[${i}:a]`).join('');\n        filterParts.push(`${audioInputs}concat=n=${inputPaths.length}:v=0:a=1[outa]`);\n      }\n\n      args.push('-filter_complex', filterParts.join(';'));\n      args.push('-map', '[outv]', '-map', '[outa]');\n    } else {\n      // Simple concat filter\n      const videoInputs = inputPaths.map((_, i) => `[${i}:v]`).join('');\n      const audioInputs = inputPaths.map((_, i) => `[${i}:a]`).join('');\n\n      const filter =\n        `${videoInputs}concat=n=${inputPaths.length}:v=1:a=0[outv];` +\n        `${audioInputs}concat=n=${inputPaths.length}:v=0:a=1[outa]`;\n\n      args.push('-filter_complex', filter);\n      args.push('-map', '[outv]', '-map', '[outa]');\n    }\n\n    // Output settings\n    if (config.normalize?.video?.codec) {\n      args.push('-c:v', config.normalize.video.codec);\n    } else {\n      args.push('-c:v', 'libx264');\n    }\n\n    if (config.normalize?.video?.bitrate) {\n      args.push('-b:v', config.normalize.video.bitrate.toString());\n    }\n\n    if (config.normalize?.audio?.codec) {\n      args.push('-c:a', config.normalize.audio.codec);\n    } else {\n      args.push('-c:a', 'aac');\n    }\n\n    args.push('-y', config.output);\n\n    await this.runFFmpeg(args);\n\n    const duration = await this.getVideoDuration(config.output);\n\n    return {\n      output: config.output,\n      duration,\n      inputCount: inputPaths.length,\n    };\n  }\n\n  /**\n   * Merge multiple inputs (video + audio + subtitles)\n   */\n  async merge(config: MergeConfig): Promise<string> {\n    const inputInfos = await Promise.all(config.inputs.map(input => prepareInput(input.source)));\n\n    try {\n      const args = ['-hide_banner'];\n\n      // Add all inputs\n      inputInfos.forEach(info => {\n        args.push('-i', getInputPath(info));\n      });\n\n      // Map streams\n      const videoInput = config.inputs.find(i => i.type === 'video');\n      const audioInputs = config.inputs.filter(i => i.type === 'audio');\n      const subtitleInputs = config.inputs.filter(i => i.type === 'subtitle');\n\n      if (videoInput) {\n        const videoIndex = config.inputs.indexOf(videoInput);\n        args.push('-map', `${videoIndex}:v`);\n      }\n\n      audioInputs.forEach(input => {\n        const index = config.inputs.indexOf(input);\n        args.push('-map', `${index}:a`);\n      });\n\n      subtitleInputs.forEach(input => {\n        const index = config.inputs.indexOf(input);\n        args.push('-map', `${index}:s`);\n      });\n\n      // Output codec\n      if (config.video?.codec) {\n        args.push('-c:v', config.video.codec);\n      } else {\n        args.push('-c:v', 'copy');\n      }\n\n      if (config.audio?.codec) {\n        args.push('-c:a', config.audio.codec);\n      } else {\n        args.push('-c:a', 'copy');\n      }\n\n      mkdirSync(dirname(config.output), { recursive: true });\n      args.push('-y', config.output);\n\n      await this.runFFmpeg(args);\n\n      return config.output;\n    } finally {\n      inputInfos.forEach(info => {\n        if (info.tempPath) {\n          cleanupInput(info);\n        }\n      });\n    }\n  }\n\n  /**\n   * Get video duration\n   */\n  private async getVideoDuration(path: string): Promise<number> {\n    return new Promise((resolve, reject) => {\n      const ffprobe = this.ffmpegPath.replace('ffmpeg', 'ffprobe');\n      const process = spawn(ffprobe, [\n        '-v',\n        'error',\n        '-show_entries',\n        'format=duration',\n        '-of',\n        'default=noprint_wrappers=1:nokey=1',\n        path,\n      ]);\n\n      let output = '';\n      process.stdout.on('data', (data: Buffer) => {\n        output += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve(parseFloat(output.trim()));\n        } else {\n          reject(new Error('Failed to get duration'));\n        }\n      });\n    });\n  }\n\n  /**\n   * Run FFmpeg command\n   */\n  private async runFFmpeg(args: string[]): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const process = spawn(this.ffmpegPath, args);\n      let stderr = '';\n\n      process.stderr?.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve();\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              'Concatenation failed',\n              `${this.ffmpegPath} ${args.join(' ')}`,\n              stderr\n            )\n          );\n        }\n      });\n\n      process.on('error', err => {\n        reject(new FFmpegExecutionError(`Failed to start FFmpeg: ${err.message}`));\n      });\n    });\n  }\n}\n","import { spawn } from 'child_process';\nimport { mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport type { PictureInPictureConfig, SideBySideConfig } from '../types/multi-input';\nimport { prepareInput, cleanupInput, getInputPath } from './input-handler';\nimport { FFmpegExecutionError } from '../errors/ffmpeg-errors';\n\n/**\n * Handle multiple input operations\n */\nexport class MultiInputHandler {\n  constructor(private ffmpegPath: string = 'ffmpeg') {}\n\n  /**\n   * Create picture-in-picture video\n   */\n  async pictureInPicture(config: PictureInPictureConfig): Promise<string> {\n    const [mainInfo, overlayInfo] = await Promise.all([\n      prepareInput(config.main),\n      prepareInput(config.overlay),\n    ]);\n\n    try {\n      const mainPath = getInputPath(mainInfo);\n      const overlayPath = getInputPath(overlayInfo);\n\n      mkdirSync(dirname(config.output), { recursive: true });\n\n      const args = ['-hide_banner', '-i', mainPath, '-i', overlayPath];\n\n      // Build overlay filter\n      let overlayFilter = '[1:v]';\n\n      // Resize overlay if needed\n      if (config.overlaySize) {\n        const size =\n          typeof config.overlaySize === 'string'\n            ? config.overlaySize\n            : `${config.overlaySize.width}x${config.overlaySize.height}`;\n        const [w, h] = size.split('x');\n        overlayFilter += `scale=${w}:${h}[ovl];[ovl]`;\n      }\n\n      // Add border if specified\n      if (config.border) {\n        overlayFilter += `pad=w=iw+${config.border.width * 2}:h=ih+${config.border.width * 2}:x=${config.border.width}:y=${config.border.width}:color=${config.border.color}[ovl];[ovl]`;\n      }\n\n      // Determine position\n      const pos = this.getOverlayPosition(config.position, config.x, config.y);\n\n      // Complete filter\n      const filter = `${overlayFilter}format=rgba[ovl];[0:v][ovl]overlay=${pos.x}:${pos.y}`;\n\n      args.push('-filter_complex', filter);\n\n      // Audio handling\n      if (config.audio === 'main') {\n        args.push('-map', '0:a');\n      } else if (config.audio === 'overlay') {\n        args.push('-map', '1:a');\n      } else if (config.audio === 'both') {\n        args.push('-filter_complex', '[0:a][1:a]amix=inputs=2[a]', '-map', '[a]');\n      } else {\n        args.push('-an');\n      }\n\n      // Video settings\n      if (config.video?.codec) {\n        args.push('-c:v', config.video.codec);\n      }\n      if (config.video?.bitrate) {\n        args.push('-b:v', config.video.bitrate.toString());\n      }\n\n      args.push('-y', config.output);\n\n      await this.runFFmpeg(args);\n\n      return config.output;\n    } finally {\n      if (mainInfo.tempPath) cleanupInput(mainInfo);\n      if (overlayInfo.tempPath) cleanupInput(overlayInfo);\n    }\n  }\n\n  /**\n   * Create side-by-side comparison\n   */\n  async sideBySide(config: SideBySideConfig): Promise<string> {\n    const [leftInfo, rightInfo] = await Promise.all([\n      prepareInput(config.left),\n      prepareInput(config.right),\n    ]);\n\n    try {\n      const leftPath = getInputPath(leftInfo);\n      const rightPath = getInputPath(rightInfo);\n\n      mkdirSync(dirname(config.output), { recursive: true });\n\n      const args = ['-hide_banner', '-i', leftPath, '-i', rightPath];\n\n      const orientation = config.orientation || 'horizontal';\n      let filter = '';\n\n      // Match size if requested\n      if (config.matchSize) {\n        const size = config.targetSize || '1280x720';\n        filter = `[0:v]scale=${size}[left];[1:v]scale=${size}[right];`;\n      } else {\n        filter = '[0:v]null[left];[1:v]null[right];';\n      }\n\n      // Stack videos\n      if (orientation === 'horizontal') {\n        filter += '[left][right]hstack';\n      } else {\n        filter += '[left][right]vstack';\n      }\n\n      // Add separator if specified\n      if (config.separator) {\n        // Note: Separator would need custom filter implementation\n        // For now, just stack\n      }\n\n      args.push('-filter_complex', filter);\n\n      // Audio\n      if (config.audio === 'left') {\n        args.push('-map', '0:a');\n      } else if (config.audio === 'right') {\n        args.push('-map', '1:a');\n      } else if (config.audio === 'both') {\n        args.push('-filter_complex', '[0:a][1:a]amerge[a]', '-map', '[a]');\n      } else {\n        args.push('-an');\n      }\n\n      // Video settings\n      if (config.video?.codec) {\n        args.push('-c:v', config.video.codec);\n      }\n\n      args.push('-y', config.output);\n\n      await this.runFFmpeg(args);\n\n      return config.output;\n    } finally {\n      if (leftInfo.tempPath) cleanupInput(leftInfo);\n      if (rightInfo.tempPath) cleanupInput(rightInfo);\n    }\n  }\n\n  /**\n   * Get overlay position\n   */\n  private getOverlayPosition(\n    position?: string,\n    x?: number | string,\n    y?: number | string\n  ): { x: string; y: string } {\n    if (x !== undefined && y !== undefined) {\n      return { x: x.toString(), y: y.toString() };\n    }\n\n    switch (position) {\n      case 'top-left':\n        return { x: '10', y: '10' };\n      case 'top-right':\n        return { x: 'main_w-overlay_w-10', y: '10' };\n      case 'bottom-left':\n        return { x: '10', y: 'main_h-overlay_h-10' };\n      case 'bottom-right':\n      default:\n        return { x: 'main_w-overlay_w-10', y: 'main_h-overlay_h-10' };\n    }\n  }\n\n  /**\n   * Run FFmpeg command\n   */\n  private async runFFmpeg(args: string[]): Promise<void> {\n    return new Promise((resolve, reject) => {\n      const process = spawn(this.ffmpegPath, args);\n      let stderr = '';\n\n      process.stderr?.on('data', (data: Buffer) => {\n        stderr += data.toString();\n      });\n\n      process.on('close', code => {\n        if (code === 0) {\n          resolve();\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              'Multi-input operation failed',\n              `${this.ffmpegPath} ${args.join(' ')}`,\n              stderr\n            )\n          );\n        }\n      });\n\n      process.on('error', err => {\n        reject(new FFmpegExecutionError(`Failed to start FFmpeg: ${err.message}`));\n      });\n    });\n  }\n}\n","import { EventEmitter } from 'events';\nimport { execSync } from 'child_process';\nimport { existsSync } from 'fs';\nimport { CommandBuilder } from './command-builder';\nimport {\n  parseVersion,\n  parseFormats,\n  parseEncoders,\n  parseDecoders,\n  parseMediaMetadata,\n  parseVideoMetadata,\n  parseImageMetadata,\n} from './parsers';\nimport type { FFmpegVersionInfo, FFmpegCapabilities } from './types/version';\nimport type { MediaMetadata, VideoMetadata, ImageMetadata } from './types/metadata';\nimport {\n  HardwareAcceleration,\n  type HardwareAccelerationValue,\n  type HardwareAccelerationInfo,\n} from './types/hardware';\nimport { StreamType, type StreamTypeValue } from './types/stream';\nimport type { InputSource } from './types/input';\nimport type {\n  ConversionSuggestion,\n  ConversionCompatibility,\n  ConversionRecommendation,\n} from './types/conversion';\nimport type {\n  ConversionConfig,\n  ConversionCallbacks,\n  BatchConversionCallbacks,\n  ConversionResult,\n  ConversionEvents,\n  ProgressInfo,\n  ConversionResultBuffer,\n} from './types/conversion-config';\nimport { filterCodecsByAcceleration, detectHardwareType } from './utils/hardware-detection';\nimport { prepareInput, cleanupInput, getInputPath } from './utils/input-handler';\nimport {\n  generateConversionSuggestions,\n  checkConversionCompatibility,\n  getConversionRecommendation,\n  CODEC_CONTAINER_COMPATIBILITY,\n} from './utils/conversion-helper';\nimport { ExecutionEngine, BatchExecutionEngine } from './utils/execution-engine';\nimport { CommandGenerator } from './utils/command-generator';\nimport { ThumbnailExtractor } from './utils/thumbnail-extractor';\nimport { TrailerGenerator } from './utils/trailer-generator';\nimport { ScreenshotExtractor } from './utils/screenshot-extractor';\nimport { Concatenation } from './utils/concatenation';\nimport { MultiInputHandler } from './utils/multi-input-handler';\nimport type {\n  ThumbnailConfig,\n  ThumbnailResult,\n  TrailerConfig,\n  TrailerResult,\n} from './types/thumbnail';\nimport type { ScreenshotConfig, ScreenshotsConfig, ScreenshotResult } from './types/screenshot';\nimport type { ConcatenationConfig, ConcatenationResult, MergeConfig } from './types/concat';\nimport type { PictureInPictureConfig, SideBySideConfig } from './types/multi-input';\nimport {\n  FFmpegNotFoundError,\n  FFprobeNotFoundError,\n  FFmpegExecutionError,\n  CodecNotSupportedError,\n  FormatNotSupportedError,\n  HardwareAccelerationError,\n} from './errors';\n\nexport interface FFmpegConstructorOptions {\n  ffmpegPath?: string;\n  ffprobePath?: string;\n}\n\nexport class FFmpeg extends EventEmitter {\n  private static ffmpegPath: string = 'ffmpeg';\n  private static ffprobePath: string = 'ffprobe';\n  protected commandBuilder: CommandBuilder;\n\n  constructor(options?: FFmpegConstructorOptions) {\n    super();\n    this.commandBuilder = new CommandBuilder();\n\n    // Set paths from constructor options if provided\n    if (options?.ffmpegPath) {\n      FFmpeg.setFFmpegPath(options.ffmpegPath);\n    } else {\n      // Auto-detect ffmpeg path if not provided\n      this.autoDetectFFmpegPath();\n    }\n\n    if (options?.ffprobePath) {\n      FFmpeg.setFFprobePath(options.ffprobePath);\n    } else {\n      // Auto-detect ffprobe path if not provided\n      this.autoDetectFFprobePath();\n    }\n  }\n\n  /**\n   * Auto-detect FFmpeg binary path\n   */\n  private autoDetectFFmpegPath(): void {\n    try {\n      const command = process.platform === 'win32' ? 'where ffmpeg' : 'which ffmpeg';\n      const path = execSync(command, { encoding: 'utf-8' }).trim().split('\\n')[0];\n\n      if (path && existsSync(path)) {\n        FFmpeg.setFFmpegPath(path);\n      }\n    } catch {\n      // Falls back to system PATH\n    }\n  }\n\n  /**\n   * Auto-detect FFprobe binary path\n   */\n  private autoDetectFFprobePath(): void {\n    try {\n      const command = process.platform === 'win32' ? 'where ffprobe' : 'which ffprobe';\n      const path = execSync(command, { encoding: 'utf-8' }).trim().split('\\n')[0];\n\n      if (path && existsSync(path)) {\n        FFmpeg.setFFprobePath(path);\n      }\n    } catch {\n      // Falls back to system PATH\n    }\n  }\n\n  /**\n   * Validate that FFmpeg binary is accessible\n   */\n  private static validateFFmpegPath(): void {\n    try {\n      execSync(`${FFmpeg.ffmpegPath} -version`, {\n        encoding: 'utf-8',\n        stdio: ['pipe', 'pipe', 'pipe'],\n      });\n    } catch (error) {\n      throw new FFmpegNotFoundError(FFmpeg.ffmpegPath);\n    }\n  }\n\n  /**\n   * Validate that FFprobe binary is accessible\n   */\n  private static validateFFprobePath(): void {\n    try {\n      execSync(`${FFmpeg.ffprobePath} -version`, {\n        encoding: 'utf-8',\n        stdio: ['pipe', 'pipe', 'pipe'],\n      });\n    } catch (error) {\n      throw new FFprobeNotFoundError(FFmpeg.ffprobePath);\n    }\n  }\n\n  /**\n   * Set the path to the FFmpeg binary\n   * @param path - Absolute path to the FFmpeg executable (default: 'ffmpeg' from PATH)\n   */\n  static setFFmpegPath(path: string): void {\n    FFmpeg.ffmpegPath = path;\n  }\n\n  /**\n   * Set the path to the FFprobe binary\n   * @param path - Absolute path to the FFprobe executable (default: 'ffprobe' from PATH)\n   */\n  static setFFprobePath(path: string): void {\n    FFmpeg.ffprobePath = path;\n  }\n\n  /**\n   * Get the configured FFmpeg binary path\n   */\n  static getFFmpegPath(): string {\n    return FFmpeg.ffmpegPath;\n  }\n\n  /**\n   * Get the configured FFprobe binary path\n   */\n  static getFFprobePath(): string {\n    return FFmpeg.ffprobePath;\n  }\n\n  /**\n   * Get FFmpeg version information as structured data\n   */\n  static async getVersion(): Promise<FFmpegVersionInfo> {\n    return new Promise((resolve, reject) => {\n      try {\n        this.validateFFmpegPath();\n\n        const output = execSync(`${FFmpeg.ffmpegPath} -version`, {\n          encoding: 'utf-8',\n          stdio: ['pipe', 'pipe', 'pipe'],\n        });\n\n        resolve(parseVersion(output));\n      } catch (error) {\n        if (error instanceof FFmpegNotFoundError) {\n          reject(error);\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              `Failed to get FFmpeg version: ${error instanceof Error ? error.message : 'Unknown error'}`,\n              `${FFmpeg.ffmpegPath} -version`\n            )\n          );\n        }\n      }\n    });\n  }\n\n  /**\n   * Get available formats (muxers and demuxers)\n   */\n  static async getFormats(): Promise<{ demuxing: string[]; muxing: string[] }> {\n    return new Promise((resolve, reject) => {\n      try {\n        this.validateFFmpegPath();\n\n        const output = execSync(`${FFmpeg.ffmpegPath} -formats`, {\n          encoding: 'utf-8',\n          stdio: ['pipe', 'pipe', 'pipe'],\n        });\n\n        resolve(parseFormats(output));\n      } catch (error) {\n        if (error instanceof FFmpegNotFoundError) {\n          reject(error);\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              `Failed to get formats: ${error instanceof Error ? error.message : 'Unknown error'}`,\n              `${FFmpeg.ffmpegPath} -formats`\n            )\n          );\n        }\n      }\n    });\n  }\n\n  /**\n   * Get available codecs\n   */\n  static async getCodecs(): Promise<{\n    video: { encoders: string[]; decoders: string[] };\n    audio: { encoders: string[]; decoders: string[] };\n    subtitle: { encoders: string[]; decoders: string[] };\n  }> {\n    return new Promise(async (resolve, reject) => {\n      try {\n        this.validateFFmpegPath();\n\n        const [encodersOutput, decodersOutput] = await Promise.all([\n          Promise.resolve(\n            execSync(`${FFmpeg.ffmpegPath} -encoders`, {\n              encoding: 'utf-8',\n              stdio: ['pipe', 'pipe', 'pipe'],\n            })\n          ),\n          Promise.resolve(\n            execSync(`${FFmpeg.ffmpegPath} -decoders`, {\n              encoding: 'utf-8',\n              stdio: ['pipe', 'pipe', 'pipe'],\n            })\n          ),\n        ]);\n\n        const encoders = parseEncoders(encodersOutput);\n        const decoders = parseDecoders(decodersOutput);\n\n        resolve({\n          video: { encoders: encoders.video, decoders: decoders.video },\n          audio: { encoders: encoders.audio, decoders: decoders.audio },\n          subtitle: { encoders: encoders.subtitle, decoders: decoders.subtitle },\n        });\n      } catch (error) {\n        if (error instanceof FFmpegNotFoundError) {\n          reject(error);\n        } else {\n          reject(\n            new FFmpegExecutionError(\n              `Failed to get codecs: ${error instanceof Error ? error.message : 'Unknown error'}`,\n              `${FFmpeg.ffmpegPath} -encoders/-decoders`\n            )\n          );\n        }\n      }\n    });\n  }\n\n  /**\n   * Get all FFmpeg capabilities (version, formats, codecs)\n   */\n  static async getCapabilities(): Promise<FFmpegCapabilities> {\n    const [version, formats, codecs] = await Promise.all([\n      this.getVersion(),\n      this.getFormats(),\n      this.getCodecs(),\n    ]);\n\n    return {\n      version,\n      formats,\n      codecs,\n    };\n  }\n\n  /**\n   * Check if a format is supported for output (muxing)\n   * @throws {FormatNotSupportedError} If format is not supported and throwOnError is true\n   */\n  static async canOutputFormat(format: string, throwOnError: boolean = false): Promise<boolean> {\n    const formats = await this.getFormats();\n    const supported = formats.muxing.includes(format);\n\n    if (!supported && throwOnError) {\n      throw new FormatNotSupportedError(format, 'mux');\n    }\n\n    return supported;\n  }\n\n  /**\n   * Check if a codec can be used for encoding\n   * @throws {CodecNotSupportedError} If codec is not supported and throwOnError is true\n   * @throws {HardwareAccelerationError} If hardware acceleration is not available\n   */\n  static async canEncodeWithCodec(\n    codec: string,\n    type: StreamTypeValue = StreamType.VIDEO,\n    acceleration: HardwareAccelerationValue = HardwareAcceleration.ANY,\n    throwOnError: boolean = false\n  ): Promise<boolean> {\n    const codecs = await this.getCodecs();\n    const availableEncoders = filterCodecsByAcceleration(codecs[type].encoders, acceleration);\n    const supported = availableEncoders.includes(codec);\n\n    if (!supported && throwOnError) {\n      // Check if it's a hardware acceleration issue\n      const accelValue = typeof acceleration === 'string' ? acceleration : acceleration;\n      if (\n        accelValue !== HardwareAcceleration.ANY &&\n        accelValue !== 'any' &&\n        accelValue !== HardwareAcceleration.CPU &&\n        accelValue !== 'cpu'\n      ) {\n        const allEncoders = codecs[type].encoders;\n        if (allEncoders.includes(codec)) {\n          throw new HardwareAccelerationError(accelValue);\n        }\n      }\n      throw new CodecNotSupportedError(codec, type, 'encode');\n    }\n\n    return supported;\n  }\n\n  /**\n   * Check if a codec can be used for decoding\n   * @throws {CodecNotSupportedError} If codec is not supported and throwOnError is true\n   * @throws {HardwareAccelerationError} If hardware acceleration is not available\n   */\n  static async canDecodeWithCodec(\n    codec: string,\n    type: StreamTypeValue = StreamType.VIDEO,\n    acceleration: HardwareAccelerationValue = HardwareAcceleration.ANY,\n    throwOnError: boolean = false\n  ): Promise<boolean> {\n    const codecs = await this.getCodecs();\n    const availableDecoders = filterCodecsByAcceleration(codecs[type].decoders, acceleration);\n    const supported = availableDecoders.includes(codec);\n\n    if (!supported && throwOnError) {\n      // Check if it's a hardware acceleration issue\n      const accelValue = typeof acceleration === 'string' ? acceleration : acceleration;\n      if (\n        accelValue !== HardwareAcceleration.ANY &&\n        accelValue !== 'any' &&\n        accelValue !== HardwareAcceleration.CPU &&\n        accelValue !== 'cpu'\n      ) {\n        const allDecoders = codecs[type].decoders;\n        if (allDecoders.includes(codec)) {\n          throw new HardwareAccelerationError(accelValue);\n        }\n      }\n      throw new CodecNotSupportedError(codec, type, 'decode');\n    }\n\n    return supported;\n  }\n\n  /**\n   * Verify that output format and codecs are supported\n   */\n  static async verifyOutputSupport(options: {\n    format?: string;\n    videoCodec?: string;\n    audioCodec?: string;\n    acceleration?: HardwareAccelerationValue;\n  }): Promise<{\n    supported: boolean;\n    details: {\n      format?: { supported: boolean; name: string };\n      videoCodec?: { supported: boolean; name: string; hardwareType?: HardwareAccelerationValue };\n      audioCodec?: { supported: boolean; name: string };\n    };\n    unsupported: string[];\n  }> {\n    const acceleration = options.acceleration || HardwareAcceleration.ANY;\n    const details: {\n      format?: { supported: boolean; name: string };\n      videoCodec?: { supported: boolean; name: string; hardwareType?: HardwareAccelerationValue };\n      audioCodec?: { supported: boolean; name: string };\n    } = {};\n    const unsupported: string[] = [];\n\n    // Check format\n    if (options.format) {\n      const formatSupported = await this.canOutputFormat(options.format);\n      details.format = { supported: formatSupported, name: options.format };\n      if (!formatSupported) {\n        unsupported.push(`format: ${options.format}`);\n      }\n    }\n\n    // Check video codec\n    if (options.videoCodec && options.videoCodec !== 'copy') {\n      const videoSupported = await this.canEncodeWithCodec(\n        options.videoCodec,\n        'video',\n        acceleration\n      );\n      const hardwareType = detectHardwareType(options.videoCodec);\n      details.videoCodec = {\n        supported: videoSupported,\n        name: options.videoCodec,\n        hardwareType,\n      };\n      if (!videoSupported) {\n        unsupported.push(`video codec: ${options.videoCodec} (${hardwareType})`);\n      }\n    }\n\n    // Check audio codec\n    if (options.audioCodec && options.audioCodec !== 'copy') {\n      const audioSupported = await this.canEncodeWithCodec(\n        options.audioCodec,\n        'audio',\n        acceleration\n      );\n      details.audioCodec = { supported: audioSupported, name: options.audioCodec };\n      if (!audioSupported) {\n        unsupported.push(`audio codec: ${options.audioCodec}`);\n      }\n    }\n\n    return {\n      supported: unsupported.length === 0,\n      details,\n      unsupported,\n    };\n  }\n\n  /**\n   * Get available hardware acceleration types\n   */\n  static async getAvailableHardwareAcceleration(): Promise<HardwareAccelerationInfo[]> {\n    const codecs = await this.getCodecs();\n    const result: HardwareAccelerationInfo[] = [];\n\n    // Check CPU (always available if we have any CPU codecs)\n    const cpuEncoders = filterCodecsByAcceleration(codecs.video.encoders, HardwareAcceleration.CPU);\n    const cpuDecoders = filterCodecsByAcceleration(codecs.video.decoders, HardwareAcceleration.CPU);\n    if (cpuEncoders.length > 0 || cpuDecoders.length > 0) {\n      result.push({\n        type: HardwareAcceleration.CPU,\n        available: true,\n        encoders: cpuEncoders,\n        decoders: cpuDecoders,\n      });\n    }\n\n    // Check each GPU type\n    const gpuTypes: HardwareAccelerationValue[] = [\n      HardwareAcceleration.NVIDIA,\n      HardwareAcceleration.INTEL,\n      HardwareAcceleration.AMD,\n      HardwareAcceleration.VAAPI,\n      HardwareAcceleration.VIDEOTOOLBOX,\n      HardwareAcceleration.V4L2,\n    ];\n    for (const type of gpuTypes) {\n      const encoders = filterCodecsByAcceleration(codecs.video.encoders, type);\n      const decoders = filterCodecsByAcceleration(codecs.video.decoders, type);\n\n      if (encoders.length > 0 || decoders.length > 0) {\n        result.push({\n          type,\n          available: true,\n          encoders,\n          decoders,\n        });\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Get encoders filtered by hardware acceleration type\n   */\n  static async getEncodersByAcceleration(\n    acceleration: HardwareAccelerationValue = HardwareAcceleration.ANY,\n    type: StreamTypeValue = StreamType.VIDEO\n  ): Promise<string[]> {\n    const codecs = await this.getCodecs();\n    return filterCodecsByAcceleration(codecs[type].encoders, acceleration);\n  }\n\n  /**\n   * Get decoders filtered by hardware acceleration type\n   */\n  static async getDecodersByAcceleration(\n    acceleration: HardwareAccelerationValue = HardwareAcceleration.ANY,\n    type: StreamTypeValue = StreamType.VIDEO\n  ): Promise<string[]> {\n    const codecs = await this.getCodecs();\n    return filterCodecsByAcceleration(codecs[type].decoders, acceleration);\n  }\n\n  /**\n   * Get raw metadata from a media file using FFprobe\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async getMetadata(input: InputSource): Promise<MediaMetadata> {\n    let inputInfo;\n\n    try {\n      FFmpeg.validateFFprobePath();\n\n      // Prepare input (convert buffer/stream to temp file if needed)\n      inputInfo = await prepareInput(input);\n      const inputPath = getInputPath(inputInfo);\n\n      const args = this.commandBuilder.buildProbeCommand(inputPath);\n      const output = execSync(`${FFmpeg.getFFprobePath()} ${args.join(' ')}`, {\n        encoding: 'utf-8',\n        stdio: ['pipe', 'pipe', 'pipe'],\n      });\n\n      const metadata = parseMediaMetadata(output);\n      return metadata;\n    } catch (error) {\n      if (error instanceof FFprobeNotFoundError) {\n        throw error;\n      } else {\n        throw new FFmpegExecutionError(\n          `Failed to get metadata: ${error instanceof Error ? error.message : 'Unknown error'}`,\n          `${FFmpeg.getFFprobePath()} probe`\n        );\n      }\n    } finally {\n      // Clean up temporary file if created\n      if (inputInfo) {\n        cleanupInput(inputInfo);\n      }\n    }\n  }\n\n  /**\n   * Get structured video metadata\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async getVideoMetadata(input: InputSource): Promise<VideoMetadata> {\n    const metadata = await this.getMetadata(input);\n    return parseVideoMetadata(metadata);\n  }\n\n  /**\n   * Get structured image metadata\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async getImageMetadata(input: InputSource): Promise<ImageMetadata> {\n    const metadata = await this.getMetadata(input);\n    return parseImageMetadata(metadata);\n  }\n\n  /**\n   * Get video duration in seconds\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async getDuration(input: InputSource): Promise<number> {\n    const metadata = await this.getVideoMetadata(input);\n    return metadata.duration;\n  }\n\n  /**\n   * Get video resolution\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async getResolution(input: InputSource): Promise<{ width: number; height: number }> {\n    const metadata = await this.getVideoMetadata(input);\n    return {\n      width: metadata.width,\n      height: metadata.height,\n    };\n  }\n\n  /**\n   * Get video frame rate\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async getFrameRate(input: InputSource): Promise<number> {\n    const metadata = await this.getVideoMetadata(input);\n    return metadata.frameRate;\n  }\n\n  /**\n   * Check if file is a video\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async isVideo(input: InputSource): Promise<boolean> {\n    try {\n      const metadata = await this.getMetadata(input);\n      return metadata.streams.some(s => s.codecType === 'video' && (s.frameRate || s.avgFrameRate)); // Has video stream with frame rate\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * Check if file is an image\n   * @param input - File path, Buffer, or ReadStream\n   */\n  async isImage(input: InputSource): Promise<boolean> {\n    try {\n      const metadata = await this.getMetadata(input);\n      const videoStreams = metadata.streams.filter(s => s.codecType === 'video');\n      // Image has video stream but no frame rate\n      return videoStreams.length > 0 && !videoStreams[0].frameRate && !videoStreams[0].avgFrameRate;\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * Get conversion suggestions for a video file\n   * Analyzes the video and suggests compatible formats and codecs\n   */\n  async getConversionSuggestions(input: InputSource): Promise<ConversionSuggestion> {\n    const metadata = await this.getVideoMetadata(input);\n    const formats = await FFmpeg.getFormats();\n    const codecs = await FFmpeg.getCodecs();\n\n    return generateConversionSuggestions(metadata, formats, codecs);\n  }\n\n  /**\n   * Check compatibility between source and target conversion settings\n   */\n  async checkConversionCompatibility(\n    input: InputSource,\n    targetFormat: string,\n    targetVideoCodec: string,\n    targetAudioCodec?: string\n  ): Promise<ConversionCompatibility> {\n    const metadata = await this.getVideoMetadata(input);\n\n    return checkConversionCompatibility(\n      metadata.videoCodec,\n      metadata.audioCodec,\n      metadata.format.formatName.split(',')[0],\n      targetVideoCodec,\n      targetAudioCodec,\n      targetFormat\n    );\n  }\n\n  /**\n   * Get recommended conversion settings based on use case\n   */\n  async getConversionRecommendation(\n    input: InputSource,\n    useCase: 'web' | 'mobile' | 'quality' | 'size' | 'compatibility' = 'web'\n  ): Promise<ConversionRecommendation> {\n    const metadata = await this.getVideoMetadata(input);\n    return getConversionRecommendation(metadata, useCase);\n  }\n\n  /**\n   * Check if a video can be remuxed to a different format without transcoding\n   */\n  async canRemux(input: InputSource, targetFormat: string): Promise<boolean> {\n    const suggestions = await this.getConversionSuggestions(input);\n    return suggestions.canRemux && suggestions.suggestedFormats.includes(targetFormat);\n  }\n\n  /**\n   * Get list of formats that support direct copy (remux) for this video\n   */\n  async getRemuxableFormats(input: InputSource): Promise<string[]> {\n    const metadata = await this.getVideoMetadata(input);\n    const formats = await FFmpeg.getFormats();\n\n    const videoCodec = metadata.videoCodec;\n    const videoCompatible = CODEC_CONTAINER_COMPATIBILITY[videoCodec] || [];\n\n    // Return only formats that are available in FFmpeg\n    return videoCompatible.filter(fmt => formats.muxing.includes(fmt));\n  }\n\n  /**\n   * Convert video/audio with configuration-based API\n   */\n  /**\n   * Convert media file with event-based progress tracking (fluent-ffmpeg style)\n   */\n  convert(config: ConversionConfig): ConversionResult {\n    const engine = new ExecutionEngine(FFmpeg.ffmpegPath);\n    let currentProgress: ProgressInfo | null = null;\n    let isCancelled = false;\n\n    // Create event emitter for this specific conversion\n    const eventEmitter = new EventEmitter();\n    \n    const events: ConversionEvents = {\n      start: (callback: (command: string) => void) => {\n        eventEmitter.on('start', callback);\n      },\n      progress: (callback: (progress: ProgressInfo) => void) => {\n        eventEmitter.on('progress', callback);\n      },\n      end: (callback: () => void) => {\n        eventEmitter.on('end', callback);\n      },\n      error: (callback: (error: Error) => void) => {\n        eventEmitter.on('error', callback);\n      }\n    };\n\n    // Forward events from engine to eventEmitter\n    engine.on('start', (command: string) => {\n      currentProgress = null;\n      eventEmitter.emit('start', command);\n    });\n    engine.on('progress', (progress: ProgressInfo) => {\n      currentProgress = progress;\n      eventEmitter.emit('progress', progress);\n    });\n    engine.on('end', () => {\n      eventEmitter.emit('end');\n    });\n    engine.on('error', (error: Error) => {\n      eventEmitter.emit('error', error);\n    });\n\n    const promise = engine.execute(config).catch(error => {\n      if (!isCancelled) {\n        eventEmitter.emit('error', error);\n      }\n      throw error;\n    });\n\n    return {\n      promise,\n      events,\n      cancel: () => {\n        isCancelled = true;\n        engine.cancel();\n      },\n      getProgress: () => currentProgress,\n    };\n  }\n\n  /**\n   * Convert media file with callback-based progress tracking (legacy)\n   */\n  async convertWithCallbacks(\n    config: ConversionConfig,\n    callbacks?: ConversionCallbacks\n  ): Promise<void> {\n    const engine = new ExecutionEngine(FFmpeg.ffmpegPath);\n\n    // Forward events from engine to this instance\n    engine.on('start', cmd => this.emit('start', cmd));\n    engine.on('progress', progress => this.emit('progress', progress));\n    engine.on('end', () => this.emit('end'));\n    engine.on('error', error => this.emit('error', error));\n\n    return engine.execute(config, callbacks);\n  }\n\n  /**\n   * Convert and return output as Buffer with event-based progress tracking\n   */\n  convertToBuffer(config: Omit<ConversionConfig, 'output'>): ConversionResultBuffer {\n    const engine = new ExecutionEngine(FFmpeg.ffmpegPath);\n    let currentProgress: ProgressInfo | null = null;\n    let isCancelled = false;\n\n    // Create event emitter for this specific conversion\n    const eventEmitter = new EventEmitter();\n    \n    const events: ConversionEvents = {\n      start: (callback: (command: string) => void) => {\n        eventEmitter.on('start', callback);\n      },\n      progress: (callback: (progress: ProgressInfo) => void) => {\n        eventEmitter.on('progress', callback);\n      },\n      end: (callback: () => void) => {\n        eventEmitter.on('end', callback);\n      },\n      error: (callback: (error: Error) => void) => {\n        eventEmitter.on('error', callback);\n      }\n    };\n\n    // Forward events from engine to eventEmitter\n    engine.on('start', (command: string) => {\n      currentProgress = null;\n      eventEmitter.emit('start', command);\n    });\n    engine.on('progress', (progress: ProgressInfo) => {\n      currentProgress = progress;\n      eventEmitter.emit('progress', progress);\n    });\n    engine.on('end', () => {\n      eventEmitter.emit('end');\n    });\n    engine.on('error', (error: Error) => {\n      eventEmitter.emit('error', error);\n    });\n\n    const promise = engine.executeToBuffer(config).catch(error => {\n      if (!isCancelled) {\n        eventEmitter.emit('error', error);\n      }\n      throw error;\n    });\n\n    return {\n      promise,\n      events,\n      cancel: () => {\n        isCancelled = true;\n        engine.cancel();\n      },\n      getProgress: () => currentProgress,\n    };\n  }\n\n  /**\n   * Convert and return output as Buffer with callback-based progress tracking (legacy)\n   */\n  async convertToBufferWithCallbacks(\n    config: Omit<ConversionConfig, 'output'>,\n    callbacks?: ConversionCallbacks\n  ): Promise<Buffer> {\n    const engine = new ExecutionEngine(FFmpeg.ffmpegPath);\n\n    // Forward events\n    engine.on('start', cmd => this.emit('start', cmd));\n    engine.on('progress', progress => this.emit('progress', progress));\n    engine.on('end', () => this.emit('end'));\n    engine.on('error', error => this.emit('error', error));\n\n    return engine.executeToBuffer(config, callbacks);\n  }\n\n  /**\n   * Convert multiple files sequentially\n   */\n  async convertBatch(\n    configs: ConversionConfig[],\n    callbacks?: BatchConversionCallbacks\n  ): Promise<void> {\n    const batchEngine = new BatchExecutionEngine(FFmpeg.ffmpegPath);\n    return batchEngine.executeBatch(configs, callbacks);\n  }\n\n  /**\n   * Convert multiple files in parallel\n   */\n  async convertBatchParallel(\n    configs: ConversionConfig[],\n    maxConcurrent: number = 2,\n    callbacks?: BatchConversionCallbacks\n  ): Promise<void> {\n    const batchEngine = new BatchExecutionEngine(FFmpeg.ffmpegPath);\n    return batchEngine.executeBatchParallel(configs, maxConcurrent, callbacks);\n  }\n\n  /**\n   * Validate configuration without executing\n   */\n  validateConfig(config: ConversionConfig): { valid: boolean; errors: string[] } {\n    return CommandGenerator.validate(config);\n  }\n\n  /**\n   * Build FFmpeg command without executing (dry run)\n   */\n  buildCommand(config: ConversionConfig): string {\n    return CommandGenerator.generateCommandString(config, FFmpeg.ffmpegPath);\n  }\n\n  /**\n   * Extract thumbnails from video\n   */\n  async extractThumbnails(config: ThumbnailConfig): Promise<ThumbnailResult> {\n    const extractor = new ThumbnailExtractor(FFmpeg.ffmpegPath);\n    return extractor.extract(config);\n  }\n\n  /**\n   * Generate video trailer\n   */\n  async generateTrailer(config: TrailerConfig): Promise<TrailerResult> {\n    const generator = new TrailerGenerator(FFmpeg.ffmpegPath);\n    return generator.generate(config);\n  }\n\n  /**\n   * Extract single screenshot\n   */\n  async extractScreenshot(config: ScreenshotConfig): Promise<string> {\n    const extractor = new ScreenshotExtractor(FFmpeg.ffmpegPath);\n    return extractor.extractOne(config);\n  }\n\n  /**\n   * Extract multiple screenshots\n   */\n  async extractScreenshots(config: ScreenshotsConfig): Promise<ScreenshotResult> {\n    const extractor = new ScreenshotExtractor(FFmpeg.ffmpegPath);\n    return extractor.extractMultiple(config);\n  }\n\n  /**\n   * Concatenate multiple videos\n   */\n  async concatenate(config: ConcatenationConfig): Promise<ConcatenationResult> {\n    const concatenation = new Concatenation(FFmpeg.ffmpegPath);\n    return concatenation.concatenate(config);\n  }\n\n  /**\n   * Merge multiple inputs (video + audio + subtitles)\n   */\n  async merge(config: MergeConfig): Promise<string> {\n    const concatenation = new Concatenation(FFmpeg.ffmpegPath);\n    return concatenation.merge(config);\n  }\n\n  /**\n   * Create picture-in-picture video\n   */\n  async pictureInPicture(config: PictureInPictureConfig): Promise<string> {\n    const handler = new MultiInputHandler(FFmpeg.ffmpegPath);\n    return handler.pictureInPicture(config);\n  }\n\n  /**\n   * Create side-by-side comparison video\n   */\n  async sideBySide(config: SideBySideConfig): Promise<string> {\n    const handler = new MultiInputHandler(FFmpeg.ffmpegPath);\n    return handler.sideBySide(config);\n  }\n}\n","/**\n * Video and Audio Filter Types\n */\n\nimport type { Color } from './enums';\n\n// Common scaling algorithms\nexport enum ScalingAlgorithm {\n  FAST_BILINEAR = 'fast_bilinear',\n  BILINEAR = 'bilinear',\n  BICUBIC = 'bicubic',\n  EXPERIMENTAL = 'experimental',\n  NEIGHBOR = 'neighbor',\n  AREA = 'area',\n  BICUBLIN = 'bicublin',\n  GAUSS = 'gauss',\n  SINC = 'sinc',\n  LANCZOS = 'lanczos',\n  SPLINE = 'spline',\n}\n\nexport type ScalingAlgorithmValue = ScalingAlgorithm | string;\n\n// Deinterlace methods\nexport enum DeinterlaceMode {\n  YADIF = 'yadif',\n  BWDIF = 'bwdif',\n  W3FDIF = 'w3fdif',\n}\n\nexport type DeinterlaceModeValue = DeinterlaceMode | string;\n\n// Denoise filter types\nexport enum DenoiseFilterType {\n  HQDN3D = 'hqdn3d',\n  NLMEANS = 'nlmeans',\n  ATADENOISE = 'atadenoise',\n  VAGUEDENOISER = 'vaguedenoiser',\n}\n\nexport type DenoiseFilterValue = DenoiseFilterType | string;\n\n// Video filter interfaces\nexport interface ScaleFilter {\n  width?: number | string; // 1920, '1920', 'iw*2', '-1' (auto)\n  height?: number | string; // 1080, '1080', 'ih*2', '-1' (auto)\n  algorithm?: ScalingAlgorithmValue;\n  force_original_aspect_ratio?: 'disable' | 'decrease' | 'increase';\n  force_divisible_by?: number; // Force dimensions divisible by N (e.g., 2)\n}\n\nexport interface CropFilter {\n  width: number | string;\n  height: number | string;\n  x?: number | string; // X position (default: center)\n  y?: number | string; // Y position (default: center)\n}\n\nexport interface PadFilter {\n  width: number | string;\n  height: number | string;\n  x?: number | string; // X position\n  y?: number | string; // Y position\n  color?: string | Color; // 'black', Color.BLACK, '#FF0000'\n}\n\nexport interface DeinterlaceFilter {\n  mode?: DeinterlaceModeValue;\n  parity?: 'tff' | 'bff' | 'auto'; // Top field first, bottom field first, auto\n  deint?: 'all' | 'interlaced';\n}\n\nexport interface VideoDenoiseFilter {\n  filter?: DenoiseFilterValue;\n  luma_spatial?: number; // Spatial luma strength (0-10)\n  chroma_spatial?: number; // Spatial chroma strength (0-10)\n  luma_tmp?: number; // Temporal luma strength (0-10)\n  chroma_tmp?: number; // Temporal chroma strength (0-10)\n}\n\nexport interface SharpenFilter {\n  luma_msize_x?: number; // Luma matrix horizontal size (3-23)\n  luma_msize_y?: number; // Luma matrix vertical size (3-23)\n  luma_amount?: number; // Luma effect strength (-2 to 5)\n  chroma_msize_x?: number;\n  chroma_msize_y?: number;\n  chroma_amount?: number;\n}\n\nexport interface ColorFilter {\n  brightness?: number; // -1 to 1\n  contrast?: number; // -1000 to 1000\n  saturation?: number; // 0 to 3\n  gamma?: number; // 0.1 to 10\n  gamma_r?: number; // Red gamma\n  gamma_g?: number; // Green gamma\n  gamma_b?: number; // Blue gamma\n}\n\nexport interface RotateFilter {\n  angle: number | string; // Angle in radians or degrees\n  fillcolor?: string | Color; // Background color: 'black', Color.BLACK, '#FF0000'\n  bilinear?: boolean; // Use bilinear interpolation\n}\n\nexport interface FlipFilter {\n  horizontal?: boolean; // Flip horizontally (hflip)\n  vertical?: boolean; // Flip vertically (vflip)\n}\n\nexport interface WatermarkFilter {\n  input: string; // Path to watermark image\n  x?: number | string; // X position: 10, 'main_w-overlay_w-10'\n  y?: number | string; // Y position: 10, 'main_h-overlay_h-10'\n  opacity?: number; // 0.0 to 1.0\n  enable?: string; // Time expression, e.g., 'between(t,10,20)'\n}\n\nexport interface TextFilter {\n  text: string;\n  fontfile?: string;\n  fontsize?: number;\n  fontcolor?: string | Color; // Font color: 'white', Color.WHITE, '#FFFFFF'\n  x?: number | string;\n  y?: number | string;\n  shadowcolor?: string | Color; // Shadow color\n  shadowx?: number;\n  shadowy?: number;\n  borderw?: number;\n  bordercolor?: string | Color; // Border color\n}\n\nexport interface FadeFilter {\n  type: 'in' | 'out';\n  start_frame?: number;\n  nb_frames?: number;\n  start_time?: number;\n  duration?: number;\n  color?: string;\n}\n\n// Audio filter interfaces\nexport interface VolumeFilter {\n  volume: number | string; // 0.5, '10dB', '0.5'\n  precision?: 'fixed' | 'float' | 'double';\n}\n\nexport interface AudioDenoiseFilter {\n  noise_reduction?: number; // 0.01 to 1\n  noise_type?: 'white' | 'vinyl' | 'shellac' | 'hiss';\n}\n\nexport interface EqualizerFilter {\n  frequency: number; // Center frequency in Hz\n  width_type?: 'h' | 'q' | 'o' | 's';\n  width?: number;\n  gain?: number; // Gain in dB\n}\n\nexport interface TempoFilter {\n  tempo: number; // 0.5 to 2.0 (playback speed)\n}\n\nexport interface PitchFilter {\n  pitch: number; // Semitones to shift (-12 to 12)\n}\n\n// Complex filter specifications\nexport interface FilterSpec {\n  inputs?: string[];\n  filter: string;\n  options?: Record<string, any>;\n  outputs?: string[];\n}\n\n// Combined video filters configuration\nexport interface VideoFilters {\n  // Scaling and resizing\n  scale?: ScaleFilter;\n\n  // Cropping and padding\n  crop?: CropFilter;\n  pad?: PadFilter;\n\n  // Quality enhancement\n  deinterlace?: DeinterlaceFilter;\n  denoise?: VideoDenoiseFilter;\n  sharpen?: SharpenFilter;\n\n  // Color adjustments\n  color?: ColorFilter;\n\n  // Transformations\n  rotate?: RotateFilter;\n  flip?: FlipFilter;\n\n  // Overlays\n  watermark?: WatermarkFilter;\n  text?: TextFilter;\n\n  // Effects\n  fade?: FadeFilter;\n\n  // Custom filters (raw FFmpeg filter strings)\n  custom?: string[];\n}\n\n// Combined audio filters configuration\nexport interface AudioFilters {\n  // Volume\n  volume?: VolumeFilter;\n\n  // Noise reduction\n  denoise?: AudioDenoiseFilter;\n\n  // Equalizer\n  equalizer?: EqualizerFilter[];\n\n  // Tempo and pitch\n  tempo?: TempoFilter;\n  pitch?: PitchFilter;\n\n  // Custom filters (raw FFmpeg filter strings)\n  custom?: string[];\n}\n\n// Complex filter graph\nexport interface FilterGraph {\n  video?: VideoFilters;\n  audio?: AudioFilters;\n  complex?: FilterSpec[]; // For advanced multi-input/output filters\n}\n\n// Upscaling-specific options\nexport interface UpscalingOptions {\n  algorithm: ScalingAlgorithmValue;\n  targetWidth: number;\n  targetHeight: number;\n  enhanceSharpness?: boolean; // Apply unsharp filter after upscaling\n  denoiseBeforeScale?: boolean; // Denoise before upscaling\n  sharpnessAmount?: number; // 0-5 (for unsharp filter)\n}\n\n// Downscaling-specific options\nexport interface DownscalingOptions {\n  algorithm: ScalingAlgorithmValue;\n  targetWidth: number;\n  targetHeight: number;\n  deinterlace?: boolean; // Deinterlace before downscaling\n  preserveDetails?: boolean; // Use better algorithm for detail preservation\n}\n","/**\n * Video encoding presets (speed vs quality)\n */\nexport enum VideoPreset {\n  ULTRAFAST = 'ultrafast',\n  SUPERFAST = 'superfast',\n  VERYFAST = 'veryfast',\n  FASTER = 'faster',\n  FAST = 'fast',\n  MEDIUM = 'medium',\n  SLOW = 'slow',\n  SLOWER = 'slower',\n  VERYSLOW = 'veryslow',\n}\n\n/**\n * H.264/H.265 encoding profiles\n */\nexport enum VideoProfile {\n  // H.264 profiles\n  BASELINE = 'baseline',\n  MAIN = 'main',\n  HIGH = 'high',\n  HIGH10 = 'high10',\n  HIGH422 = 'high422',\n  HIGH444 = 'high444',\n}\n\n/**\n * H.264/H.265 encoding levels\n */\nexport enum VideoLevel {\n  LEVEL_3_0 = '3.0',\n  LEVEL_3_1 = '3.1',\n  LEVEL_3_2 = '3.2',\n  LEVEL_4_0 = '4.0',\n  LEVEL_4_1 = '4.1',\n  LEVEL_4_2 = '4.2',\n  LEVEL_5_0 = '5.0',\n  LEVEL_5_1 = '5.1',\n  LEVEL_5_2 = '5.2',\n}\n\n/**\n * Pixel formats\n */\nexport enum PixelFormat {\n  YUV420P = 'yuv420p',\n  YUV422P = 'yuv422p',\n  YUV444P = 'yuv444p',\n  YUV420P10LE = 'yuv420p10le',\n  YUV422P10LE = 'yuv422p10le',\n  YUV444P10LE = 'yuv444p10le',\n  RGB24 = 'rgb24',\n  BGR24 = 'bgr24',\n  RGBA = 'rgba',\n  BGRA = 'bgra',\n  GRAY = 'gray',\n  GRAY16LE = 'gray16le',\n  NV12 = 'nv12',\n  NV21 = 'nv21',\n}\n\n/**\n * AAC encoding profiles\n */\nexport enum AACProfile {\n  AAC_LOW = 'aac_low',\n  AAC_HE = 'aac_he',\n  AAC_HE_V2 = 'aac_he_v2',\n  AAC_LD = 'aac_ld',\n  AAC_ELD = 'aac_eld',\n}\n\n/**\n * Common aspect ratios\n */\nexport enum AspectRatio {\n  RATIO_16_9 = '16:9',\n  RATIO_4_3 = '4:3',\n  RATIO_21_9 = '21:9',\n  RATIO_1_1 = '1:1',\n  RATIO_9_16 = '9:16', // Vertical (Instagram Stories, TikTok)\n  RATIO_3_2 = '3:2',\n  RATIO_5_4 = '5:4',\n}\n\n/**\n * Common colors for filters\n */\nexport enum Color {\n  BLACK = 'black',\n  WHITE = 'white',\n  RED = 'red',\n  GREEN = 'green',\n  BLUE = 'blue',\n  YELLOW = 'yellow',\n  CYAN = 'cyan',\n  MAGENTA = 'magenta',\n  TRANSPARENT = 'transparent',\n}\n\n/**\n * Video quality presets\n */\nexport enum QualityPreset {\n  ULTRA = 'ultra', // Highest quality, largest file\n  HIGH = 'high',\n  MEDIUM = 'medium',\n  LOW = 'low',\n  VERY_LOW = 'very_low', // Lowest quality, smallest file\n}\n\n/**\n * Common resolutions\n */\nexport enum Resolution {\n  // SD\n  SD_480P = '854x480',\n  SD_576P = '1024x576',\n  \n  // HD\n  HD_720P = '1280x720',\n  HD_1080P = '1920x1080',\n  \n  // 2K\n  QHD = '2560x1440',\n  \n  // 4K\n  UHD_4K = '3840x2160',\n  DCI_4K = '4096x2160',\n  \n  // 8K\n  UHD_8K = '7680x4320',\n  \n  // Mobile/Social\n  INSTAGRAM_SQUARE = '1080x1080',\n  INSTAGRAM_STORY = '1080x1920',\n  TIKTOK = '1080x1920',\n  YOUTUBE_SHORTS = '1080x1920',\n}\n\n/**\n * Frame rates\n */\nexport enum FrameRate {\n  FPS_23_976 = 23.976,\n  FPS_24 = 24,\n  FPS_25 = 25,\n  FPS_29_97 = 29.97,\n  FPS_30 = 30,\n  FPS_50 = 50,\n  FPS_59_94 = 59.94,\n  FPS_60 = 60,\n  FPS_120 = 120,\n}\n\n/**\n * Audio sample rates (Hz)\n */\nexport enum SampleRate {\n  RATE_8000 = 8000,\n  RATE_11025 = 11025,\n  RATE_16000 = 16000,\n  RATE_22050 = 22050,\n  RATE_32000 = 32000,\n  RATE_44100 = 44100,\n  RATE_48000 = 48000,\n  RATE_88200 = 88200,\n  RATE_96000 = 96000,\n  RATE_192000 = 192000,\n}\n\n/**\n * Audio channels\n */\nexport enum AudioChannels {\n  MONO = 1,\n  STEREO = 2,\n  SURROUND_2_1 = 3,\n  SURROUND_4_0 = 4,\n  SURROUND_5_0 = 5,\n  SURROUND_5_1 = 6,\n  SURROUND_7_1 = 8,\n}\n\n","import type { ConversionConfig } from '../types/conversion-config';\nimport { VideoCodec, AudioCodec } from '../types/codecs';\nimport { OutputFormat } from '../types/formats';\n\n/**\n * Preset configurations for common use cases\n * Usage: import { presets } from 'ffmpeg-forge';\n *        ffmpeg.convert({ ...presets.youtube.hd1080, input: 'in.mp4', output: 'out.mp4' })\n */\nexport const presets = {\n  /**\n   * Web-optimized presets\n   */\n  web: {\n    /** 1080p HD for web streaming */\n    hd: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '1920x1080',\n        bitrate: '5M',\n        preset: 'medium',\n        profile: 'high',\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '128k',\n      },\n    } as Partial<ConversionConfig>,\n\n    /** 720p SD for web */\n    sd: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '1280x720',\n        bitrate: '3M',\n        preset: 'medium',\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '96k',\n      },\n    } as Partial<ConversionConfig>,\n\n    /** Mobile optimized */\n    mobile: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '854x480',\n        bitrate: '1.5M',\n        preset: 'medium',\n        profile: 'baseline',\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '64k',\n      },\n    } as Partial<ConversionConfig>,\n  },\n\n  /**\n   * YouTube upload presets\n   */\n  youtube: {\n    /** 1080p HD for YouTube */\n    hd1080: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '1920x1080',\n        bitrate: '8M',\n        preset: 'slow',\n        profile: 'high',\n        level: '4.2',\n        pixelFormat: 'yuv420p',\n        fps: 30,\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '192k',\n        channels: 2,\n        frequency: 48000,\n      },\n    } as Partial<ConversionConfig>,\n\n    /** 720p HD for YouTube */\n    hd720: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '1280x720',\n        bitrate: '5M',\n        preset: 'medium',\n        profile: 'high',\n        level: '4.0',\n        fps: 30,\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '128k',\n        frequency: 48000,\n      },\n    } as Partial<ConversionConfig>,\n\n    /** 4K UHD for YouTube */\n    uhd4k: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '3840x2160',\n        bitrate: '45M',\n        preset: 'slow',\n        profile: 'high',\n        level: '5.2',\n        fps: 30,\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '192k',\n        frequency: 48000,\n      },\n    } as Partial<ConversionConfig>,\n  },\n\n  /**\n   * Instagram presets\n   */\n  instagram: {\n    /** Square feed post (1:1) */\n    feed: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '1080x1080',\n        bitrate: '5M',\n        preset: 'medium',\n        fps: 30,\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '128k',\n      },\n    } as Partial<ConversionConfig>,\n\n    /** Vertical story (9:16) */\n    story: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        size: '1080x1920',\n        bitrate: '4M',\n        preset: 'medium',\n        fps: 30,\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '128k',\n      },\n    } as Partial<ConversionConfig>,\n  },\n\n  /**\n   * TikTok preset (vertical video)\n   */\n  tiktok: {\n    format: OutputFormat.MP4,\n    video: {\n      codec: VideoCodec.H264,\n      size: '1080x1920',\n      bitrate: '6M',\n      preset: 'medium',\n      fps: 30,\n    },\n    audio: {\n      codec: AudioCodec.AAC,\n      bitrate: '192k',\n      frequency: 44100,\n    },\n  } as Partial<ConversionConfig>,\n\n  /**\n   * Quality-focused presets\n   */\n  quality: {\n    /** Ultra high quality */\n    high: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H265,\n        quality: 18,\n        preset: 'slow',\n        profile: 'main',\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '256k',\n      },\n    } as Partial<ConversionConfig>,\n\n    /** Medium quality */\n    medium: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        quality: 23,\n        preset: 'medium',\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '128k',\n      },\n    } as Partial<ConversionConfig>,\n\n    /** Lower quality for smaller files */\n    low: {\n      format: OutputFormat.MP4,\n      video: {\n        codec: VideoCodec.H264,\n        quality: 28,\n        preset: 'fast',\n      },\n      audio: {\n        codec: AudioCodec.AAC,\n        bitrate: '96k',\n      },\n    } as Partial<ConversionConfig>,\n  },\n\n  /**\n   * Size-optimized presets\n   */\n  size: {\n    /** Very small file size */\n    small: {\n      format: OutputFormat.WEBM,\n      video: {\n        codec: VideoCodec.VP9,\n        quality: 35,\n        preset: 'medium',\n      },\n      audio: {\n        codec: AudioCodec.OPUS,\n        bitrate: '96k',\n      },\n    } as Partial<ConversionConfig>,\n\n    /** Extremely small file size */\n    tiny: {\n      format: OutputFormat.WEBM,\n      video: {\n        codec: VideoCodec.VP9,\n        quality: 40,\n        size: '640x360',\n        fps: 24,\n      },\n      audio: {\n        codec: AudioCodec.OPUS,\n        bitrate: '64k',\n      },\n    } as Partial<ConversionConfig>,\n  },\n\n  /**\n   * DVD quality (legacy format)\n   */\n  dvd: {\n    format: OutputFormat.MPEG,\n    video: {\n      codec: VideoCodec.MPEG2,\n      bitrate: '6M',\n      size: '720x480',\n      fps: 29.97,\n    },\n    audio: {\n      codec: AudioCodec.AC3,\n      bitrate: '192k',\n      channels: 2,\n      frequency: 48000,\n    },\n  } as Partial<ConversionConfig>,\n};\n\n// Export legacy Presets for backward compatibility\nexport const Presets = presets;\n\n/**\n * Get preset by path\n * @example getPreset('youtube', 'hd1080')\n * @example getPreset('web', 'mobile')\n */\nexport function getPreset(category: string, name: string): Partial<ConversionConfig> | undefined {\n  const cat = presets[category as keyof typeof presets];\n  if (!cat) return undefined;\n  \n  if (typeof cat === 'object' && 'format' in cat) {\n    return cat as Partial<ConversionConfig>;\n  }\n  \n  return cat[name as keyof typeof cat] as Partial<ConversionConfig>;\n}\n\n/**\n * List all available presets\n */\nexport function listPresets() {\n  const result: Array<{ category: string; name: string; config: Partial<ConversionConfig> }> = [];\n  \n  for (const [category, value] of Object.entries(presets)) {\n    if (typeof value === 'object' && 'format' in value) {\n      result.push({ category, name: category, config: value as Partial<ConversionConfig> });\n    } else {\n      for (const [name, config] of Object.entries(value)) {\n        result.push({ category, name, config: config as Partial<ConversionConfig> });\n      }\n    }\n  }\n  \n  return result;\n}\n"],"names":["HardwareAcceleration","StreamType","join","tmpdir","writeFileSync","unlinkSync","VideoCodec","AudioCodec","OutputFormat","execSync","path","EventEmitter","spawn","_a","_b","_c","mkdirSync","dirname","process","existsSync","events","ScalingAlgorithm","DeinterlaceMode","DenoiseFilterType","VideoPreset","VideoProfile","VideoLevel","PixelFormat","AACProfile","AspectRatio","Color","QualityPreset","Resolution","FrameRate","SampleRate","AudioChannels"],"mappings":"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"}