logo

iOS Speech框架实战:语音转文字的完整实现指南

作者:4042025.09.23 12:53浏览量:0

简介:本文详细解析iOS Speech框架实现语音转文字的技术方案,涵盖框架特性、核心API使用、权限配置及完整代码示例,助力开发者快速构建语音识别功能。

一、Speech框架概述

iOS Speech框架是Apple官方提供的语音识别解决方案,自iOS 10起作为系统级API开放,具备高精度、低延迟的实时语音转文字能力。相比第三方服务,Speech框架的优势在于:

  1. 隐私安全:所有语音处理均在设备端完成,无需上传云端
  2. 性能优化:深度集成iOS系统,资源占用率低
  3. 功能丰富:支持实时识别、连续识别、多语言识别等场景

核心组件包括:

  • SFSpeechRecognizer:语音识别器管理类
  • SFSpeechAudioBufferRecognitionRequest:实时音频流识别请求
  • SFSpeechRecognitionTask:识别任务控制类
  • SFSpeechRecognitionResult:识别结果封装类

二、开发环境准备

1. 权限配置

在Info.plist中添加两个权限声明:

  1. <key>NSSpeechRecognitionUsageDescription</key>
  2. <string>需要语音识别权限以实现实时转文字功能</string>
  3. <key>NSMicrophoneUsageDescription</key>
  4. <string>需要麦克风权限以采集语音数据</string>

2. 导入框架

在需要使用的文件中导入:

  1. import Speech

三、核心实现步骤

1. 初始化语音识别器

  1. let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))!
  2. // 中文识别使用zh-CN,英文使用en-US

2. 请求授权

  1. func requestAuthorization() {
  2. SFSpeechRecognizer.requestAuthorization { authStatus in
  3. DispatchQueue.main.async {
  4. switch authStatus {
  5. case .authorized:
  6. print("授权成功")
  7. case .denied:
  8. print("用户拒绝授权")
  9. case .restricted:
  10. print("设备限制")
  11. case .notDetermined:
  12. print("未决定")
  13. @unknown default:
  14. break
  15. }
  16. }
  17. }
  18. }

3. 创建识别请求

实时识别场景(麦克风输入)

  1. func startRecording() {
  2. guard let recognizer = speechRecognizer else { return }
  3. let audioEngine = AVAudioEngine()
  4. let request = SFSpeechAudioBufferRecognitionRequest()
  5. // 配置音频会话
  6. let audioSession = AVAudioSession.sharedInstance()
  7. try? audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
  8. try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
  9. // 安装音频输入节点
  10. let inputNode = audioEngine.inputNode
  11. let recordingFormat = inputNode.outputFormat(forBus: 0)
  12. inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
  13. request.append(buffer)
  14. }
  15. // 启动识别任务
  16. recognizer.recognitionTask(with: request) { [weak self] result, error in
  17. if let result = result {
  18. let transcribedText = result.bestTranscription.formattedString
  19. print("识别结果: \(transcribedText)")
  20. // 处理最终结果
  21. if result.isFinal {
  22. print("最终结果: \(transcribedText)")
  23. }
  24. }
  25. if let error = error {
  26. print("识别错误: \(error.localizedDescription)")
  27. audioEngine.stop()
  28. inputNode.removeTap(onBus: 0)
  29. }
  30. }
  31. // 启动音频引擎
  32. audioEngine.prepare()
  33. try? audioEngine.start()
  34. }

文件识别场景

  1. func recognizeAudioFile(url: URL) {
  2. guard let recognizer = speechRecognizer else { return }
  3. let request = SFSpeechURLRecognitionRequest(url: url)
  4. recognizer.recognitionTask(with: request) { result, error in
  5. if let result = result {
  6. print("文件识别结果: \(result.bestTranscription.formattedString)")
  7. }
  8. if let error = error {
  9. print("文件识别错误: \(error.localizedDescription)")
  10. }
  11. }
  12. }

4. 停止识别

  1. func stopRecording() {
  2. audioEngine.stop()
  3. audioEngine.inputNode.removeTap(onBus: 0)
  4. // 取消所有识别任务
  5. if let task = recognitionTask {
  6. task.cancel()
  7. }
  8. }

四、高级功能实现

1. 实时反馈优化

通过SFSpeechRecognitionResultisFinal属性区分中间结果和最终结果:

  1. recognizer.recognitionTask(with: request) { result, error in
  2. guard let result = result else { return }
  3. // 获取所有候选结果
  4. for transcription in result.transcriptions {
  5. print("候选结果: \(transcription.formattedString)")
  6. }
  7. // 只显示最佳结果
  8. let bestString = result.bestTranscription.formattedString
  9. if !result.isFinal {
  10. // 实时更新UI(需在主线程)
  11. DispatchQueue.main.async {
  12. self.textView.text = bestString
  13. }
  14. }
  15. }

