gpt4 book ai didi

ios - 录制时裁剪音频文件的方法?

转载 作者:可可西里 更新时间:2023-11-01 00:40:31 25 4
gpt4 key购买 nike

我正在编写一个先进先出的录音应用程序,使用 AudioQueue 缓冲最多 2.5 分钟的音频.我已经弄清楚了其中的大部分内容,但我在尝试裁剪音频数据时遇到了障碍。

我见过有人用 AVAssetExportSession 来做这件事但每次 AudioQueueInputCallback 时导出新轨道似乎性能不佳被称为。

我不喜欢使用 AVAssestExportSession如果有人有更好的主意,可以通过任何方式。

这是我写作的地方,希望能进行裁剪。

 var beforeSeconds = TimeInterval() // find the current estimated duration (not reliable)
var propertySize = UInt32(MemoryLayout.size(ofValue: beforeSeconds))
var osStatus = AudioFileGetProperty(audioRecorder.recordFile!, kAudioFilePropertyEstimatedDuration, &propertySize, &beforeSeconds)

if numPackets > 0 {
AudioFileWritePackets(audioRecorder.recordFile!, // write to disk
false,
buffer.mAudioDataByteSize,
packetDescriptions,
audioRecorder.recordPacket,
&numPackets,
buffer.mAudioData)
audioRecorder.recordPacket += Int64(numPackets) // up the packet index

var afterSeconds = TimeInterval() // find the after write estimated duration (not reliable)
var propertySize = UInt32(MemoryLayout.size(ofValue: afterSeconds))
var osStatus = AudioFileGetProperty(audioRecorder.recordFile!, kAudioFilePropertyEstimatedDuration, &propertySize, &afterSeconds)
assert(osStatus == noErr, "couldn't get record time")

if afterSeconds >= 150.0 {
print("hit max buffer!")
audioRecorder.onBufferMax?(afterSeconds - beforeSeconds)
}
}

这里是执行回调的地方

func onBufferMax(_ difference: Double){
let asset = AVAsset(url: tempFilePath)
let duration = CMTimeGetSeconds(asset.duration)
guard duration >= 150.0 else { return }

guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
print("exporter init failed")
return }


exporter.outputURL = getDocumentsDirectory().appendingPathComponent("buffered.caf") // helper function that calls the FileManager
exporter.outputFileType = AVFileTypeAppleM4A

let startTime = CMTimeMake(Int64(difference), 1)
let endTime = CMTimeMake(Int64(WYNDRConstants.maxTimeInterval + difference), 1)

exporter.timeRange = CMTimeRangeFromTimeToTime(startTime, endTime)
exporter.exportAsynchronously(completionHandler: {
switch exporter.status {
case .failed:
print("failed to export")
case .cancelled:
print("canceled export")
default:
print("export successful")
}
})
}

最佳答案

环形缓冲区是一种有用的结构,可用于在内存或磁盘上存储最近 n 秒的音频。这是一个将音频存储在内存中的简单解决方案,以传统的 UIViewController 格式呈现。

注意 2.5 分钟的 44.1kHz 音频存储为 float 需要大约 26MB 的 RAM,这对于移动设备来说是沉重的一面。

import AVFoundation

class ViewController: UIViewController {
let engine = AVAudioEngine()

var requiredSamples: AVAudioFrameCount = 0
var ringBuffer: [AVAudioPCMBuffer] = []
var ringBufferSizeInSamples: AVAudioFrameCount = 0

func startRecording() {
let input = engine.inputNode!

let bus = 0
let inputFormat = input.inputFormat(forBus: bus)

requiredSamples = AVAudioFrameCount(inputFormat.sampleRate * 2.5 * 60)

input.installTap(onBus: bus, bufferSize: 512, format: inputFormat) { (buffer, time) -> Void in
self.appendAudioBuffer(buffer)
}

try! engine.start()
}

func appendAudioBuffer(_ buffer: AVAudioPCMBuffer) {
ringBuffer.append(buffer)
ringBufferSizeInSamples += buffer.frameLength

// throw away old buffers if ring buffer gets too large
if let firstBuffer = ringBuffer.first {
if ringBufferSizeInSamples - firstBuffer.frameLength >= requiredSamples {
ringBuffer.remove(at: 0)
ringBufferSizeInSamples -= firstBuffer.frameLength
}
}
}

func stopRecording() {
engine.stop()

let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("foo.m4a")
let settings: [String : Any] = [AVFormatIDKey: Int(kAudioFormatMPEG4AAC)]

// write ring buffer to file.
let file = try! AVAudioFile(forWriting: url, settings: settings)
for buffer in ringBuffer {
try! file.write(from: buffer)
}
}

override func viewDidLoad() {
super.viewDidLoad()

// example usage
startRecording()

DispatchQueue.main.asyncAfter(deadline: .now() + 4*60) {
print("stopping")
self.stopRecording()
}
}
}

关于ios - 录制时裁剪音频文件的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44271545/

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