Skip to content
This repository was archived by the owner on Dec 9, 2025. It is now read-only.
This repository was archived by the owner on Dec 9, 2025. It is now read-only.

Improve Opus decoder error handling with frame skipping #13

Description

@unforced

Problem

Currently, if a single Opus frame is corrupted during decoding, the entire recording fails. This is too aggressive and can result in complete data loss.

Location: lib/utils/audio/wav_bytes_util.dart:176-185

Uint8List _processOpus() {
  final decodedSamples = <int>[];
  
  for (final frame in frames) {
    final decoded = _opusDecoder!.decode(input: Uint8List.fromList(frame));
    decodedSamples.addAll(decoded); // Fails entire decode if one frame bad
  }
  
  return _convertToLittleEndianBytes(decodedSamples);
}

Suggested Solution

Skip corrupted frames instead of failing:

Uint8List _processOpus() {
  final decodedSamples = <int>[];
  int skippedFrames = 0;
  
  for (int i = 0; i < frames.length; i++) {
    try {
      final decoded = _opusDecoder!.decode(input: Uint8List.fromList(frames[i]));
      decodedSamples.addAll(decoded);
    } catch (e) {
      debugPrint('[WavBytesUtil] Skipping corrupted Opus frame $i: $e');
      skippedFrames++;
      
      // Insert silence for corrupted frame (20ms at 16kHz = 320 samples)
      decodedSamples.addAll(List.filled(320, 0));
    }
  }
  
  if (skippedFrames > 0) {
    debugPrint('[WavBytesUtil] Skipped $skippedFrames corrupted frames');
  }
  
  return _convertToLittleEndianBytes(decodedSamples);
}

Benefits

  • Partial recording recovery instead of complete failure
  • Better user experience (some audio > no audio)
  • More resilient to BLE transmission errors
  • Graceful degradation

Trade-offs

  • Introduces brief silence/gaps in audio where frames were corrupted
  • Could mask data quality issues if not logged properly

Priority

Medium - Improves robustness for edge cases

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions