Expo AV issue on iOS

Please provide the following:

  1. SDK Version: “expo”: “~48.0.15”, “expo-av”: “~13.2.1”,
  2. Platforms(Android/iOS/web/all): iOS

Hi! I just cannot make my audioplayer work (playAsync). I know it’s an iOS specific issue because the sound works properly in web and Android. I’ll leave my code below. I tried adding “NSAppTransportSecurity”: {“NSAllowsArbitraryLoads”: true, “NSAllowsArbitraryLoadsInWebContent”: true}, permissions as well, but it didn’t help+ I don’t think permissions are necessary because I’m just playing sound?

import React, { useEffect, useState } from ‘react’;
import { StyleSheet, View, Text, TouchableOpacity } from ‘react-native’;
import { Audio, InterruptionModeAndroid, InterruptionModeIOS } from ‘expo-av’;
import Slider from ‘@react-native-community/slider’;

interface AudioPlayerProps {
audioURI: string;
}

export const AudioPlayer: React.FC = ({ audioURI }) => {
const [sound, setSound] = useState<Audio.Sound | null>(null);
const [isPlaying, setIsPlaying] = useState(false);
const [duration, setDuration] = useState<number | null>(null);
const [position, setPosition] = useState<number | null>(null);
const [playbackRate, setPlaybackRate] = useState(1);
const rates = [0.5, 1, 1.5, 1.75, 2];

useEffect(() => {
const setupAudioMode = async () => {
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,
interruptionModeIOS: InterruptionModeIOS.DoNotMix,
playsInSilentModeIOS: true,
shouldDuckAndroid: true,
interruptionModeAndroid: InterruptionModeAndroid.DoNotMix,
playThroughEarpieceAndroid: false,
staysActiveInBackground: false,
});
};

setupAudioMode();

}, );

async function loadAudio() {
try {
console.log(‘loading audio’);
const { sound } = await Audio.Sound.createAsync(
require(‘…/…/assets/testable_audio.wav’),
{ shouldPlay: true},
updateScreenForSoundStatus,
);

} catch (e) {
    console.log(e);
}
setSound(sound);

}

const updateScreenForSoundStatus = (status: any) => {
if (status.isLoaded) {
setDuration(status.durationMillis);
setPosition(status.positionMillis);
setIsPlaying(status.isPlaying);
} else {
if (status.error) {
console.log(FATAL PLAYER ERROR: ${status.error});
}
}
};

useEffect(() => {
loadAudio();

return sound ? () => sound.unloadAsync() : undefined;

}, );

async function handlePlayPause() {
isPlaying ? await sound?.pauseAsync() : await sound?.playAsync();
}

async function handleSliderValueChange(value: number) {
if (sound) {
await sound.setPositionAsync(value);
}
}

async function handlePlaybackSpeed() {
let nextIndex = rates.indexOf(playbackRate) + 1;
if (nextIndex === rates.length) nextIndex = 0;
const nextRate = rates[nextIndex];
setPlaybackRate(nextRate);
if (sound) {
await sound.setRateAsync(nextRate, true);
}
}

return (



{isPlaying ? ‘Pause’ : ‘Play’}

<Slider
style={{ flex: 1, height: 40 }}
minimumValue={0}
maximumValue={duration ? duration : 0}
value={position ? position : 0}
onValueChange={handleSliderValueChange}
/>

{playbackRate}x



);
};

Here’s an example of how I’m calling the component:

What am I missing? I read that { shouldPlay: true} is a must, but it still doesn’t work with it.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.