2. 多语言支持

动态切换识别语言:

  1. func switchLanguage(to localeIdentifier: String) {
  2. speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: localeIdentifier))
  3. }

3. 错误处理

常见错误及解决方案:
| 错误类型 | 解决方案 |
|————-|—————|
| SFSpeechRecognizerError.notAvailable | 检查设备是否支持(iOS 10+) |
| SFSpeechRecognizerError.restricted | 引导用户到设置开启权限 |
| AVAudioSessionError | 检查麦克风权限和音频会话配置 |
| 网络相关错误(离线模式) | 确保supportsOnDeviceRecognition为true |

五、性能优化建议

  1. 音频格式选择:使用16kHz单声道采样率,平衡精度和性能
  2. 缓冲区大小:1024-4096样本点为最佳范围
  3. 后台处理:使用DispatchQueue.global()进行非UI相关计算
  4. 内存管理:及时取消不再需要的识别任务
  5. 电量优化:在后台时暂停识别

六、完整示例代码

  1. import UIKit
  2. import Speech
  3. import AVFoundation
  4. class VoiceRecognitionViewController: UIViewController {
  5. @IBOutlet weak var textView: UITextView!
  6. @IBOutlet weak var recordButton: UIButton!
  7. private let speechRecognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))!
  8. private var recognitionTask: SFSpeechRecognitionTask?
  9. private let audioEngine = AVAudioEngine()
  10. override func viewDidLoad() {
  11. super.viewDidLoad()
  12. requestAuthorization()
  13. }
  14. @IBAction func toggleRecording(_ sender: UIButton) {
  15. if audioEngine.isRunning {
  16. stopRecording()
  17. recordButton.setTitle("开始录音", for: .normal)
  18. } else {
  19. startRecording()
  20. recordButton.setTitle("停止录音", for: .normal)
  21. }
  22. }
  23. private func startRecording() {
  24. let audioSession = AVAudioSession.sharedInstance()
  25. try? audioSession.setCategory(.record, mode: .measurement, options: .duckOthers)
  26. try? audioSession.setActive(true, options: .notifyOthersOnDeactivation)
  27. let request = SFSpeechAudioBufferRecognitionRequest()
  28. guard let inputNode = audioEngine.inputNode else { return }
  29. recognitionTask = speechRecognizer.recognitionTask(with: request) { [weak self] result, error in
  30. guard let self = self else { return }
  31. if let result = result {
  32. let bestString = result.bestTranscription.formattedString
  33. DispatchQueue.main.async {
  34. self.textView.text = bestString
  35. }
  36. }
  37. if let error = error {
  38. print("识别错误: \(error.localizedDescription)")
  39. self.stopRecording()
  40. }
  41. }
  42. let recordingFormat = inputNode.outputFormat(forBus: 0)
  43. inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordingFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in
  44. request.append(buffer)
  45. }
  46. audioEngine.prepare()
  47. try? audioEngine.start()
  48. }
  49. private func stopRecording() {
  50. audioEngine.stop()
  51. audioEngine.inputNode.removeTap(onBus: 0)
  52. recognitionTask?.cancel()
  53. recognitionTask = nil
  54. }
  55. private func requestAuthorization() {
  56. SFSpeechRecognizer.requestAuthorization { authStatus in
  57. DispatchQueue.main.async {
  58. if authStatus != .authorized {
  59. self.showAlert(title: "权限错误", message: "需要麦克风和语音识别权限")
  60. }
  61. }
  62. }
  63. }
  64. private func showAlert(title: String, message: String) {
  65. let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
  66. alert.addAction(UIAlertAction(title: "确定", style: .default))
  67. present(alert, animated: true)
  68. }
  69. }

七、常见问题解答

Q1:Speech框架支持哪些语言?
A:支持iOS系统所有语言包,可通过SFSpeechRecognizer.supportedLocales()获取完整列表

Q2:离线识别效果如何?
A:中文离线识别准确率可达90%以上,专业术语识别建议使用在线模式

Q3:如何限制识别时长?
A:使用SFSpeechRecognitionRequestshouldReportPartialResults属性控制

Q4:后台识别如何实现?
A:需在Info.plist中添加UIBackgroundModes数组并包含audio

八、总结与展望

Speech框架为iOS开发者提供了强大且易用的语音识别能力,通过合理配置可以实现接近专业的转写效果。未来随着设备端AI的发展,离线识别的准确率和功能将进一步提升。建议开发者持续关注Apple的API更新,特别是对多语言支持和行业术语识别的优化。

实际应用中,建议结合CoreML框架实现领域特定的语音识别优化,例如医疗、法律等专业场景的术语增强。同时注意处理不同口音和背景噪音的情况,可通过预处理音频数据来提升识别质量。

相关文章推荐

发表评论