Swift-语音识别、翻译

2019-03-20  本文已影响0人  oymuzi

前言

可能很多人都没去注意手机的语音识别功能,基本的键盘都具备了此功能,他的位置其实也很明显,可是用的人不多。估计是因为中国人太喜欢那个双手停不下来的打字的淋漓酣畅的感觉吧,再不然就是直接使用语音通话、语音消息,视频电话,所以这个功能在手机上的存在感很低。

image

图中原话是:到達できないものはすべて存在するものを持っている必要があります
正宗翻译是:凡不能人到的事物,必定有必能有将必存在
还是有点区别的

但是呢跟今天探讨的语音识别功能自然也很成熟,但是作者想到了可以体验一下说外国语识别出来的效果以及看下外国字,顺便想到了翻译的功能,就做了一个demo,实时识别-实时翻译。听起来很wanderfull是不是,但是呢,只是一个小把戏,系统提供了接口,翻译接口使用的是词霸的接口(仅仅学习,所以想玩的可以找个更好的接口),开始进入正题吧。

本地化

为啥玩语音识别还要附带这个玩意,其实很简单,就像之前在某音上看的。各个国家有各个国家的国歌,和某地的语言像极了鸟语。方言太多了,所以要统一语言,说出的话大家理解的都是同一份意思,这是小的,对于全球这么多国家,需要的是尊重各个国家的文化和历史,所以语言也是喽。
语音识别就像是一个倾听者,他工作的时候必须和你在同一个频道上,才能正确识别的你的话语。Locale是一个本地化类,相信大家在很多地方都看到这个类的踪影,其实也就是包含当地的语言,货币,货币符号,语言代码等等之类的。iOS系统支持的语言有目前797种,可以提供识别的语言有63种,其中分地区语言的,如zh_CNzh_HKzh_TW

/** 可用的标识符*/
        let identifiers = Locale.availableIdentifiers
        let allLocales = identifiers.map { (identifier) -> OMLocale in
            let local = Locale(identifier: identifier)
            let languageName = Locale.current.localizedString(forLanguageCode: identifier)
            let currencySymbol = local.currencySymbol
            let currencyCode = local.currencyCode
            let languageIdentifier = "\(local.languageCode ?? "")-\(local.regionCode ?? "")"
            let detail = "货币代号:\(currencyCode ?? "")   货币符号:\(currencySymbol ?? "")"
            return OMLocale.init(title: languageName ?? "", detailTitle: detail, languageIdentifier: languageIdentifier)
            }
        tipLabel.text = "当前系统共支持\(allLocales.count)种语言,但是由于语音识别只支持\(supportRecognitionLanuages.count)种语言,故只展示支持识别语言"
        locales = allLocales.filter({ (local) -> Bool in
            print(local.languageIdentifier)
            return supportRecognitionLanuages.contains(local.languageIdentifier)
        })

语音识别

我诉说心肠说系统听并理解,那么肯定需要两个权限,一个是耳朵(麦克风)、另一个是大脑(语音识别)。其中语音识别权限字段可能不是很清楚:Privacy - Speech Recognition Usage Description

private var speechRecognizer: SFSpeechRecognizer? = SFSpeechRecognizer.init(locale: Locale(identifier: "en-US"))
private var speechRecognitionRequest: SFSpeechAudioBufferRecognitionRequest?
private var speechRecognitionTask: SFSpeechRecognitionTask?
private var audioEngine: AVAudioEngine = AVAudioEngine.init()

使用音频引擎开始监听输入数据,并把数据添加到变化的识别请求中,语音识别通过识别任务来进行一个识别结果的回,就可以拿到识别的结果。听起来很简单,事实也就是这么简单。

 let audioSession = AVAudioSession.sharedInstance()
 try audioSession.setCategory(.record, mode: .measurement)
 try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
 speechRecognitionRequest = SFSpeechAudioBufferRecognitionRequest.init()
        guard let speechRecognitionRequest = speechRecognitionRequest else {
            fatalError("The Audio can't create SFSpeechAudioBufferRecognitionRequest object")
        }
        speechRecognitionRequest.shouldReportPartialResults = true
        speechRecognitionTask = speechRecognizer?.recognitionTask(with: speechRecognitionRequest) { (result, error) in
            var isFinished = false
            if let result = result {
                /**  调用翻译接口并把识别数据实时进行请求,来模拟实现实时翻译*/
                self.translation(string: result.bestTranscription.formattedString, identifier: self.identifier, completion: { [weak self] (translationResult) in
                    guard let `self` = self else { return }
                    DispatchQueue.main.async {
                        self.translationTextView?.text = translationResult
                    }
                })
                self.inputTextView?.text = result.bestTranscription.formattedString
                isFinished = result.isFinal
            }
            
            if error != nil || isFinished{
                self.audioEngine.stop()
                self.audioEngine.inputNode.removeTap(onBus: 0)
                
                self.speechRecognitionRequest = nil
                self.speechRecognitionTask = nil
                
                self.recordButton?.setTitle("Start Record", for: .normal)
                self.recordButton?.isEnabled = true
            }
        }
    let recordFormat = self.audioEngine.inputNode.outputFormat(forBus: 0)
    self.audioEngine.inputNode.installTap(onBus: 0, bufferSize: 1024, format: recordFormat, block: { (buffer, time) in
            self.speechRecognitionRequest?.append(buffer)
 })
        
 self.audioEngine.prepare()
 try self.audioEngine.start()

翻译

在上面的代码里已经使用了,之前提到用的是词霸的,索性把接口说下吧:

参数-f:输入语言的简写,默认为auto
参数-t:翻译语言的简写,默认为auto
参数-w:需要翻译的内容 
http://fy.iciba.com/ajax.php?a=fy&f=auto&t=auto&w=text

结果返回的样式大概是这样的,为了简单明了,手动调整的,其中out就是翻译结果,ciba_use就是被翻译的内容:

{
  "status":1,
  "content":{
    "from":"zh-CN",
    "to":"en",
    "vendor":"tencent",
    "out":"It's a nice day.",
    "ciba_use":"\u6765\u81ea\u673a\u5668\u7ffb\u8bd1\u3002",
    "ciba_out":"",
    "err_no":0
  }
}

结语

这个demo呢,就是识别中文还是挺准的,英文也挺准的,其他的日语、俄罗斯语什么的呀,一顿哈赛就行了,反正我也认不出来(翻译也不一定靠谱的,毕竟这个翻译不是很准的哦)。就是那个标点符号么有,我不知道是我手机的问题,还是我的英语太烂了。

这篇文章就这么结束了?作者水平也太low了吧,😝结束了,这个呢只是一时兴起写的一个demo,记录一下,客官不必太在意。

上一篇下一篇

猜你喜欢

热点阅读