You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS应用中使用SFSpeechRecognizer转录长音频报错‘Corrupt’如何解决

解决SFSpeechRecognizer处理长音频时的"Corrupt"错误

错误原因

  1. 误用实时录音逻辑处理本地长音频:你通过AudioEngine输入节点的tap收集音频,这是为实时录音设计的流程,完全不适合批量处理长音频文件;而且代码仅读取了1024帧的音频片段,根本没加载完整的30分钟音频内容。
  2. 音频格式不匹配:用设备输入节点的格式创建tap,但本地音频文件格式和该格式不一致,导致识别服务收到损坏的音频数据,触发"Corrupt"错误。
  3. 忽略官方专用API:SFSpeechRecognizer提供了直接处理本地文件的接口,绕路用AudioEngine反而引发兼容性问题。

修正后的代码

import Speech
import AVFoundation

class AudioTranscriber {
    private let speechRecognizer: SFSpeechRecognizer?
    private var recognitionTask: SFSpeechRecognitionTask?
    
    init(locale: Locale? = nil) {
        speechRecognizer = SFSpeechRecognizer(locale: locale ?? Locale(identifier: "uk"))
        // 提前请求权限,避免处理音频时阻塞
        SFSpeechRecognizer.requestAuthorization { status in
            switch status {
            case .authorized:
                print("语音识别权限已授权")
            case .denied, .restricted, .notDetermined:
                print("语音识别权限未授权,无法进行转录")
            @unknown default:
                break
            }
        }
    }
    
    func transcribeAudio(at url: URL) {
        guard speechRecognizer?.isAvailable == true else {
            print("语音识别服务当前不可用")
            return
        }
        
        // 取消正在进行的任务
        if let task = recognitionTask {
            task.cancel()
            recognitionTask = nil
        }
        
        // 使用官方针对本地文件的请求类型
        let recognitionRequest = SFSpeechURLRecognitionRequest(url: url)
        // 长音频建议关闭部分结果,减少资源消耗,按需开启
        recognitionRequest.shouldReportPartialResults = false
        
        // 创建识别任务
        recognitionTask = speechRecognizer?.recognitionTask(with: recognitionRequest) { [weak self] result, error in
            guard let self = self else { return }
            
            if let error = error {
                print("识别错误: \(error.localizedDescription)")
                return
            }
            
            // 处理完整转录结果
            if let result = result {
                let fullText = result.bestTranscription.formattedString
                print("完整转录内容:\n\(fullText)")
                
                // 可选:获取每个片段的时间戳和文本
                for segment in result.bestTranscription.segments {
                    let start = segment.timestamp
                    let end = start + segment.duration
                    print("[\(String(format: "%.2f", start))s - \(String(format: "%.2f", end))s]: \(segment.substring)")
                }
            }
            
            // 任务结束时清理
            if result?.isFinal == true {
                self.recognitionTask = nil
            }
        }
    }
}

关键改动说明

  • 改用SFSpeechURLRecognitionRequest:苹果官方推荐的本地音频处理方式,系统自动完成音频解码、分段和流转,完美支持长音频。
  • 移除AudioEngine冗余代码:不需要通过播放音频收集数据,直接让识别服务读取文件,效率更高且避免格式冲突。
  • 完善权限与任务管理:提前请求权限,避免运行时阻塞;增加任务取消逻辑,防止重复任务冲突。
  • 优化结果输出:支持完整文本和分段时间戳输出,满足长音频内容定位需求。

内容的提问来源于stack exchange,提问作者MarK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 09:30:38