Android only. Capture the device's whole output mix from inside a Mob app —
including audio produced by other apps and by native players (a game's own
AudioTrack) that bypass Mob.Audio.
A normal app cannot tap the global output mix with a session-0 Visualizer
(privileged: ERROR_NO_INIT), so this plugin uses the consent-gated
MediaProjection + AudioPlaybackCapture path (Android API 29+). Because capture
requires a per-session system consent dialog and a typed foreground service, it is a
test-environment dependency for agent-driven verification, not a capability you
ship in a production app.
Platform support
- Android 10+ (API 29): full capture of the output mix, subject to each
source app's
allowAudioPlaybackCapture(default-on for non-privileged apps targeting API 29+;VOICE_COMMUNICATIONusage and DRM output are never captured by design). - iOS: not supported, and not possible. Apple provides no public API for an app
to capture another app's or the system's audio output (a sandbox/privacy limit).
Every call returns
{:error, :unsupported_on_platform}— this is permanent, not a pending feature. To check your own app's audio instead (e.g. a game engine running inside the Mob app), meter it at the source rather than using this plugin.
Usage
MobAudioCapture.start(socket)
# → handle_info({:audio_capture, :permission, :granted | :denied}, socket)
# once granted, while audio is playing anywhere on the device:
MobAudioCapture.output_level()
# => {-12.0, -3.4} # {rms_db, peak_db}, or :silent
MobAudioCapture.stop(socket)Capture must be active for output_level/0 to read; otherwise it returns
{:error, :not_capturing}.
Summary
Functions
Build the config map passed to audio_capture_start/1. Pure function exposed so
tests can pin defaults + serialisation without the NIF.
Read the current captured-mix level as {rms_db, peak_db} (dBFS), :silent when
there is no measurable signal, or {:error, reason}.
Begin capturing the device output mix. Triggers the MediaProjection consent
dialog; the outcome arrives as {:audio_capture, :permission, :granted | :denied}
to the calling process. Once granted, capture runs in a foreground service until
stop/1.
Stop the active capture session and tear down the foreground service.
Types
Functions
Build the config map passed to audio_capture_start/1. Pure function exposed so
tests can pin defaults + serialisation without the NIF.
@spec output_level() :: {float(), float()} | :silent | {:error, level_error()}
Read the current captured-mix level as {rms_db, peak_db} (dBFS), :silent when
there is no measurable signal, or {:error, reason}.
reason is :not_capturing (no active session — call start/1 first),
:needs_record_audio (Android permission not granted at runtime), or
:unsupported_on_platform (iOS).
@spec start( Mob.Socket.t(), keyword() ) :: Mob.Socket.t()
Begin capturing the device output mix. Triggers the MediaProjection consent
dialog; the outcome arrives as {:audio_capture, :permission, :granted | :denied}
to the calling process. Once granted, capture runs in a foreground service until
stop/1.
Options:
:usages— which audio usages to capture, any of:media,:game,:unknown(default[:media, :game, :unknown]). These are the only usagesAudioPlaybackCaptureis permitted to record.
@spec stop(Mob.Socket.t()) :: Mob.Socket.t()
Stop the active capture session and tear down the foreground service.