0
votes

I want to play an audio that is being played through a url using react-native-sound, at the same time I want to record a video so that I can capture the audio being played through the speakers of the phone in the video. I'm able to achieve this in android, but iOS is giving me a hard time.

I've already asked this on the official react-native-camera github repo, but no response yet.

To Do First

  • [ YES ] Did you try latest release?
  • [ YES ] Did you try master?
  • [ YES ] Did you look for existing matching issues?

Platforms

No issue faced in Android

It happens only in iOS.

Versions

  • Android: Used different versions of android, no issues faced
  • iOS:
  • react-native-camera: 3.44.3
  • react-native: 0.64.2
  • react: 17.0.1

Description/Current Behaviour

This happens with iOS only, it's working fine in Android. I want to play an audio while recording a video so that the audio playing on the phone's speaker can be captured through the microphone that is being used by the camera. I play the audio and as soon as I call the recordAsync() function, the audio stops and the recording starts, at first I though that it's impossible to do this in iOS due to different permission policies in iOS as compared to Android, but I was provided with an native iOS version of the app by the client that is doing the same thing, so permissions is not an issue.

Expected Behavior Expected to allow the audio to keep playing while I record the video

Steps to Reproduce

Try playing any audio from a file or a URL using react-native-sound and call recordAsync() from react-native-camera,

Additionals

I'm using react-native-sound for playing the audio, as the audio is played through a URL, This is my RNCamera Component with props:

    <RNCamera
          style={styles.preview}
          type={RNCamera.Constants.Type.back}
          flashMode={RNCamera.Constants.FlashMode.on}
          captureAudio={true}
          androidCameraPermissionOptions={{
            title: 'Permission to use camera',
            message: 'We need your permission to use your camera',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}
          androidRecordAudioPermissionOptions={{
            title: 'Permission to use audio recording',
            message: 'We need your permission to use your audio',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}>
          {({camera, status, recordAudioPermissionStatus}) => {
            if (showFilenameModal) {
             // show a modal to save the video file with a user entered name
            }
            if (status !== 'READY')
              return (
                <View
                  style={{
                    flex: 1,
                    width: globalStyles.WIDTH,
                    backgroundColor: 'black',
                    justifyContent: 'center',
                    alignItems: 'center',
                  }}>
                  <Text>Waiting</Text>
                </View>
              );
            return recording || processing ? (
              <IconButton
                title={'Stop'}
                icon={'stop'}
                disabled={processing}
                onPress={() => {
                  console.log('Stop Recording');
                  camera.stopRecording();
                }}
              />
            ) : (
              <View
                style={{
                  display: 'flex',
                  flexDirection: 'row',
                  justifyContent: 'space-around',
                  marginBottom: 10,
                }}>
                  {/* Button to record video without playing the audio */}
                <IconButton
                  title={'Record'}
                  icon="record"
                  onPress={() => this.startRecording(camera, false)}
                />
                  {/* Button to record video while playing the audio */}
                <IconButton
                  title={'Record with Audio'}
                  icon="record"
                  showSound={true}
                  onPress={() => this.startRecording(camera)}
                /> 
              </View>
            );
          }}
        </RNCamera>

This is how I start the recording:

startRecording = async function (camera, withAudio = true) {
    const {audioPlayer, setVideoStatus} = this.props;
    audioPlayer.stopAudio();
    setVideoStatus({
      recording: true,
      processing: false,
      uri: null,
    });

    if (withAudio) audioPlayer.playAudio();

    const video = await camera.recordAsync({
      quality: RNCamera.Constants.VideoQuality['720p'],
      // I've tried this with different flag combination i.e:
      // captureAudio: true / false,
      // keepAudioSession: true / false,
    });

    console.log(video.uri.substr(7, video.uri.length), video.codec);

    audioPlayer.stopAudio();
    setVideoStatus({
      recording: false,
      processing: true,
    });

    this.setState({
      showFilenameModal: true,
      uri: video.uri,
    });
  };

This is my info.plist

  <key>NSCameraUsageDescription</key>
  <string>Allow app to open camera to record video</string>
  <key>NSPhotoLibraryAddUsageDescription</key>
  <string>Allow app to save videos to library</string>
  <key>NSAppleMusicUsageDescription</key>
  <string>Allow app to use media library for audio</string>
  <key>NSLocationAlwaysUsageDescription</key>
  <string>Allow app to use location for getting current state</string>
  <key>NSLocationWhenInUseUsageDescription</key>
  <string>Allow app to use location for getting current state</string>
  <key>NSMicrophoneUsageDescription</key>
  <string>Allow app to use microphone to record video with audio</string>

Just in case these are the permissions in my AndoroidManifest.xml:

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

The other app that I'm talking about, is not based on react native, I think it's native iOS.

1

1 Answers

0
votes

Thanks to the react-native-camera community, I was able to solve this issue:

https://github.com/react-native-camera/react-native-camera/issues/3276