expo-audio 0.3.4 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,10 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.3.5 — 2025-02-19
14
+
15
+ _This version does not introduce any user-facing changes._
16
+
13
17
  ## 0.3.4 — 2025-01-19
14
18
 
15
19
  ### 💡 Others
@@ -30,6 +34,8 @@
30
34
  - On `Android`, allow player to accept a `null` audio source. ([#33854](https://github.com/expo/expo/pull/33854) by [@alanjhughes](https://github.com/alanjhughes))
31
35
  - Override the `replace` method on the `AudioPlayer` so the source can be parsed correctly. ([#33708](https://github.com/expo/expo/pull/33708) by [@alanjhughes](https://github.com/alanjhughes))
32
36
  - [Android] Remove unused `setAudioMode()` parameters. ([#34031](https://github.com/expo/expo/pull/34031) by [@alanjhughes](https://github.com/alanjhughes))
37
+ - [Android] Improvements in recording handling. ([#34841](https://github.com/expo/expo/pull/34841) by [@alanjhughes](https://github.com/alanjhughes))
38
+ - Fix `AudioMode` defaults. ([#34920](https://github.com/expo/expo/pull/34920) by [@alanjhughes](https://github.com/alanjhughes))
33
39
 
34
40
  ## 0.3.1 — 2024-12-16
35
41
 
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'expo.modules.audio'
4
- version = '0.3.4'
4
+ version = '0.3.5'
5
5
 
6
6
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
7
  apply from: expoModulesCorePlugin
@@ -14,7 +14,7 @@ android {
14
14
  namespace "expo.modules.audio"
15
15
  defaultConfig {
16
16
  versionCode 1
17
- versionName "0.3.4"
17
+ versionName "0.3.5"
18
18
  }
19
19
 
20
20
  compileOptions {
@@ -33,6 +33,7 @@ import expo.modules.kotlin.modules.ModuleDefinition
33
33
  import kotlinx.coroutines.launch
34
34
  import kotlinx.coroutines.runBlocking
35
35
  import okhttp3.OkHttpClient
36
+ import java.io.File
36
37
  import kotlin.math.min
37
38
 
38
39
  @androidx.annotation.OptIn(androidx.media3.common.util.UnstableApi::class)
@@ -313,7 +314,7 @@ class AudioModule : Module() {
313
314
  }
314
315
 
315
316
  Property("uri") { ref ->
316
- ref.uri
317
+ ref.filePath
317
318
  }
318
319
 
319
320
  Property("isRecording") { ref ->
@@ -321,7 +322,7 @@ class AudioModule : Module() {
321
322
  }
322
323
 
323
324
  Property("currentTime") { ref ->
324
- ref.uptime
325
+ ref.startTime
325
326
  }
326
327
 
327
328
  AsyncFunction("prepareToRecordAsync") { ref: AudioRecorder, options: RecordingOptions? ->
@@ -331,7 +332,9 @@ class AudioModule : Module() {
331
332
 
332
333
  Function("record") { ref: AudioRecorder ->
333
334
  checkRecordingPermission()
334
- ref.record()
335
+ if (!ref.isPrepared) {
336
+ ref.record()
337
+ }
335
338
  }
336
339
 
337
340
  Function("pause") { ref: AudioRecorder ->
@@ -345,7 +348,11 @@ class AudioModule : Module() {
345
348
  }
346
349
 
347
350
  Function("getStatus") { ref: AudioRecorder ->
348
- ref.getAudioRecorderStatus()
351
+ try {
352
+ return@Function ref.getAudioRecorderStatus()
353
+ } catch (e: Exception) {
354
+ throw e
355
+ }
349
356
  }
350
357
 
351
358
  AsyncFunction("getCurrentInput") { ref: AudioRecorder ->
@@ -362,16 +369,24 @@ class AudioModule : Module() {
362
369
  }
363
370
  }
364
371
 
365
- private fun createMediaItem(source: AudioSource?): MediaSource? = source?.let {
366
- val factory = createDataSourceFactory(it)
367
- it.uri?.let { uri ->
368
- val item = MediaItem.fromUri(uri)
369
- buildMediaSourceFactory(factory, item)
372
+ private fun createMediaItem(source: AudioSource?): MediaSource? = source?.uri?.let { uri ->
373
+ val factory = createDataSourceFactory(source)
374
+ val uri = if (Util.isLocalFileUri(Uri.parse(source.uri))) {
375
+ Uri.fromFile(File(source.uri))
376
+ } else {
377
+ Uri.parse(source.uri)
370
378
  }
379
+ val item = MediaItem.fromUri(uri)
380
+ buildMediaSourceFactory(factory, item)
371
381
  }
372
382
 
373
383
  private fun createDataSourceFactory(audioSource: AudioSource): DataSource.Factory {
374
- val isLocal = Util.isLocalFileUri(Uri.parse(audioSource.uri))
384
+ val uri = if (Util.isLocalFileUri(Uri.parse(audioSource.uri))) {
385
+ Uri.fromFile(File(audioSource.uri))
386
+ } else {
387
+ Uri.parse(audioSource.uri)
388
+ }
389
+ val isLocal = Util.isLocalFileUri(uri)
375
390
  return if (isLocal) {
376
391
  DefaultDataSource.Factory(context)
377
392
  } else {
@@ -379,7 +394,6 @@ class AudioModule : Module() {
379
394
  audioSource.headers?.let { headers ->
380
395
  setDefaultRequestProperties(headers)
381
396
  }
382
- DefaultDataSource.Factory(context, this)
383
397
  }
384
398
  }
385
399
  }
@@ -396,14 +410,13 @@ class AudioModule : Module() {
396
410
  mediaItem: MediaItem
397
411
  ): MediaSource {
398
412
  val uri = mediaItem.localConfiguration?.uri
399
- val newFactory = when (val type = uri?.let { retrieveStreamType(it) }) {
413
+ return when (val type = uri?.let { retrieveStreamType(it) }) {
400
414
  CONTENT_TYPE_SS -> SsMediaSource.Factory(factory)
401
415
  CONTENT_TYPE_DASH -> DashMediaSource.Factory(factory)
402
416
  CONTENT_TYPE_HLS -> HlsMediaSource.Factory(factory)
403
417
  CONTENT_TYPE_OTHER -> ProgressiveMediaSource.Factory(factory)
404
418
  else -> throw IllegalStateException("Unsupported type: $type")
405
- }
406
- return newFactory.createMediaSource(MediaItem.fromUri(uri))
419
+ }.createMediaSource(mediaItem)
407
420
  }
408
421
 
409
422
  private fun <T> runOnMain(block: () -> T): T =
@@ -10,7 +10,6 @@ import androidx.media3.common.AudioAttributes
10
10
  import androidx.media3.common.C
11
11
  import androidx.media3.common.MediaItem
12
12
  import androidx.media3.common.Player
13
- import androidx.media3.common.Player.MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED
14
13
  import androidx.media3.common.util.UnstableApi
15
14
  import androidx.media3.exoplayer.ExoPlayer
16
15
  import androidx.media3.exoplayer.source.MediaSource
@@ -18,9 +17,12 @@ import expo.modules.kotlin.AppContext
18
17
  import expo.modules.kotlin.sharedobjects.SharedRef
19
18
  import kotlinx.coroutines.CoroutineScope
20
19
  import kotlinx.coroutines.Dispatchers
20
+ import kotlinx.coroutines.Job
21
21
  import kotlinx.coroutines.cancel
22
22
  import kotlinx.coroutines.delay
23
- import kotlinx.coroutines.isActive
23
+ import kotlinx.coroutines.flow.flow
24
+ import kotlinx.coroutines.flow.launchIn
25
+ import kotlinx.coroutines.flow.onEach
24
26
  import kotlinx.coroutines.launch
25
27
  import kotlinx.coroutines.withContext
26
28
  import java.util.UUID
@@ -33,18 +35,11 @@ class AudioPlayer(
33
35
  context: Context,
34
36
  appContext: AppContext,
35
37
  source: MediaSource?,
36
- updateInterval: Double
38
+ private val updateInterval: Double
37
39
  ) : SharedRef<ExoPlayer>(
38
40
  ExoPlayer.Builder(context)
39
41
  .setLooper(context.mainLooper)
40
- .build()
41
- .apply {
42
- source?.let {
43
- setMediaSource(it)
44
- }
45
- setAudioAttributes(AudioAttributes.DEFAULT, true)
46
- prepare()
47
- },
42
+ .build(),
48
43
  appContext
49
44
  ) {
50
45
  val id = UUID.randomUUID().toString()
@@ -57,20 +52,34 @@ class AudioPlayer(
57
52
  private var visualizer: Visualizer? = null
58
53
  private var playing = false
59
54
 
60
- val currentTime get() = player.currentPosition / 1000
61
- val duration get() = if (player.duration != C.TIME_UNSET) player.duration / 1000 else 0
55
+ private var updateJob: Job? = null
56
+
57
+ val currentTime get() = player.currentPosition / 1000f
58
+ val duration get() = if (player.duration != C.TIME_UNSET) player.duration / 1000f else 0f
62
59
 
63
60
  init {
64
- addPlayerListeners()
65
61
  player.setAudioAttributes(AudioAttributes.DEFAULT, true)
66
- playerScope.launch {
67
- while (isActive) {
68
- if (playing) {
69
- sendPlayerUpdate()
70
- }
62
+ addPlayerListeners()
63
+ source?.let {
64
+ setMediaSource(source)
65
+ }
66
+ }
67
+
68
+ private fun setMediaSource(source: MediaSource) {
69
+ player.setMediaSource(source)
70
+ player.prepare()
71
+ startUpdating()
72
+ }
73
+
74
+ private fun startUpdating() {
75
+ updateJob = flow {
76
+ while (true) {
77
+ emit(Unit)
71
78
  delay(updateInterval.toLong())
72
79
  }
73
80
  }
81
+ .onEach { sendPlayerUpdate() }
82
+ .launchIn(playerScope)
74
83
  }
75
84
 
76
85
  private fun addPlayerListeners() = player.addListener(object : Player.Listener {
@@ -81,22 +90,33 @@ class AudioPlayer(
81
90
  }
82
91
  }
83
92
 
93
+ override fun onIsLoadingChanged(isLoading: Boolean) {
94
+ playerScope.launch {
95
+ sendPlayerUpdate(mapOf("isLoaded" to isLoading))
96
+ }
97
+ }
98
+
84
99
  override fun onPlaybackStateChanged(playbackState: Int) {
85
100
  playerScope.launch {
86
- sendPlayerUpdate(mapOf("status" to playbackStateToString(playbackState)))
101
+ sendPlayerUpdate(mapOf("playbackState" to playbackStateToString(playbackState)))
87
102
  }
88
103
  }
89
104
 
90
105
  override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
91
- if (reason == MEDIA_ITEM_TRANSITION_REASON_PLAYLIST_CHANGED) {
92
- playerScope.launch {
93
- sendPlayerUpdate()
94
- }
106
+ playerScope.launch {
107
+ sendPlayerUpdate()
95
108
  }
96
109
  }
97
110
  })
98
111
 
99
112
  fun setSamplingEnabled(enabled: Boolean) {
113
+ appContext?.reactContext?.let {
114
+ if (ContextCompat.checkSelfPermission(it, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
115
+ Log.d(TAG, "\'android.permission.RECORD_AUDIO\' is required to use audio sampling. Please request this permission and try again.")
116
+ return
117
+ }
118
+ }
119
+
100
120
  samplingEnabled = enabled
101
121
  if (enabled) {
102
122
  createVisualizer()
@@ -163,13 +183,6 @@ class AudioPlayer(
163
183
  }
164
184
 
165
185
  private fun createVisualizer() {
166
- appContext?.reactContext?.let {
167
- if (ContextCompat.checkSelfPermission(it, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
168
- Log.d(TAG, "\'android.permission.RECORD_AUDIO\' is required to use audio sampling. Please request this permission and try again.")
169
- return
170
- }
171
- }
172
-
173
186
  // It must only be created once, otherwise the app will crash
174
187
  if (visualizer == null) {
175
188
  visualizer = Visualizer(player.audioSessionId).apply {
@@ -12,7 +12,6 @@ import android.media.MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED
12
12
  import android.net.Uri
13
13
  import android.os.Build
14
14
  import android.os.Bundle
15
- import android.os.SystemClock
16
15
  import androidx.core.content.ContextCompat
17
16
  import expo.modules.kotlin.AppContext
18
17
  import expo.modules.kotlin.sharedobjects.SharedObject
@@ -30,24 +29,23 @@ class AudioRecorder(
30
29
  ) : SharedObject(appContext),
31
30
  MediaRecorder.OnErrorListener,
32
31
  MediaRecorder.OnInfoListener {
33
- private var filePath: String? = null
32
+ var filePath: String? = null
34
33
  private var meteringEnabled = options.isMeteringEnabled
35
34
  private var durationAlreadyRecorded = 0L
36
- private var isPrepared = false
37
- private var shouldCreateRecorder = false
35
+ var isPrepared = false
38
36
 
39
- private var recorder = createRecorder(options)
37
+ private var recorder: MediaRecorder? = null
40
38
  val id = UUID.randomUUID().toString()
41
- var uri: String? = null
42
- var uptime = 0L
39
+ var startTime = 0L
43
40
  var isRecording = false
44
41
  var isPaused = false
45
42
 
46
- private fun getAudioRecorderLevels(): Int {
47
- if (!meteringEnabled) {
48
- return -160
43
+ private fun getAudioRecorderLevels(): Int? {
44
+ if (!meteringEnabled || recorder == null || !isRecording) {
45
+ return null
49
46
  }
50
- val amplitude: Int = recorder.maxAmplitude
47
+
48
+ val amplitude: Int = recorder?.maxAmplitude ?: 0
51
49
  return if (amplitude == 0) {
52
50
  -160
53
51
  } else {
@@ -56,46 +54,51 @@ class AudioRecorder(
56
54
  }
57
55
 
58
56
  fun prepareRecording(options: RecordingOptions?) {
59
- if (options != null && !shouldCreateRecorder) {
60
- // New options have been passed in so we rebuild the recorder
61
- shouldCreateRecorder = this.options != options
62
- }
63
- if (shouldCreateRecorder) {
64
- recorder = options?.let { createRecorder(it) } ?: createRecorder(this.options)
57
+ recorder = options?.let { createRecorder(it) } ?: createRecorder(this.options)
58
+ try {
59
+ recorder?.prepare()
60
+ isPrepared = true
61
+ } catch (_: Exception) {
62
+ recorder?.release()
63
+ recorder = null
64
+ isPrepared = false
65
65
  }
66
- recorder.prepare()
67
- isPrepared = true
68
66
  }
69
67
 
70
68
  fun record() {
71
69
  if (isPaused) {
72
- recorder.resume()
70
+ recorder?.resume()
73
71
  } else {
74
- recorder.start()
72
+ recorder?.start()
75
73
  }
74
+ startTime = System.currentTimeMillis()
76
75
  isRecording = true
77
76
  isPaused = false
78
- uptime = SystemClock.uptimeMillis()
79
77
  }
80
78
 
81
79
  fun pauseRecording() {
82
- recorder.pause()
80
+ recorder?.pause()
83
81
  durationAlreadyRecorded = getAudioRecorderDurationMillis()
84
82
  isRecording = false
85
83
  isPaused = true
86
84
  }
87
85
 
88
86
  fun stopRecording(): Bundle {
89
- recorder.stop()
90
- reset()
87
+ try {
88
+ recorder?.stop()
89
+ } finally {
90
+ reset()
91
+ }
91
92
  return getAudioRecorderStatus()
92
93
  }
93
94
 
94
95
  private fun reset() {
96
+ recorder?.release()
97
+ recorder = null
95
98
  isRecording = false
96
99
  isPaused = false
97
100
  durationAlreadyRecorded = 0
98
- shouldCreateRecorder = true
101
+ startTime = 0L
99
102
  isPrepared = false
100
103
  }
101
104
 
@@ -149,14 +152,13 @@ class AudioRecorder(
149
152
  setOnErrorListener(this@AudioRecorder)
150
153
  setOnInfoListener(this@AudioRecorder)
151
154
  setOutputFile(filePath)
152
- uri = filePath
153
155
  isPrepared = false
154
156
  }
155
157
  }
156
158
 
157
159
  override fun sharedObjectDidRelease() {
158
160
  super.sharedObjectDidRelease()
159
- recorder.release()
161
+ reset()
160
162
  }
161
163
 
162
164
  fun getAudioRecorderStatus() = if (hasRecordingPermissions()) {
@@ -164,10 +166,10 @@ class AudioRecorder(
164
166
  putBoolean("canRecord", isPrepared)
165
167
  putBoolean("isRecording", isRecording)
166
168
  putLong("durationMillis", getAudioRecorderDurationMillis())
167
- if (meteringEnabled) {
168
- putInt("metering", getAudioRecorderLevels())
169
+ getAudioRecorderLevels()?.let {
170
+ putInt("metering", it)
169
171
  }
170
- putString("url", uri)
172
+ putString("url", filePath)
171
173
  }
172
174
  } else {
173
175
  Bundle().apply {
@@ -180,8 +182,8 @@ class AudioRecorder(
180
182
 
181
183
  private fun getAudioRecorderDurationMillis(): Long {
182
184
  var duration = durationAlreadyRecorded
183
- if (isRecording && uptime > 0) {
184
- duration += SystemClock.uptimeMillis() - uptime
185
+ if (isRecording) {
186
+ duration += System.currentTimeMillis() - startTime
185
187
  }
186
188
  return duration
187
189
  }
@@ -206,14 +208,14 @@ class AudioRecorder(
206
208
  override fun onInfo(mr: MediaRecorder?, what: Int, extra: Int) {
207
209
  when (what) {
208
210
  MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED -> {
209
- recorder.stop()
211
+ recorder?.stop()
210
212
  emit(
211
- "onRecordingStatusUpdate",
213
+ RECORDING_STATUS_UPDATE,
212
214
  mapOf(
213
215
  "isFinished" to true,
214
216
  "hasError" to true,
215
217
  "error" to null,
216
- "url" to Uri.fromFile(filePath?.let { File(it) }).toString()
218
+ "url" to Uri.parse(filePath).toString()
217
219
  )
218
220
  )
219
221
  }
@@ -231,14 +233,14 @@ class AudioRecorder(
231
233
  // getRoutedDevice() is the most reliable way to return the actual mic input, however it
232
234
  // only returns a valid device when actively recording, and may throw otherwise.
233
235
  // https://developer.android.com/reference/android/media/MediaRecorder#getRoutedDevice()
234
- deviceInfo = recorder.routedDevice
236
+ deviceInfo = recorder?.routedDevice
235
237
  } catch (e: java.lang.Exception) {
236
238
  // no-op
237
239
  }
238
240
 
239
241
  // If no routed device is found try preferred device
240
242
  if (deviceInfo == null) {
241
- deviceInfo = recorder.preferredDevice
243
+ deviceInfo = recorder?.preferredDevice
242
244
  }
243
245
 
244
246
  if (deviceInfo == null) {
@@ -248,7 +250,7 @@ class AudioRecorder(
248
250
  val type = availableDeviceInfo.type
249
251
  if (type == AudioDeviceInfo.TYPE_BUILTIN_MIC) {
250
252
  deviceInfo = availableDeviceInfo
251
- recorder.setPreferredDevice(deviceInfo)
253
+ recorder?.setPreferredDevice(deviceInfo)
252
254
  break
253
255
  }
254
256
  }
@@ -295,8 +297,8 @@ class AudioRecorder(
295
297
  }
296
298
  }
297
299
 
298
- val success = recorder.setPreferredDevice(deviceInfo)
299
- if (!success) {
300
+ val success = recorder?.setPreferredDevice(deviceInfo)
301
+ if (success == false) {
300
302
  throw PreferredInputNotFoundException()
301
303
  }
302
304
  }
@@ -305,8 +307,7 @@ class AudioRecorder(
305
307
  val id = uid.toInt()
306
308
  val audioDevices: Array<AudioDeviceInfo> = audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)
307
309
  for (device in audioDevices) {
308
- val deviceId = device.id
309
- if (deviceId == id) {
310
+ if (device.id == id) {
310
311
  return device
311
312
  }
312
313
  }
@@ -12,7 +12,7 @@ class AudioSource(
12
12
  ) : Record
13
13
 
14
14
  class AudioMode(
15
- @Field val shouldPlayInBackground: Boolean = true,
15
+ @Field val shouldPlayInBackground: Boolean = false,
16
16
  @Field val shouldRouteThroughEarpiece: Boolean?
17
17
  ) : Record
18
18
 
@@ -221,6 +221,11 @@ export type RecordingOptionsAndroid = {
221
221
  maxFileSize?: number;
222
222
  };
223
223
  export type AudioMode = {
224
+ /**
225
+ * Determines if audio playback is allowed when the device is in silent mode.
226
+ *
227
+ * @platform ios
228
+ */
224
229
  playsInSilentMode: boolean;
225
230
  /**
226
231
  * Determines how the audio session interacts with other sessions.
@@ -228,8 +233,22 @@ export type AudioMode = {
228
233
  * @platform ios
229
234
  */
230
235
  interruptionMode: InterruptionMode;
236
+ /**
237
+ * Whether the audio session allows recording.
238
+ *
239
+ * @default false
240
+ * @platform ios
241
+ */
231
242
  allowsRecording: boolean;
243
+ /**
244
+ * Whether the audio session stays active when the app moves to the background.
245
+ * @default false
246
+ */
232
247
  shouldPlayInBackground: boolean;
248
+ /**
249
+ * Whether the audio should route through the earpiece.
250
+ * @platform android
251
+ */
233
252
  shouldRouteThroughEarpiece: boolean;
234
253
  };
235
254
  export type InterruptionMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers';
@@ -1 +1 @@
1
- {"version":3,"file":"Audio.types.d.ts","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Audio.types.d.ts","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Audio.types.js","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"AA4EA,MAAM,CAAN,IAAY,eAmCX;AAnCD,WAAY,eAAe;IACzB,qCAAkB,CAAA;IAClB,+BAAY,CAAA;IACZ,oCAAmB,CAAA;IACnB,qCAAkB,CAAA;IAClB,oCAAiB,CAAA;IACjB,qCAAkB,CAAA;IAClB,qCAAkB,CAAA;IAClB,uCAAoB,CAAA;IACpB,iCAAc,CAAA;IACd,iCAAc,CAAA;IACd,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,mCAAgB,CAAA;IAChB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,yCAAsB,CAAA;IACtB,uCAAoB,CAAA;IACpB,uCAAoB,CAAA;IACpB,wCAAqB,CAAA;IACrB,4CAAyB,CAAA;IACzB,2CAAwB,CAAA;IACxB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,+BAAY,CAAA;IACZ,kCAAe,CAAA;IACf,mCAAgB,CAAA;IAChB,gCAAa,CAAA;IACb,4EAAwB,CAAA;IACxB,8EAAyB,CAAA;IACzB,gCAAa,CAAA;IACb,uCAAoB,CAAA;AACtB,CAAC,EAnCW,eAAe,KAAf,eAAe,QAmC1B;AAED,MAAM,CAAN,IAAY,YAMX;AAND,WAAY,YAAY;IACtB,6CAAO,CAAA;IACP,8CAAU,CAAA;IACV,oDAAa,CAAA;IACb,gDAAW,CAAA;IACX,+CAAU,CAAA;AACZ,CAAC,EANW,YAAY,KAAZ,YAAY,QAMvB","sourcesContent":["export type AudioSource =\n | string\n | number\n | null\n | {\n /**\n * A string representing the resource identifier for the audio,\n * which could be an HTTPS address, a local file path, or the name of a static audio file resource.\n */\n uri?: string;\n /**\n * The asset ID of a local audio asset, acquired with the `require` function.\n * This property is exclusive with the `uri` property. When both are present, the `assetId` will be ignored.\n */\n assetId?: number;\n /**\n * An object representing the HTTP headers to send along with the request for a remote audio source.\n * On web requires the `Access-Control-Allow-Origin` header returned by the server to include the current domain.\n */\n headers?: Record<string, string>;\n };\n\nexport type RecordingInput = {\n name: string;\n type: string;\n uid: string;\n};\n\nexport type PitchCorrectionQuality = 'low' | 'medium' | 'high';\n\nexport type AudioStatus = {\n id: number;\n currentTime: number;\n playbackState: string;\n timeControlStatus: string;\n reasonForWaitingToPlay: string;\n mute: boolean;\n duration: number;\n playing: boolean;\n loop: boolean;\n didJustFinish: boolean;\n isBuffering: boolean;\n isLoaded: boolean;\n playbackRate: number;\n shouldCorrectPitch: boolean;\n};\n\nexport type RecordingStatus = {\n id: number;\n isFinished: boolean;\n hasError: boolean;\n error: string | null;\n url: string | null;\n};\n\nexport type RecorderState = {\n canRecord: boolean;\n isRecording: boolean;\n durationMillis: number;\n mediaServicesDidReset: boolean;\n metering?: number;\n url: string | null;\n};\n\nexport type AndroidOutputFormat =\n | 'default'\n | '3gp'\n | 'mpeg4'\n | 'amrnb'\n | 'amrwb'\n | 'aac_adts'\n | 'mpeg2ts'\n | 'webm';\n\nexport type AndroidAudioEncoder = 'default' | 'amr_nb' | 'amr_wb' | 'aac' | 'he_aac' | 'aac_eld';\n\nexport enum IOSOutputFormat {\n LINEARPCM = 'lpcm',\n AC3 = 'ac-3',\n '60958AC3' = 'cac3',\n APPLEIMA4 = 'ima4',\n MPEG4AAC = 'aac ',\n MPEG4CELP = 'celp',\n MPEG4HVXC = 'hvxc',\n MPEG4TWINVQ = 'twvq',\n MACE3 = 'MAC3',\n MACE6 = 'MAC6',\n ULAW = 'ulaw',\n ALAW = 'alaw',\n QDESIGN = 'QDMC',\n QDESIGN2 = 'QDM2',\n QUALCOMM = 'Qclp',\n MPEGLAYER1 = '.mp1',\n MPEGLAYER2 = '.mp2',\n MPEGLAYER3 = '.mp3',\n APPLELOSSLESS = 'alac',\n MPEG4AAC_HE = 'aach',\n MPEG4AAC_LD = 'aacl',\n MPEG4AAC_ELD = 'aace',\n MPEG4AAC_ELD_SBR = 'aacf',\n MPEG4AAC_ELD_V2 = 'aacg',\n MPEG4AAC_HE_V2 = 'aacp',\n MPEG4AAC_SPATIAL = 'aacs',\n AMR = 'samr',\n AMR_WB = 'sawb',\n AUDIBLE = 'AUDB',\n ILBC = 'ilbc',\n DVIINTELIMA = 0x6d730011,\n MICROSOFTGSM = 0x6d730031,\n AES3 = 'aes3',\n ENHANCEDAC3 = 'ec-3',\n}\n\nexport enum AudioQuality {\n MIN = 0,\n LOW = 0x20,\n MEDIUM = 0x40,\n HIGH = 0x60,\n MAX = 0x7f,\n}\n\nexport type BitRateStrategy = 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable';\n\nexport type RecordingOptions = {\n /**\n * A boolean that determines whether audio level information will be part of the status object under the \"metering\" key.\n */\n isMeteringEnabled?: boolean;\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate: number;\n /**\n * The desired number of channels.\n *\n * @example 2\n */\n numberOfChannels: number;\n /**\n * The desired bit rate.\n *\n * @example 128000\n */\n bitRate: number;\n /**\n * Recording options for the Android platform.\n */\n android: RecordingOptionsAndroid;\n /**\n * Recording options for the iOS platform.\n */\n ios: RecordingOptionsIos;\n /**\n * Recording options for the Web platform.\n */\n web?: RecordingOptionsWeb;\n};\n\nexport type RecordingOptionsWeb = {\n mimeType?: string;\n bitsPerSecond?: number;\n};\n\nexport type RecordingOptionsIos = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`IOSOutputFormat`](#iosoutputformat) enum for all valid values.\n */\n outputFormat?: string | IOSOutputFormat | number;\n /**\n * The desired audio quality. See the [`AudioQuality`](#audioquality) enum for all valid values.\n */\n audioQuality: AudioQuality | number;\n /**\n * The desired bit rate strategy. See the next section for an enumeration of all valid values of `bitRateStrategy`.\n */\n bitRateStrategy?: number;\n /**\n * The desired bit depth hint.\n *\n * @example 16\n */\n bitDepthHint?: number;\n /**\n * The desired PCM bit depth.\n *\n * @example 16\n */\n linearPCMBitDepth?: number;\n /**\n * A boolean describing if the PCM data should be formatted in big endian.\n */\n linearPCMIsBigEndian?: boolean;\n /**\n * A boolean describing if the PCM data should be encoded in floating point or integral values.\n */\n linearPCMIsFloat?: boolean;\n};\n\nexport type RecordingOptionsAndroid = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`AndroidOutputFormat`](#androidoutputformat) enum for all valid values.\n */\n outputFormat: AndroidOutputFormat;\n /**\n * The desired audio encoder. See the [`AndroidAudioEncoder`](#androidaudioencoder) enum for all valid values.\n */\n audioEncoder: AndroidAudioEncoder;\n /**\n * The desired maximum file size in bytes, after which the recording will stop (but `stopAndUnloadAsync()` must still\n * be called after this point).\n *\n * @example\n * `65536`\n */\n maxFileSize?: number;\n};\n\nexport type AudioMode = {\n playsInSilentMode: boolean;\n /**\n * Determines how the audio session interacts with other sessions.\n *\n * @platform ios\n */\n interruptionMode: InterruptionMode;\n allowsRecording: boolean;\n shouldPlayInBackground: boolean;\n shouldRouteThroughEarpiece: boolean;\n};\n\nexport type InterruptionMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers';\n"]}
1
+ {"version":3,"file":"Audio.types.js","sourceRoot":"","sources":["../src/Audio.types.ts"],"names":[],"mappings":"AA4EA,MAAM,CAAN,IAAY,eAmCX;AAnCD,WAAY,eAAe;IACzB,qCAAkB,CAAA;IAClB,+BAAY,CAAA;IACZ,oCAAmB,CAAA;IACnB,qCAAkB,CAAA;IAClB,oCAAiB,CAAA;IACjB,qCAAkB,CAAA;IAClB,qCAAkB,CAAA;IAClB,uCAAoB,CAAA;IACpB,iCAAc,CAAA;IACd,iCAAc,CAAA;IACd,gCAAa,CAAA;IACb,gCAAa,CAAA;IACb,mCAAgB,CAAA;IAChB,oCAAiB,CAAA;IACjB,oCAAiB,CAAA;IACjB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,sCAAmB,CAAA;IACnB,yCAAsB,CAAA;IACtB,uCAAoB,CAAA;IACpB,uCAAoB,CAAA;IACpB,wCAAqB,CAAA;IACrB,4CAAyB,CAAA;IACzB,2CAAwB,CAAA;IACxB,0CAAuB,CAAA;IACvB,4CAAyB,CAAA;IACzB,+BAAY,CAAA;IACZ,kCAAe,CAAA;IACf,mCAAgB,CAAA;IAChB,gCAAa,CAAA;IACb,4EAAwB,CAAA;IACxB,8EAAyB,CAAA;IACzB,gCAAa,CAAA;IACb,uCAAoB,CAAA;AACtB,CAAC,EAnCW,eAAe,KAAf,eAAe,QAmC1B;AAED,MAAM,CAAN,IAAY,YAMX;AAND,WAAY,YAAY;IACtB,6CAAO,CAAA;IACP,8CAAU,CAAA;IACV,oDAAa,CAAA;IACb,gDAAW,CAAA;IACX,+CAAU,CAAA;AACZ,CAAC,EANW,YAAY,KAAZ,YAAY,QAMvB","sourcesContent":["export type AudioSource =\n | string\n | number\n | null\n | {\n /**\n * A string representing the resource identifier for the audio,\n * which could be an HTTPS address, a local file path, or the name of a static audio file resource.\n */\n uri?: string;\n /**\n * The asset ID of a local audio asset, acquired with the `require` function.\n * This property is exclusive with the `uri` property. When both are present, the `assetId` will be ignored.\n */\n assetId?: number;\n /**\n * An object representing the HTTP headers to send along with the request for a remote audio source.\n * On web requires the `Access-Control-Allow-Origin` header returned by the server to include the current domain.\n */\n headers?: Record<string, string>;\n };\n\nexport type RecordingInput = {\n name: string;\n type: string;\n uid: string;\n};\n\nexport type PitchCorrectionQuality = 'low' | 'medium' | 'high';\n\nexport type AudioStatus = {\n id: number;\n currentTime: number;\n playbackState: string;\n timeControlStatus: string;\n reasonForWaitingToPlay: string;\n mute: boolean;\n duration: number;\n playing: boolean;\n loop: boolean;\n didJustFinish: boolean;\n isBuffering: boolean;\n isLoaded: boolean;\n playbackRate: number;\n shouldCorrectPitch: boolean;\n};\n\nexport type RecordingStatus = {\n id: number;\n isFinished: boolean;\n hasError: boolean;\n error: string | null;\n url: string | null;\n};\n\nexport type RecorderState = {\n canRecord: boolean;\n isRecording: boolean;\n durationMillis: number;\n mediaServicesDidReset: boolean;\n metering?: number;\n url: string | null;\n};\n\nexport type AndroidOutputFormat =\n | 'default'\n | '3gp'\n | 'mpeg4'\n | 'amrnb'\n | 'amrwb'\n | 'aac_adts'\n | 'mpeg2ts'\n | 'webm';\n\nexport type AndroidAudioEncoder = 'default' | 'amr_nb' | 'amr_wb' | 'aac' | 'he_aac' | 'aac_eld';\n\nexport enum IOSOutputFormat {\n LINEARPCM = 'lpcm',\n AC3 = 'ac-3',\n '60958AC3' = 'cac3',\n APPLEIMA4 = 'ima4',\n MPEG4AAC = 'aac ',\n MPEG4CELP = 'celp',\n MPEG4HVXC = 'hvxc',\n MPEG4TWINVQ = 'twvq',\n MACE3 = 'MAC3',\n MACE6 = 'MAC6',\n ULAW = 'ulaw',\n ALAW = 'alaw',\n QDESIGN = 'QDMC',\n QDESIGN2 = 'QDM2',\n QUALCOMM = 'Qclp',\n MPEGLAYER1 = '.mp1',\n MPEGLAYER2 = '.mp2',\n MPEGLAYER3 = '.mp3',\n APPLELOSSLESS = 'alac',\n MPEG4AAC_HE = 'aach',\n MPEG4AAC_LD = 'aacl',\n MPEG4AAC_ELD = 'aace',\n MPEG4AAC_ELD_SBR = 'aacf',\n MPEG4AAC_ELD_V2 = 'aacg',\n MPEG4AAC_HE_V2 = 'aacp',\n MPEG4AAC_SPATIAL = 'aacs',\n AMR = 'samr',\n AMR_WB = 'sawb',\n AUDIBLE = 'AUDB',\n ILBC = 'ilbc',\n DVIINTELIMA = 0x6d730011,\n MICROSOFTGSM = 0x6d730031,\n AES3 = 'aes3',\n ENHANCEDAC3 = 'ec-3',\n}\n\nexport enum AudioQuality {\n MIN = 0,\n LOW = 0x20,\n MEDIUM = 0x40,\n HIGH = 0x60,\n MAX = 0x7f,\n}\n\nexport type BitRateStrategy = 'constant' | 'longTermAverage' | 'variableConstrained' | 'variable';\n\nexport type RecordingOptions = {\n /**\n * A boolean that determines whether audio level information will be part of the status object under the \"metering\" key.\n */\n isMeteringEnabled?: boolean;\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate: number;\n /**\n * The desired number of channels.\n *\n * @example 2\n */\n numberOfChannels: number;\n /**\n * The desired bit rate.\n *\n * @example 128000\n */\n bitRate: number;\n /**\n * Recording options for the Android platform.\n */\n android: RecordingOptionsAndroid;\n /**\n * Recording options for the iOS platform.\n */\n ios: RecordingOptionsIos;\n /**\n * Recording options for the Web platform.\n */\n web?: RecordingOptionsWeb;\n};\n\nexport type RecordingOptionsWeb = {\n mimeType?: string;\n bitsPerSecond?: number;\n};\n\nexport type RecordingOptionsIos = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`IOSOutputFormat`](#iosoutputformat) enum for all valid values.\n */\n outputFormat?: string | IOSOutputFormat | number;\n /**\n * The desired audio quality. See the [`AudioQuality`](#audioquality) enum for all valid values.\n */\n audioQuality: AudioQuality | number;\n /**\n * The desired bit rate strategy. See the next section for an enumeration of all valid values of `bitRateStrategy`.\n */\n bitRateStrategy?: number;\n /**\n * The desired bit depth hint.\n *\n * @example 16\n */\n bitDepthHint?: number;\n /**\n * The desired PCM bit depth.\n *\n * @example 16\n */\n linearPCMBitDepth?: number;\n /**\n * A boolean describing if the PCM data should be formatted in big endian.\n */\n linearPCMIsBigEndian?: boolean;\n /**\n * A boolean describing if the PCM data should be encoded in floating point or integral values.\n */\n linearPCMIsFloat?: boolean;\n};\n\nexport type RecordingOptionsAndroid = {\n /**\n * The desired file extension.\n *\n * @example .caf\n */\n extension?: string;\n /**\n * The desired sample rate.\n *\n * @example 44100\n */\n sampleRate?: number;\n /**\n * The desired file format. See the [`AndroidOutputFormat`](#androidoutputformat) enum for all valid values.\n */\n outputFormat: AndroidOutputFormat;\n /**\n * The desired audio encoder. See the [`AndroidAudioEncoder`](#androidaudioencoder) enum for all valid values.\n */\n audioEncoder: AndroidAudioEncoder;\n /**\n * The desired maximum file size in bytes, after which the recording will stop (but `stopAndUnloadAsync()` must still\n * be called after this point).\n *\n * @example\n * `65536`\n */\n maxFileSize?: number;\n};\n\nexport type AudioMode = {\n /**\n * Determines if audio playback is allowed when the device is in silent mode.\n *\n * @platform ios\n */\n playsInSilentMode: boolean;\n /**\n * Determines how the audio session interacts with other sessions.\n *\n * @platform ios\n */\n interruptionMode: InterruptionMode;\n /**\n * Whether the audio session allows recording.\n *\n * @default false\n * @platform ios\n */\n allowsRecording: boolean;\n /**\n * Whether the audio session stays active when the app moves to the background.\n * @default false\n */\n shouldPlayInBackground: boolean;\n /**\n * Whether the audio should route through the earpiece.\n * @platform android\n */\n shouldRouteThroughEarpiece: boolean;\n};\n\nexport type InterruptionMode = 'mixWithOthers' | 'doNotMix' | 'duckOthers';\n"]}
@@ -3,8 +3,8 @@ import ExpoModulesCore
3
3
  struct AudioMode: Record {
4
4
  @Field var playsInSilentMode: Bool = false
5
5
  @Field var interruptionMode: InterruptionMode = .mixWithOthers
6
- @Field var allowsRecording: Bool = true
7
- @Field var shouldPlayInBackground: Bool = true
6
+ @Field var allowsRecording: Bool = false
7
+ @Field var shouldPlayInBackground: Bool = false
8
8
  }
9
9
 
10
10
  enum InterruptionMode: String, Enumerable {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-audio",
3
3
  "title": "Expo Audio",
4
- "version": "0.3.4",
4
+ "version": "0.3.5",
5
5
  "description": "A cross-platform audio library for React Native and Expo apps.",
6
6
  "main": "build/index.js",
7
7
  "types": "build/index.d.ts",
@@ -33,12 +33,12 @@
33
33
  "license": "MIT",
34
34
  "dependencies": {},
35
35
  "devDependencies": {
36
- "expo-module-scripts": "^4.0.3"
36
+ "expo-module-scripts": "^4.0.4"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "expo": "*",
40
40
  "react": "*",
41
41
  "react-native": "*"
42
42
  },
43
- "gitHead": "0a0c6d35a691fc59c0d94675d159ac9e3dfd6f26"
43
+ "gitHead": "c01c449a1d6e6e8690bfcc88a778b46781a59674"
44
44
  }
@@ -248,6 +248,11 @@ export type RecordingOptionsAndroid = {
248
248
  };
249
249
 
250
250
  export type AudioMode = {
251
+ /**
252
+ * Determines if audio playback is allowed when the device is in silent mode.
253
+ *
254
+ * @platform ios
255
+ */
251
256
  playsInSilentMode: boolean;
252
257
  /**
253
258
  * Determines how the audio session interacts with other sessions.
@@ -255,8 +260,22 @@ export type AudioMode = {
255
260
  * @platform ios
256
261
  */
257
262
  interruptionMode: InterruptionMode;
263
+ /**
264
+ * Whether the audio session allows recording.
265
+ *
266
+ * @default false
267
+ * @platform ios
268
+ */
258
269
  allowsRecording: boolean;
270
+ /**
271
+ * Whether the audio session stays active when the app moves to the background.
272
+ * @default false
273
+ */
259
274
  shouldPlayInBackground: boolean;
275
+ /**
276
+ * Whether the audio should route through the earpiece.
277
+ * @platform android
278
+ */
260
279
  shouldRouteThroughEarpiece: boolean;
261
280
  };
262
281