Skip to content

Unify conversion API with generic convertTo method #13

@sjoenk

Description

@sjoenk

Problem

The current API has separate methods per output format with inconsistent parameter support:

  • convertToWav(inputPath, outputPath, {sampleRate, channels, bitDepth}) — supports audio transformation parameters
  • convertToM4a(inputPath, outputPath) — no parameters at all, despite M4A supporting sampleRate, channels, and bitRate

On Android, performM4aConversion already decodes to PCM and re-encodes via encodePcmToM4a — the infrastructure to accept custom sampleRate/channels is there, but the values are just passed through from the source. The bitRate is hardcoded at 128kbps.

On iOS/macOS, AVAssetExportSession (high-level) is used, which doesn't expose these parameters. Supporting them would require switching to AVAssetReader + AVAssetWriter.

This also means adding any future output format (FLAC, OGG, etc.) would require new top-level methods, multiplying the API surface.

Proposal

Replace format-specific methods with a single generic conversion method:

enum AudioFormat { wav, m4a }

abstract class FormatOptions {}

class WavOptions extends FormatOptions {
  final int? bitDepth;       // 8, 16, 24, 32 — default 16
  final bool includeHeader;  // default true
}

class M4aOptions extends FormatOptions {
  final int? bitRate;        // default 128000
}

// File-based
static Future<String> convertTo(
  String inputPath,
  String outputPath, {
  required AudioFormat format,
  int? sampleRate,
  int? channels,
  FormatOptions? options,
});

// Bytes-based
static Future<Uint8List> convertToBytes(
  Uint8List inputData, {
  required String formatHint,
  required AudioFormat format,
  int? sampleRate,
  int? channels,
  FormatOptions? options,
});

Shared parameters (sampleRate, channels) live on the method. Format-specific parameters (bitDepth, bitRate, compressionLevel) live in a typed options object.

Benefits

  • Closes the M4A parameter gap — sampleRate, channels, and bitRate become configurable
  • Single method channel call on the native side instead of one per format
  • Easy to extend — adding FLAC just means adding AudioFormat.flac and FlacOptions(compressionLevel)
  • Consistent API — all formats go through the same pipeline

Scope

  • Add AudioFormat enum and FormatOptions class hierarchy
  • Implement generic convertTo / convertToBytes in the Dart layer
  • Update platform interface and method channel
  • Add sampleRate/channels/bitRate support to M4A on Android
  • Switch iOS/macOS M4A from AVAssetExportSession to AVAssetReader+AVAssetWriter for parameter support
  • Update web, Linux, and Windows implementations
  • Deprecate convertToWav, convertToM4a and their bytes variants (keep as thin wrappers during deprecation period)
  • Update trimAudioBytes outputFormat string parameter to use AudioFormat enum
  • Update tests and documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions