Swift語音和文字的轉換

weixin_33751566發表於2017-12-22

TextAndVoice

Swift語音和文字的轉換

相關部落格

談到語音和文字的轉換, 就要說到語音轉文字和文字轉語音兩大技術

  • 文字轉語音是iOS7以後的技術, 用到的是AVFoundation框架
  • 語音轉文字是iOS10以後, 蘋果釋出的一個Speech框架
  • 下面先介紹一下簡單的文字轉語音
  • GitHub上Demo地址
  • 專案包括
    • 文字轉語音
    • 實時語音轉文字
    • 本地語音轉文字
    • 錄音儲存本地,轉文字

一. 文字轉語音

  • 文字轉語音技術, 簡稱TTS (是Text To Speech的縮寫), 語音合成蘋果官方文件
  • 是蘋果iOS7以後新增的功能, 使用AVFoundation 庫
  • 下面介紹一下需要用到的類

1. AVSpeechSynthesizer: 語音合成器

1-1. 屬性

//是否正在語音播放
open var isSpeaking: Bool { get }

//是否停止語音播放
open var isPaused: Bool { get }

1-2. 方法

//播放語音
open func speak(_ utterance: AVSpeechUtterance)

//停止語音播放
open func stopSpeaking(at boundary: AVSpeechBoundary) -> Bool

//暫停語音播放
open func pauseSpeaking(at boundary: AVSpeechBoundary) -> Bool

//繼續語音播放
open func continueSpeaking() -> Bool

//(iOS10以上, 輸出通道)
open var outputChannels: [AVAudioSessionChannelDescription]?

2. AVSpeechBoundary

  • 描述語音可能被暫停或停止的列舉值
case immediate
//表示發言應該暫停或立即停止。

case word
//說完整個詞語之後再暫停或者停止

3. AVSpeechUtterance

  • 可以將文字和成一段語音的類, 或者說就是一段要播放的語音

3-1. 屬性

//使用的聲音
open var voice: AVSpeechSynthesisVoice?

//文字屬性    
open var speechString: String { get }

//富文字屬性
@available(iOS 10.0, *)
open var attributedSpeechString: NSAttributedString { get }

//說話的速度    
open var rate: Float 
//提供了兩個語速 AVSpeechUtteranceMinimumSpeechRate和 AVSpeechUtteranceMaximumSpeechRate和AVSpeechUtteranceDefaultSpeechRate

//說話的基線音高, [0.5 - 2] Default = 1   
open var pitchMultiplier: Float 

//說話音量, [0-1] Default = 1
open var volume: Float 

//開始一段語音之前等待的時間
open var preUtteranceDelay: TimeInterval 

//語音合成器在當前語音結束之後處理下一個排隊的語音之前需要等待的時間, 預設0.0 
open var postUtteranceDelay: TimeInterval

3-2. 初始化方法

public init(string: String)

@available(iOS 10.0, *)
public init(attributedString string: NSAttributedString)

4. AVSpeechSynthesisVoice

  • 用於語音合成的獨特聲音, 主要是不同的語言和地區
  • 所支援的所有語言種類詳見最底部附錄

4-1. 相關屬性

//獲得當前的語言
open var language: String { get }

//返回使用者當前語言環境的程式碼
@available(iOS 9.0, *)
open var identifier: String { get }

@available(iOS 9.0, *)
open var name: String { get }

@available(iOS 9.0, *)
open var quality: AVSpeechSynthesisVoiceQuality { get }

4-2. 相關方法

init?(language: String?)
//返回指定語言和語言環境的語音物件。

class func speechVoices()
//返回所有可用的語音。


class func currentLanguageCode()
//返回使用者當前語言環境的程式碼。

5. AVSpeechSynthesizerDelegate代理

  • 所有代理方法都是支援iOS7.0以上的系統
//開始播放
optional public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance)

//播放完成
optional public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance)

//暫停播放
optional public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance)

//繼續播放
optional public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance)

//取消播放
optional public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance)

//將要播放某一段話  
optional public func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance)

6. 具體功能的核心程式碼

//MARK: 開始/停止轉換
extension TextToVoiceController{
    //開始轉換
    fileprivate func startTranslattion(){
        //1. 建立需要合成的聲音型別
        let voice = AVSpeechSynthesisVoice(language: "zh-CN")
        
        //2. 建立合成的語音類
        let utterance = AVSpeechUtterance(string: textView.text)
        utterance.rate = AVSpeechUtteranceDefaultSpeechRate
        utterance.voice = voice
        utterance.volume = 1
        utterance.postUtteranceDelay = 0.1
        utterance.pitchMultiplier = 1
        //開始播放
        avSpeech.speak(utterance)
    }
    
    //暫停播放
    fileprivate func pauseTranslation(){
        avSpeech.pauseSpeaking(at: .immediate)
    }
    
    //繼續播放
    fileprivate func continueSpeek(){
        avSpeech.continueSpeaking()
    }
    
    //取消播放
    fileprivate func cancleSpeek(){
        avSpeech.stopSpeaking(at: .immediate)
    }
}

二. 語音轉文字

  • 在2016 WWDC大會上,Apple公司介紹了一個很好的語音識別的API,那就是Speech框架
  • Speech框架支援iOS10以上系統
  • Speech框架官方文件
  • 下面簡單介紹一下主要的操作類

1. SFSpeechRecognizer: 語音識別器

  • 這個類是語音識別的操作類
  • 用於語音識別使用者許可權的申請,語言環境的設定,語音模式的設定以及向Apple服務傳送語音識別的請求
  • 初始化方法
//這個初始化方法將預設以裝置當前的語言環境作為語音識別的語言環境
public convenience init?() 

//根據支援的語言初始化
public init?(locale: Locale) 
//示例
let recognize = SFSpeechRecognizer(locale: Locale(identifier: "zh-CN"))
  • 類方法
//獲取所有支援的語言
open class func supportedLocales() -> Set<Locale>

//獲取當前使用者許可權狀態
open class func authorizationStatus() -> SFSpeechRecognizerAuthorizationStatus

//申請語音識別使用者許可權
open class func requestAuthorization(_ handler: @escaping (SFSpeechRecognizerAuthorizationStatus) -> Swift.Void)
  • 其他屬性
var isAvailable: Bool
//指示語音識別器是否可用

var locale: Locale
//當前語音識別器的語言環境

class func supportedLocales()
//獲取語音識別所有支援的語言

var queue: OperationQueue
//語音識別器用於識別任務處理程式和委託訊息的佇列
  • 相關方法
//識別與指定請求關聯的音訊來源的語音,使用指定的協議返回結果
open func recognitionTask(with request: SFSpeechRecognitionRequest, resultHandler: @escaping (SFSpeechRecognitionResult?, Error?) -> Swift.Void) -> SFSpeechRecognitionTask

//識別與指定請求關聯的音訊源的語音, 使用閉包結果
open func recognitionTask(with request: SFSpeechRecognitionRequest, delegate: SFSpeechRecognitionTaskDelegate) -> SFSpeechRecognitionTask
  • 代理
weak var delegate: SFSpeechRecognizerDelegate? { get set }

//代理方法: 監視語音識別器的可用性
func speechRecognizer(SFSpeechRecognizer, availabilityDidChange: Bool)

2. SFSpeechRecognitionRequest

  • 語音識別請求類,需要通過其子類來進行例項化
  • 相關屬性

var contextualStrings: [String]
//一系列應該被識別的語言種類

var shouldReportPartialResults: Bool
//是否獲取每個語句的最終結果。

var taskHint: SFSpeechRecognitionTaskHint
//正在執行的語音識別的型別

var interactionIdentifier: String?
//標識與請求關聯的識別請求物件的字串
  • 子類
    • SFSpeechURLRecognitionRequest
    • SFSpeechAudioBufferRecognitionRequest

2-1. SFSpeechURLRecognitionRequest

  • 通過制定的URL路徑識別本地的語音
  • 方法和屬性
//建立一個語音識別請求,使用指定的URL進行初始化
public init(url URL: URL)

//獲取當前的usl路徑    
open var url: URL { get }

2-2. SFSpeechAudioBufferRecognitionRequest

  • 識別音訊緩衝區中提供的語音的請求
  • 識別即時語音, 類似於iPhone 中的Siri
  • 官方文件
  • 音訊緩衝區相關方法屬性
func append(AVAudioPCMBuffer)
//將PCM格式的音訊追加到識別請求的末尾。

func appendAudioSampleBuffer(CMSampleBuffer)
//將音訊附加到識別請求的末尾。

func endAudio()
//完成輸入

  • 獲取音訊格式
var nativeAudioFormat: AVAudioFormat
//用於最佳語音識別的首選音訊格式。

3. SFSpeechRecognitionTask

  • 語音識別請求結果類
  • 語音識別任務,監視識別進度
  • 相關方法屬性
func cancel()
//取消當前的語音識別任務。

var isCancelled: Bool
//語音識別任務是否已被取消。

func finish()
//停止接受新的音訊,並完成已接受的音訊輸入處理

var isFinishing: Bool
//音訊輸入是否已停止。

var state: SFSpeechRecognitionTaskState
//獲取語音識別任務的當前狀態。

var error: Error?
//在語音識別任務期間發生的錯誤的錯誤物件。

3-1. SFSpeechRecognitionTaskDelegate協議

//當開始檢測音訊源中的語音時首先呼叫此方法
optional public func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask)

//當識別出一條可用的資訊後 會呼叫
//apple的語音識別服務會根據提供的音訊源識別出多個可能的結果 每有一條結果可用 都會呼叫此方法
optional public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription)

//當識別完成所有可用的結果後呼叫
optional public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult)

//當不再接受音訊輸入時呼叫 即開始處理語音識別任務時呼叫   
optional public func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask)

//當語音識別任務被取消時呼叫    
optional public func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask)

