使用SwiftUI和AVFoundation将音频文件上载到Firebase
我想将音频文件上载到Firebase存储,然后将其取出播放。我尝试将的路径存储在全局变量中:使用SwiftUI和AVFoundation将音频文件上载到Firebase,firebase,swiftui,avfoundation,firebase-storage,avkit,Firebase,Swiftui,Avfoundation,Firebase Storage,Avkit,我想将音频文件上载到Firebase存储,然后将其取出播放。我尝试将的路径存储在全局变量中: var fileURL: URL? 目前,我使用AVFoundation录制音频的代码如下: func startRecording() { let recordingSession = AVAudioSession.sharedInstance() do { try recordingSession.setCatego
var fileURL: URL?
目前,我使用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)")
}
}
在此之后,我想停止录音,但也上传到文件到Firebase。目前,我已经编写了这段代码,它参考了基于本地参考点上传文件的Firebase文档。我不知道如何访问音频文件的数据,也不知道什么是直接上传到Firebase存储的好方法。以下是完整的ViewModel代码:
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)
}
}
}
<代码>导入基础
进口AVF基金会
导入快捷键
进口联合收割机
进口火基
类VoiceViewModel:NSObject,ObservableObject{
重写init(){
super.init()
fetchRecordings()
}
var fileURL:URL?
let objectWillChange=PassthroughSubject()
var录音机:AVAudioRecorder!
var记录=[记录]()
@已发布的var记录=false{
迪塞特{
objectWillChange.send(self)
}
}
func startRecording(){
让recordingSession=AVAudioSession.sharedInstance()
做{
尝试录制Session.setCategory(.playAndRecord,模式:。默认值)
尝试recordingSession.setActive(真)
}
抓住{
打印(“设置录制会话失败”)
}
让documentPath=FileManager.default.URL(对于:.documentDirectory,在:.userDomainMask中)[0]
让audioFilename=documentPath.appendingPathComponent(\(Date().toString(dateFormat:“dd-MM-YY”at“u HH:MM:ss”).m4a)
self.fileURL=audioFilename
让设置=[
AVFormatIDKey:Int(kaudioformampeg4aac),
AVE密钥:12000,
AVNumberOfChannelsKey:1,
AVEncoderAudioQualityKey:AVAudioQuality.high.rawValue
]
做{
audioRecorder=试用AVAudioRecorder(url:audioFilename,设置:设置)
录音机
录音=真
}
抓住{
打印(“无法开始录制,错误:\(错误)”)
}
}
函数停止录制(){
录音机
录音=假
让storageRef=Storage.Storage().reference()
让localfile=self.fileURL??URL(字符串:“”)
让fileRef=storageRef.child(“images/try.m4a”)
打印(self.fileURL?.absoluteURL)
让uploadTask=fileRef.putFile(from:localfile!,metadata:nil){metadata,err-in
guard let metadata=元数据else{return}
如果让err=err{
打印(错误本地化描述)
返回
}
fileRef.downloadURL{(url,err)位于
guard let downloadUrl=url else{return}
打印(下载URL)
}
}
fetchRecordings()
}
func fetchRecordings(){
recordings.removeAll()
让fileManager=fileManager.default
让documentDirectory=fileManager.URL(对于:.documentDirectory,在:.userDomainMask中)[0]
让directoryContents=try!fileManager.contentsOfDirectory(位于:documentDirectory,包括属性forkeys:nil)
用于directoryContents中的音频{
让录制=录制(fileURL:audio,createdAt:getCreationDate(for:audio))
录音。追加(录音)
recordings.sort(按:{$0.createdAt.compare($1.createdAt)==.orderedAscending})
objectWillChange.send(self)
}
}
}
您似乎已经编写了上载文件的代码。你能澄清问题在哪里,或者你在哪里得到了意想不到的结果吗?另外,请注意,您不需要在
@Published
属性上使用didSet{objectWillChange.send(self)}
——这只在SwiftUI 1.0的测试版期间才需要。当我调用startRecording函数时,我没有得到任何错误。调用stopRecording函数时,出现以下错误:AddInstanceForFactory:没有为id注册的工厂。我不确定问题出在哪里。当我打印出self.fileURL函数时,我得到了本地路径。你是这样搜索的吗?这个问题和答案似乎解决了这个问题:是的,这是关于AVPlayer的。尝试将文件上载到Firebase时出错。“audioRecorder.stop()”函数来自“AVAudioRecorder”类。而且音频文件可以毫无问题地保存在设备中。但是,该文件不会上载到Firebase存储。