4
votes

I am making a chat room application, so far it is able to send message, image and video.

I am using a very similar method to send video and it works, but it's not working when sending audio.

The audio file and audio url is upload to Firebase successfully, But when I tried to play back the audio, it show this error: The operation couldn’t be completed. (OSStatus error 2003334207.).

The project is getting quite overwhelmingly large, and I have very little experience using AVAudio, so if you guys had similar problems before please teach me how to fix it. Thanks!!!

Here is the code of setting up the audioRecorder, and I get the url here and pass it to other func to put the audio file to Firebase storage.

func startRecording() {
    let settings = [
        AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey: 12000,
        AVNumberOfChannelsKey: 1,
        AVEncoderAudioQualityKey: AVAudioQuality.low.rawValue
    ]

    do {
        let audioFileUrl = getAudiFileURL()
        audioRecorder = try AVAudioRecorder(url: audioFileUrl, settings: settings)
        audioRecorder.delegate = self
        audioRecorder.record()
        blackView.isHidden = false
    } catch {
        finishRecording(success: false)
    }
}

Here is where I try to upload the audio file to Firebase storage, and it does print out the correct downloadURL.

func handleAudioSendWith(url: String) {
    guard let fileUrl = URL(string: url) else {
        return
    }
    let fileName = NSUUID().uuidString + ".m4a"

    FIRStorage.storage().reference().child("message_voice").child(fileName).putFile(fileUrl, metadata: nil) { (metadata, error) in
        if error != nil {
            print(error ?? "error")
        }

        if let downloadUrl = metadata?.downloadURL()?.absoluteString {
            print(downloadUrl)
            let values: [String : Any] = ["audioUrl": downloadUrl]
            self.sendMessageWith(properties: values)
        }
    }
}

Here is how I set up the url for the audioRecorder above.

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
}

func getAudiFileURL() -> URL {
    return getDocumentsDirectory().appendingPathComponent(".m4a")
}

And this is where I play the audio:

func handleAudioPLay() {
    if let audioUrl = message?.audioUrl, let url = URL(string: audioUrl) {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayAndRecord)
            audioPlayer = try AVAudioPlayer(contentsOf: url)
            audioPlayer?.delegate = self
            audioPlayer?.prepareToPlay()
            audioPlayer?.play()
            print("Audio ready to play")
        } catch let error {
            print(error.localizedDescription)
        }
    }
}

I can actually download the sound file from Firebase using the url and play it on my computer, which means the url is fine.

1

1 Answers

4
votes

I have solved the problem by downloading the sound file using URLSession, and play it using AVAudioPlayer(data: data!, fileTypeHint: "aac").