gpt4 book ai didi

ios - AVAudioFile init 在模拟器上工作但在设备上崩溃

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:14:50 28 4
gpt4 key购买 nike

我想构建一个 iOS 应用程序(使用 Swift 3 和 Xcode 8.2.1)从 iPhone 的麦克风录音并将录音保存到 .caf 文件。


首先,我将以下行添加到我项目的 Info.plist 文件中:

<key>NSMicrophoneUsageDescription</key>
<string>Some description to explain why access is required</string>

然后,我创建了一个简单的 UIViewController,它设置了一个 AVAudioEngine 并在点击 Record停止按钮。

ViewController.swift

import UIKit
import AVFoundation

class ViewController: UIViewController {

var engine = AVAudioEngine()
var file: AVAudioFile?
var player = AVAudioPlayerNode()

override func viewDidLoad() {
super.viewDidLoad()

guard let url = urlFor(filename: "test.caf") else { return }
do {
file = try AVAudioFile(forWriting: url, settings: engine.inputNode!.inputFormat(forBus: 0).settings, commonFormat: engine.inputNode!.inputFormat(forBus: 0).commonFormat, interleaved: false)
} catch {
print("Error: \(error)")
}

engine.attach(player)
engine.connect(player, to: engine.mainMixerNode, format: engine.mainMixerNode.outputFormat(forBus: 0))

do {
try engine.start()
} catch {
print("Error: \(error)")
}
}

@IBAction func record(sender: AnyObject) {
engine.inputNode?.installTap(onBus: 0, bufferSize: 1024, format: engine.mainMixerNode.outputFormat(forBus: 0)) { (buffer, time) -> Void in
do {
try self.file?.write(from: buffer)
} catch {
print("Error: \(error)")
}
}
}

@IBAction func stop(sender: AnyObject) {
engine.inputNode?.removeTap(onBus: 0)
// Print the url of the saved file
let urls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
print(urls[urls.endIndex - 1])
}

func urlFor(filename: String) -> URL? {
// Get url of saved file
if let dir = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true).first {
let path = dir.appending(filename)
return URL(fileURLWithPath: path)
}
return nil
}

}

该应用程序在模拟器上运行良好:我可以录制我的声音,获取录制文件的 url 并测试我的声音是否已正确录制。但是,一旦我在设备上启动该应用程序(在 iOS 10.2.1 上使用 iPhone 6s 进行测试),该应用程序就会崩溃。控制台为我提供了以下日志:

2017-02-08 17:09:14.330151 AudioEngineSimpleApp[7100:2659416] Audio files cannot be non-interleaved. Ignoring setting AVLinearPCMIsNonInterleaved YES.
2017-02-08 17:09:14.333715 AudioEngineSimpleApp[7100:2659416] [central] 54: ERROR: [0x1b7440c40] >avae> AVAudioFile.mm:160: AVAudioFileImpl: error -54
2017-02-08 17:09:14.333796 AudioEngineSimpleApp[7100:2659416] [central] 54: ERROR: [0x1b7440c40] >avae> AVAudioFile.mm:122: ReadMagicCookie: error -50
2017-02-08 17:09:14.334369 AudioEngineSimpleApp[7100:2659416] *** Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -50'

这个问题似乎与 Stack Overflow 线程有关 AVAudioPlayer working on Simulator but not on Real Device但我不知道如何将其响应实现到我自己的代码中以解决我的问题。

最佳答案

我重构了我的代码,并将我的旧 urlFor(filename: String) -> URL? 方法替换为以下 url 属性:

let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("test.caf")

因此,以下代码可以在设备上正常运行:

import UIKit
import AVFoundation

class ViewController: UIViewController {

@IBOutlet weak var recordButton: UIButton!
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("test.caf")
//let url = URL(fileURLWithPath: NSTemporaryDirectory().appending("test.caf")) also works
var engine = AVAudioEngine()

override func viewDidLoad() {
super.viewDidLoad()

recordButton.setTitle("Record", for: .normal)

let file: AVAudioFile
do {
file = try AVAudioFile(forWriting: url, settings: engine.inputNode!.outputFormat(forBus: 0).settings)
} catch {
print("Error: \(error)")
return
}

engine.inputNode?.installTap(onBus: 0, bufferSize: 1024, format: engine.inputNode!.outputFormat(forBus: 0)) { (buffer, time) -> Void in
do {
try file.write(from: buffer)
} catch {
print("Error: \(error)")
}
}
}

@IBAction func toggleAction(_ sender: AnyObject) {
engine.isRunning ? stopRecording() : startRecording()
}

func startRecording() {
do {
// Start engine
try engine.start()

// Toggle button title
recordButton.setTitle("Stop", for: .normal)
} catch {
print("Error: \(error)")
}
}

func stopRecording() {
// Stop engine
engine.stop()

// Toggle button title
recordButton.setTitle("Record", for: .normal)

print(url)
}

}

关于ios - AVAudioFile init 在模拟器上工作但在设备上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42118181/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com