Microphone recording and audio playback.
Recording requires :microphone permission (Mob.Permissions.request/2).
iOS additionally needs NSMicrophoneUsageDescription in
Info.plist; Android needs RECORD_AUDIO in
AndroidManifest.xml. The default mix mob.new templates ship
both. See the permissions guide for the
cross-platform table.
Playback requires no permission.
Recording
Mob.Audio.start_recording(socket, format: :aac, quality: :medium)
Mob.Audio.stop_recording(socket)
# → handle_info({:audio, :recorded, %{path: path, duration: seconds}}, socket)
# → handle_info({:audio, :error, reason}, socket)Playback
Mob.Audio.play(socket, "/path/to/file.m4a")
Mob.Audio.play(socket, "/path/to/file.m4a", loop: true, volume: 0.8)
Mob.Audio.stop_playback(socket)
Mob.Audio.set_volume(socket, 0.5)
# → handle_info({:audio, :playback_finished, %{path: path}}, socket)
# → handle_info({:audio, :playback_error, %{reason: reason}}, socket)iOS: AVAudioPlayer / AVPlayer. Android: MediaPlayer.
Summary
Functions
Play an audio file. Stops any currently playing audio first.
Schedule path to begin playing at absolute local wall-clock time
at_wall_ms (in System.system_time(:millisecond) terms — caller is
responsible for translating from a server-supplied target time via their
own clock-sync component).
Adjust playback volume (0.0–1.0) without stopping playback.
Start recording audio from the microphone.
Stop the currently playing audio.
Stop the in-progress recording and save it to a temp file.
Result arrives as {:audio, :recorded, %{path: ..., duration: ...}}.
Types
Functions
@spec play(Mob.Socket.t(), String.t(), keyword()) :: Mob.Socket.t()
Play an audio file. Stops any currently playing audio first.
Options:
loop: boolean(defaultfalse)volume: float 0.0–1.0(default1.0)
Result arrives as:
{:audio, :playback_finished, %{path: path}}{:audio, :playback_error, %{reason: reason}}
@spec play_at(Mob.Socket.t(), String.t(), integer(), keyword()) :: Mob.Socket.t()
Schedule path to begin playing at absolute local wall-clock time
at_wall_ms (in System.system_time(:millisecond) terms — caller is
responsible for translating from a server-supplied target time via their
own clock-sync component).
The audio hardware clock — not BEAM's timer wheel — fires playback at
the requested instant. Multiple play_at/3 calls accumulate on the
player's timeline (call stop_playback/1 to flush). If at_wall_ms is
already in the past, the buffer plays as soon as the audio engine can.
Options:
volume: float 0.0–1.0(default1.0)
Result arrives as {:audio, :playback_finished, %{path: path}} when
the scheduled buffer drains, or {:audio, :playback_error, %{reason: reason}} if the file fails to open.
iOS: AVAudioEngine + AVAudioPlayerNode.scheduleBuffer(_:at:options:),
with the at: AVAudioTime constructed from mach_absolute_time so the
buffer starts at the requested host time.
Android: TODO — falls back to immediate playback on Android until the AAudio port lands.
@spec set_volume(Mob.Socket.t(), float()) :: Mob.Socket.t()
Adjust playback volume (0.0–1.0) without stopping playback.
@spec start_recording( Mob.Socket.t(), keyword() ) :: Mob.Socket.t()
Start recording audio from the microphone.
Options:
format: :aac | :wav(default:aac)quality: :low | :medium | :high(default:medium)
@spec stop_playback(Mob.Socket.t()) :: Mob.Socket.t()
Stop the currently playing audio.
@spec stop_recording(Mob.Socket.t()) :: Mob.Socket.t()
Stop the in-progress recording and save it to a temp file.
Result arrives as {:audio, :recorded, %{path: ..., duration: ...}}.