//語音識別任務完成時被呼叫    
optional public func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool)

4. SFTranscription

  • 語音轉換後的資訊類, 包含改短語音資訊的類
  • 你所說的一句話,可能是有好幾個詞語拼成的,formattedString就是你所說的那句話,segments就是你所說的你那句話的組成每個單詞的集合
//返回了一條表達語音譯文的字元資料
open var formattedString: String { get }

//所有的可能的識別資料
open var segments: [SFTranscriptionSegment] { get }

5. SFTranscriptionSegment

  • 語音轉換中的音訊節點類
  • 相關屬性
//當前節點識別後的文字資訊
open var substring: String { get }

//當前節點識別後的文字資訊在整體識別語句中的位置
open var substringRange: NSRange { get }

//當前節點的音訊時間戳
open var timestamp: TimeInterval { get }

//當前節點音訊的持續時間
open var duration: TimeInterval { get }

//可信度/準確度 0-1之間
open var confidence: Float { get }

//關於此節點的其他可能的識別結果 
open var alternativeSubstrings: [String] { get }

6. SFSpeechRecognitionResult: 語音識別結果類

  • 是語音識別結果的封裝,其中包含了許多套平行的識別資訊,其每一份識別資訊都有可信度屬性來描述其準確程度
  • 該類只是語音識別結果的一個封裝,真正的識別資訊定義在SFTranscription類中
//準確性最高的識別例項
@NSCopying open var bestTranscription: SFTranscription { get }

//識別到的多套語音轉換資訊陣列 其會按照準確度進行排序
open var transcriptions: [SFTranscription] { get }

//是否已經完成 如果YES 則所有所有識別資訊都已經獲取完成
open var isFinal: Bool { get }

三. 語音識別轉文字

  • 新增Speech框架
    • import Speech
  • info.plist必須新增相關許可權
Privacy - Speech Recognition Usage Description
//語音識別許可權

Privacy - Microphone Usage Description
//麥克風使用許可權
  • 判斷使用者授權
    • 在使用speech framework做語音識別之前,你必須首先得到使用者的允許
    • 因為不僅僅只有本地的ios裝置會進行識別,蘋果的伺服器也會識別
    • 所有的語音資料都會被傳遞到蘋果的後臺進行處理
    • 因此,獲取使用者授權是強制必須的
///語音識別許可權認證
fileprivate func addSpeechRecordLimit(){
    SFSpeechRecognizer.requestAuthorization { (state) in
        var isEnable = false
        switch state {
        case .authorized:
            isEnable = true
            print("已授權語音識別")
        case .notDetermined:
            isEnable = false
            print("沒有授權語音識別")
        case .denied:
            isEnable = false
            print("使用者已拒絕訪問語音識別")
        case .restricted:
            isEnable = false
            print("不能在該裝置上進行語音識別")
        }
        DispatchQueue.main.async {
            self.recordBtn.isEnabled = isEnable
            self.recordBtn.backgroundColor = isEnable ? UIColor(red: 255/255.0, green: 64/255.0, blue: 64/255.0, alpha: 1) : UIColor.lightGray
        }
    }
}



附錄:

AVSpeechSynthesisVoice支援的語言種類

         ar-SA  沙烏地阿拉伯(阿拉伯文)

         en-ZA, 南非(英文)

         nl-BE, 比利時(荷蘭文)

         en-AU, 澳大利亞(英文)

         th-TH, 泰國(泰文)

         de-DE, 德國(德文)

         en-US, 美國(英文)

         pt-BR, 巴西(葡萄牙文)

         pl-PL, 波蘭(波蘭文)

         en-IE, 愛爾蘭(英文)
         
         el-GR, 希臘(希臘文)

         id-ID, 印度尼西亞(印度尼西亞文)

         sv-SE, 瑞典(瑞典文)

         tr-TR, 土耳其(土耳其文)

         pt-PT, 葡萄牙(葡萄牙文)

         ja-JP, 日本(日文)

         ko-KR, 南朝鮮(朝鮮文)

         hu-HU, 匈牙利(匈牙利文)

         cs-CZ, 捷克共和國(捷克文)

         da-DK, 丹麥(丹麥文)

         es-MX, 墨西哥(西班牙文)

         fr-CA, 加拿大(法文)

         nl-NL, 荷蘭(荷蘭文)

         fi-FI, 芬蘭(芬蘭文)
         
         es-ES, 西班牙(西班牙文)

         it-IT, 義大利(義大利文)

         he-IL, 以色列(希伯萊文,阿拉伯文)

         no-NO, 挪威(挪威文)

         ro-RO, 羅馬尼亞(羅馬尼亞文)

         zh-HK, 香港(中文)

         zh-TW, 臺灣(中文)

         sk-SK, 斯洛伐克(斯洛伐克文)

         zh-CN, 中國(中文)

         ru-RU, 俄羅斯(俄文)

         en-GB, 英國(英文)

         fr-FR, 法國(法文)
         
         hi-IN  印度(印度文)

相關文章