Skip to content

fix(audio): prevent audio session interference during recording #4548

Merged
rabble merged 3 commits into
mainfrom
fix/ios-audio-volume-increase
May 20, 2026
Merged

fix(audio): prevent audio session interference during recording #4548
rabble merged 3 commits into
mainfrom
fix/ios-audio-volume-increase

Conversation

@hm21
Copy link
Copy Markdown
Contributor

@hm21 hm21 commented May 19, 2026

Description

Resolve the issue of the recording-audio on iOS devices getting progressively louder during recording.

Related Issue: Closes #4539

Type of Change

  • ✨ New feature (non-breaking change which adds functionality)
  • 🛠️ Bug fix (non-breaking change which fixes an issue)
  • ❌ Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 Code refactor
  • ✅ Build configuration change
  • 📝 Documentation
  • 🗑️ Chore

@hm21 hm21 self-assigned this May 19, 2026
@github-actions

This comment has been minimized.

@hm21 hm21 marked this pull request as ready for review May 19, 2026 04:57
@hm21 hm21 requested a review from NotThatKindOfDrLiz May 19, 2026 04:59
@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Member

@rabble rabble left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — PR #4548: prevent audio session interference during recording

Overview

Targeted fix for #4539 (iOS recording-mic volume ramp-up). Roots out the cause: just_audio's AudioPlayer was calling setCategory(.playback) on the camera-owned shared AVAudioSession when the countdown beep / lip-sync playback player was constructed, which triggered attachAudioToSessionIfNeeded() on the native camera controller, resetting VPIO/AGC mid-capture. The fix passes handleAudioSessionActivation: false to every just_audio player used during recording, via two new injectable default factories on VideoRecorderNotifier.

What's good

  • Right layer. The fix sits at the construction site of the players the recorder owns — not buried in the recorder's hot path. No await is introduced between session change and capture start (per code_style.md's Future.delayed ban).
  • No state pollution. No mutable instance vars hold session state; the factories are final configuration (architecture.md / state_management.md compliant).
  • Documentation is excellent. Each factory's dartdoc explains the whysetCategory(.playback) -> attachAudioToSessionIfNeeded() -> VPIO/AGC reset — with a backlink to #4539. Future maintainers will not silently drop handleAudioSessionActivation: false.
  • Tests anchor the wiring. The new regression group ("VideoRecorderNotifier - Audio Service Factories (#4539)") asserts: (a) default factories return the expected service types, (b) startRecording actually invokes the injected CountdownSoundService factory exactly once when the timer is enabled. Renaming or removing the factories breaks the constructor and the tests. This is the right shape — the behaviour under test (factory wiring) is what protects the fix.
  • coverage:ignore is justified inline. The JustAudioSimplePlayer constructor comment explicitly explains why the thin pass-through can't be unit-tested and points to the indirect coverage via the recorder factories. Strict-coverage gates won't be silently subverted.
  • Permission flow is untouched — mic permission gating is not in this diff. Recording hot path unchanged structurally.

Minor observations (non-blocking)

  • Unicode escape in dartdoc. simple_audio_player.dart line ~33 has a literal in the doc comment ("the associated tests — see #4539") rather than the em dash itself. Cosmetic — renders as in IDE hover. Trivial follow-up.
  • No direct assertion on the boolean. The tests verify the factory is invoked, not that handleAudioSessionActivation: false is forwarded. The forwarding is exercised only at integration. Acceptable given the documentation and the small surface, but a future iteration could expose a getter on JustAudioSimplePlayer (test-only) to assert the flag explicitly. Not a blocker — would add coverage cost for a one-line wiring.
  • Positional constructor params keep growing. VideoRecorderNotifier([CameraService?, CountdownSoundServiceFactory?, AudioPlaybackServiceFactory?]) — three optional positionals. Migrating to named parameters in a follow-up would improve readability at call sites, but the existing positional-cameraService convention pre-dates this PR and changing it would broaden scope.
  • Test timeout is Duration(seconds: 30) for the countdown test because the 3-second timer runs in real time. The comment is candid about this. Long-term, threading a fake clock into the countdown would let this drop back to default. Out of scope here.

Risk

Low. The change is additive (new optional params with defaults preserving the safer behaviour), platform-side code is untouched (no AVAudioSession code in Swift/Kotlin), and the test suite locks the wiring. CI is 14/14 green. The only platform whose behaviour changes is iOS, which is exactly the regression surface.

Verdict

Approve. Well-scoped, well-documented, and the test seam is positioned to catch the exact regression this PR fixes.

@NotThatKindOfDrLiz NotThatKindOfDrLiz force-pushed the fix/ios-audio-volume-increase branch from 3e5295a to e93aaf6 Compare May 19, 2026 14:58
@NotThatKindOfDrLiz
Copy link
Copy Markdown
Member

Pushed a follow-up commit to tighten the regression guard on the lip-sync playback path.

What changed:

  • added a VideoRecorderNotifier test that injects audioPlaybackServiceFactory
  • selects a sound through videoEditorProvider
  • verifies startRecording() uses the injected playback service for configureForRecording, loadAudio, and play
  • verifies cleanup still goes through stop and resetAudioSession

Local verification I ran on the rebased branch:

  • flutter test test/providers/video_recorder_provider_test.dart
  • flutter analyze test/providers/video_recorder_provider_test.dart
  • repo pre-push analyzer/test gate

@hm21 can you confirm the on-device iOS verification as well:

  1. the countdown beep is still audible
  2. the recorded volume stays stable after using the countdown

Once that confirmation is in and CI is green, this looks ready to approve.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown

Mobile PR Preview

Preview refreshed for f1812d1

Last refresh: f1812d1 at 2026-05-19 15:16:45 UTC (preview run)

Property Value
Preview URL https://032e862e.openvine-app.pages.dev
Pages project openvine-app
Preview branch pr-4548
PR branch fix/ios-audio-volume-increase
Commit f1812d1

Copy link
Copy Markdown
Member

@NotThatKindOfDrLiz NotThatKindOfDrLiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the missing playback-path regression coverage, then isolated it into its own skip-optimization test file so the optimized CI run stays stable. Local targeted verification and the refreshed GitHub suite are green. I left a PR comment asking for explicit iOS device confirmation on countdown audibility and stable recorded volume.

Copy link
Copy Markdown
Member

@rabble rabble left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rabble rabble merged commit 11191f2 into main May 20, 2026
10 checks passed
@rabble rabble deleted the fix/ios-audio-volume-increase branch May 20, 2026 00:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: audio progressively gets louder during iOS recording after using countdown feature

3 participants