Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift 3 Record audio and upload to Firebase storage and play back

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. (The URL is pointing to the file's location in the iOS devices.)

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.

like image 710
Bryce Avatar asked Mar 12 '17 14:03

Bryce


1 Answers

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

like image 74
Bryce Avatar answered Nov 15 '22 05:11

Bryce