如何在 CloudKit 中存储和检索音频文件?
How can I store and retrieve audio files to and from CloudKit?
我正在尝试录制语音消息并将其作为 CKAssets 存储在 CloudKit 上。我将它们转换为 AVAudioFile 并将它们保存到 CloudKit 作为 Post 记录中的几个属性之一。
var recordedMessage: AVAudioFile?
var recordedMessageURL: URL? {
didSet {
if let recordedMessageURL = recordedMessageURL {
recordedMessage = try? AVAudioFile(forReading: recordedMessageURL)
}
}
}
这部分过程似乎有效,尽管当我通过 CloudKit 仪表板访问文件时无法播放音频。 (双击打开iTunes,但无法播放)
我创建了一个 fetchPosts 函数,它成功地下载了与记录相关的图像,但是当我尝试播放音频时,它给我以下错误:
ExtAudioFile.cpp:192:Open: about to throw -43: open audio file
我认为这与我无法将资产正确转换为 AVAudioFile 有关。它似乎不像转换图像资产那样干净利落。
var foundAudio: AVAudioFile?
if let audioAsset = ckRecord[PostStrings.audioAssetKey] as? CKAsset {
do {
let audioData = try Data(contentsOf: audioAsset.fileURL!)
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
guard let destinationPath = NSURL(fileURLWithPath: documentsPath).appendingPathComponent("filename.m4a", isDirectory: false) else {return nil}
FileManager.default.createFile(atPath: destinationPath.path, contents: audioData, attributes: nil)
foundAudio = try AVAudioFile(forReading: destinationPath)
} catch {
print("Could not transform asset into data")
}
}
谁能告诉我哪里出错了?
花了很多天时间来改变周围的事物,但我有一个可行的解决方案,它不涉及直接将数据作为数据进行操作。相反,我使用 URL。我将 audioAsset 初始化为 URL:
var opComment: URL?
var audioAsset: CKAsset? {
get {
guard let audioURL = opComment else { return nil }
return CKAsset(fileURL: audioURL)
}
set {
opComment = newValue?.fileURL
}
}
我用一个方便的初始化程序把 ckRecord 拉回来了:
var opCommentURL: URL?
if let audioAsset = ckRecord[PostStrings.audioAssetKey] as? CKAsset {
opCommentURL = audioAsset.fileURL
}
然后我将它作为 URL:
送入我的 AVAudioPlayer
guard let audioURL = post.opComment else {return}
if !isTimerRunning {
do {
audioPlayer = try AVAudioPlayer(contentsOf: audioURL)
audioPlayer.play()
} catch {
print("Error in \(#function) : \(error.localizedDescription) /n---/n \(error)")
}
} else {
audioPlayer.pause()
isTimerRunning = false
}
(如果您正在阅读本文,山姆。感谢您向正确的方向轻轻推动!)
我正在尝试录制语音消息并将其作为 CKAssets 存储在 CloudKit 上。我将它们转换为 AVAudioFile 并将它们保存到 CloudKit 作为 Post 记录中的几个属性之一。
var recordedMessage: AVAudioFile?
var recordedMessageURL: URL? {
didSet {
if let recordedMessageURL = recordedMessageURL {
recordedMessage = try? AVAudioFile(forReading: recordedMessageURL)
}
}
}
这部分过程似乎有效,尽管当我通过 CloudKit 仪表板访问文件时无法播放音频。 (双击打开iTunes,但无法播放)
我创建了一个 fetchPosts 函数,它成功地下载了与记录相关的图像,但是当我尝试播放音频时,它给我以下错误:
ExtAudioFile.cpp:192:Open: about to throw -43: open audio file
我认为这与我无法将资产正确转换为 AVAudioFile 有关。它似乎不像转换图像资产那样干净利落。
var foundAudio: AVAudioFile?
if let audioAsset = ckRecord[PostStrings.audioAssetKey] as? CKAsset {
do {
let audioData = try Data(contentsOf: audioAsset.fileURL!)
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
guard let destinationPath = NSURL(fileURLWithPath: documentsPath).appendingPathComponent("filename.m4a", isDirectory: false) else {return nil}
FileManager.default.createFile(atPath: destinationPath.path, contents: audioData, attributes: nil)
foundAudio = try AVAudioFile(forReading: destinationPath)
} catch {
print("Could not transform asset into data")
}
}
谁能告诉我哪里出错了?
花了很多天时间来改变周围的事物,但我有一个可行的解决方案,它不涉及直接将数据作为数据进行操作。相反,我使用 URL。我将 audioAsset 初始化为 URL:
var opComment: URL?
var audioAsset: CKAsset? {
get {
guard let audioURL = opComment else { return nil }
return CKAsset(fileURL: audioURL)
}
set {
opComment = newValue?.fileURL
}
}
我用一个方便的初始化程序把 ckRecord 拉回来了:
var opCommentURL: URL?
if let audioAsset = ckRecord[PostStrings.audioAssetKey] as? CKAsset {
opCommentURL = audioAsset.fileURL
}
然后我将它作为 URL:
送入我的 AVAudioPlayer guard let audioURL = post.opComment else {return}
if !isTimerRunning {
do {
audioPlayer = try AVAudioPlayer(contentsOf: audioURL)
audioPlayer.play()
} catch {
print("Error in \(#function) : \(error.localizedDescription) /n---/n \(error)")
}
} else {
audioPlayer.pause()
isTimerRunning = false
}
(如果您正在阅读本文,山姆。感谢您向正确的方向轻轻推动!)