首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVAudioFile写不动iOS 14

AVAudioFile写不动iOS 14
EN

Stack Overflow用户
提问于 2021-06-14 02:46:59
回答 2查看 589关注 0票数 2

我的职能如下:

代码语言:javascript
复制
private func getPCMBuffer(utterance: AVSpeechUtterance,
                          completion: @escaping (Result<AVAudioPCMBuffer, Failures>) -> Void
) {
    speechSynthesizer.write(utterance) { (buffer: AVAudioBuffer) in
        guard let pcmBuffer = buffer as? AVAudioPCMBuffer else {
            fatalError("unknown buffer type: \(buffer)")
        }

        completion(.success(pcmBuffer))
    }
    completion(.failure(.failed))
}

返回给我一个AVAudioPCMBuffer。我已经证实了我所传递的话语是正确的。

当我试图在本地将这个AVAudioPCMBuffer写到一个URL中时,问题就出现了,如下所示:

代码语言:javascript
复制
                getPCMBuffer(utterance: speechUtterance) { result in
                    switch result {
                    case .success(let buffer):
                        var settings: [String : Any] = [:]
                        let savePathUrl: URL = URL(fileURLWithPath: NSHomeDirectory() + "/Documents/audioFile.caf")

                        settings[AVFormatIDKey] = kAudioFormatMPEG4AAC
                        settings[AVAudioFileTypeKey] = kAudioFileCAFType
                        settings[AVSampleRateKey] = buffer.format.sampleRate
                        settings[AVNumberOfChannelsKey] = 2
                        settings[AVLinearPCMIsFloatKey] = (buffer.format.commonFormat == .pcmFormatInt32)
                        do {
                            let tempFile = try AVAudioFile(forWriting: savePathUrl, settings: settings, commonFormat: buffer.format.commonFormat, interleaved: buffer.format.isInterleaved)
                            try tempFile.write(from: buffer)
                        } catch {
                            print(error)
                        }
                    case .failure(let failure):
                        print(failure.localizedDescription)
                    }
                }

遇到以下错误: CABufferList.h:179:BytesConsumed:断言失败(nBytes <= buf->mDataByteSize) != 0为false

在我试图做的事情上:

try tempFile.write(from: buffer)

EN

回答 2

Stack Overflow用户

发布于 2022-02-07 00:01:35

有几件事需要考虑:

  1. 必须对文件使用正确的格式。
  2. -- writeUtterance:toBufferCallback:的回调被多次调用,每次使用合成音频的下一块。据我所知,它每次合成10毫秒的音频。(undocumented)
  3. You必须关闭文件才能刷新它。关闭是通过释放对对象的引用来完成的。(undocumented).

代码语言:javascript
复制
@property (readonly, nonatomic) AVSpeechSynthesizer *synth;
@property (strong, nonatomic) AVAudioFile *file;

...

_synth = [[AVSpeechSynthesizer alloc] init];
self.synth.delegate = self;

...

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
 didFinishSpeechUtterance:(AVSpeechUtterance *)utterance {
  self.file = nil; // releasing the file will close it
  NSLog(@"Finished");
}


- (void)generateTranscript {
  AVSpeechUtterance *utterance =
      [AVSpeechUtterance speechUtteranceWithString:...];
  utterance.voice = ...;

  [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
                                          withOptions:AVAudioSessionCategoryOptionMixWithOthers
                                         error:nil];

  [self.synth writeUtterance:utterance toBufferCallback:^(AVAudioBuffer * _Nonnull buffer) {
    NSAssert([buffer isKindOfClass:AVAudioPCMBuffer.class], @"");
    NSError *error;

    if (!self.file) {
      NSURL *url = [NSURL fileURLWithPath:[NSTemporaryDirectory()
                                           stringByAppendingPathComponent:@"recording.m4a"]];
      NSMutableDictionary *settings = [NSMutableDictionary dictionary];
      settings[AVFormatIDKey] = @(kAudioFormatMPEG4AAC);
      settings[AVEncoderAudioQualityKey] = @(AVAudioQualityMax);
      settings[AVSampleRateKey] = buffer.format.settings[AVSampleRateKey]; // 22050 Hz
      settings[AVNumberOfChannelsKey] = buffer.format.settings[AVNumberOfChannelsKey]; // 1 channel
      self.file = [[AVAudioFile alloc] initForWriting:url settings:settings
                                         commonFormat:buffer.format.commonFormat // AVAudioPCMFormatInt16
                                          interleaved:buffer.format.interleaved // YES
                                                        error:&error];
      if (error) {
        NSLog(@"%@", error);
        return;
      }
    }

    [self.file writeFromBuffer:(AVAudioPCMBuffer *)buffer error:&error];
    if (error) {
      NSLog(@"%@", error);
      return;
    }

    AVAudioFrameCount frameCont = ((AVAudioPCMBuffer *)buffer).frameLength;
    double sampleRate = buffer.format.sampleRate;
    NSLog(@"Written %.4lfs", (double)frameCont / sampleRate);
  }];
}

关于格式,我还建议您阅读AVSpeechSynthesisVoice audioFileSettings文档。

票数 0
EN

Stack Overflow用户

发布于 2022-04-15 19:54:37

这个对我有用

`

代码语言:javascript
复制
private func uploadBuffer(_ buffer: AVAudioPCMBuffer) {
    

    let fileManager = FileManager.default
        do {


            let documentDirectory = try! fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
            try! FileManager.default.createDirectory(atPath: documentDirectory.path, withIntermediateDirectories: true, attributes: nil)

            let fileURL = documentDirectory.appendingPathComponent("out.wav")
            print(fileURL.path)
            let audioFile = try! AVAudioFile(forWriting: fileURL, settings: buffer.format.settings, commonFormat: buffer.format.commonFormat, interleaved: true)
            try! audioFile.write(from: buffer)
            
            
  
            
            
        } catch {
            print(error)
        }
    
    

    
}

`

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67964242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档