I want to upload audio files to Firebase Storage and then fetch them to play. I try to store the path of the in a global variable:
var fileURL: URL?
Currently I have the following code the record the audio using AVFoundation:
func startRecording() {
let recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(.playAndRecord, mode: .default)
try recordingSession.setActive(true)
}
catch {
print("Failed to set up recording session")
}
let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let audioFilename = documentPath.appendingPathComponent("\(Date().toString(dateFormat: "dd-MM-YY_'at'_HH:mm:ss")).m4a")
self.fileURL = audioFilename
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.record()
recording = true
}
catch {
print("Could not start recording with error: \(error)")
}
}
After this I want to to stop the recording but also upload to file to Firebase. Currently, I have this piece of code which I have written referring to the Firebase documentation based on uploading files form a local reference point. I am not sure how to access to the data of the audio file or what is a good way to upload it directly to Firebase Storage. Here is the full ViewModel code:
import Foundation
import AVFoundation
import SwiftUI
import Combine
import Firebase
class VoiceViewModel : NSObject ,ObservableObject {
override init() {
super.init()
fetchRecordings()
}
var fileURL: URL?
let objectWillChange = PassthroughSubject<VoiceViewModel, Never>()
var audioRecorder: AVAudioRecorder!
var recordings = [Recording]()
@Published var recording = false {
didSet {
objectWillChange.send(self)
}
}
func startRecording() {
let recordingSession = AVAudioSession.sharedInstance()
do {
try recordingSession.setCategory(.playAndRecord, mode: .default)
try recordingSession.setActive(true)
}
catch {
print("Failed to set up recording session")
}
let documentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let audioFilename = documentPath.appendingPathComponent("\(Date().toString(dateFormat: "dd-MM-YY_'at'_HH:mm:ss")).m4a")
self.fileURL = audioFilename
let settings = [
AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
AVSampleRateKey: 12000,
AVNumberOfChannelsKey: 1,
AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
]
do {
audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
audioRecorder.record()
recording = true
}
catch {
print("Could not start recording with error: \(error)")
}
}
func stopRecording() {
audioRecorder.stop()
recording = false
let storageRef = Storage.storage().reference()
let localfile = self.fileURL ?? URL(string: "")
let fileRef = storageRef.child("images/try.m4a")
print(self.fileURL?.absoluteURL)
let uploadTask = fileRef.putFile(from: localfile!, metadata: nil) { metaData, err in
guard let metadata = metaData else { return }
if let err = err {
print(err.localizedDescription)
return
}
fileRef.downloadURL { (url, err) in
guard let downloadUrl = url else { return }
print(downloadUrl)
}
}
fetchRecordings()
}
func fetchRecordings() {
recordings.removeAll()
let fileManager = FileManager.default
let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let directoryContents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil)
for audio in directoryContents {
let recording = Recording(fileURL: audio, createdAt: getCreationDate(for: audio))
recordings.append(recording)
recordings.sort(by: { $0.createdAt.compare($1.createdAt) == .orderedAscending})
objectWillChange.send(self)
}
}
}