-->

9Implementing Nuance Speech Recognition on Swift,

2020-02-13 06:03发布

问题:

I have two parts of my Speech Recon project with Nuance, the .h file of a module (ObjectiveC) and aViewController (swift).

I want to set up aSpeechRecognition object in my swiftviewController, and listen to onBegin, onStop... and such methods.

The only way to make it compile is to use nil as the delegate parameter to initialize the SpeechRecon object. Obviously this is not good because my onStart... and onFinish functions don´t trigger.

I have implemented a protocol to theSKRecogniser file, and extended my ViewController class to SKReconDelegate... but if I use "self" as a delegate to initialize object, the compiler will say thatUIViewController is not a valid class. I know I need to establish some delegate between both classes, but I am an android developers, and my iOS skills are still not sharp enough. Here is the code, if I missed some important piece just let me know. I will be very thankful for your help.

//ViewController code, in SWIFT
//NO PROTOCOLS NEEDED HERE!

class ViewController:  UIViewController, SpeechKitDelegate, SKRecognizerDelegate{

override func viewDidLoad() {
        super.viewDidLoad()
        SpeechKit.setupWithID( "NMDPTRIAL_nuance_chch_com9999",
            host:"sandbox.nmdp.nuancemility.net",
            port:443,
            useSSL:false,
            delegate:self) //error said "self" is of an invalid ViewController type :( because I was NOT implementing all 4 methods BELOW:
   }
//a bit ahead, I have the same problem with a button
@IBAction func btnmicaction(sender: AnyObject) {
   self.voiceSearch=SKRecognizer(type: "websearch", detection: 2, language: langType as String, delegate: self) //error said "self" is of an invalid ViewController type :( because I was NOT implementing all 4 methods BELOW:
   }


//IMPLEMENT ALL THESE 4 FUNCTIONS, AS SUGGESTED BY THE SOLUTION
func recognizerDidBeginRecording(recognizer:SKRecognizer){
        println("************** ReconBeganRecording")
        }

func recognizerDidFinishRecording(recognizer:SKRecognizer){
        println("************** ReconFinishedRecording")
        }

func recognizer(recognizer: SKRecognizer!, didFinishWithResults results: SKRecognition!){
    //The voice recognition process has understood something
    }

func recognizer(recognizer: SKRecognizer!, didFinishWithError error: NSError!, suggestion: String!){
   //an error has occurred
   }
}

Just in case, here is my Bridge header:

#ifndef Vanilla_Bridge_h
#define Vanilla_Bridge_h
#import <SpeechKit/SpeechKit.h>

UPDATE SEE SOLUTION BELOW!!

回答1:

Here's what I've got Bridging Header:

#import <SpeechKit/SpeechKit.h>
#import "NuanceHeader.h"

NuanceHeader.h:

#import <Foundation/Foundation.h>
@interface NuanceHeader : NSObject
@end

NuanceHeader.m

#import "NuanceHeader.h"
const unsigned char SpeechKitApplicationKey[] = {...};
@implementation NuanceHeader
@end

When it comes to the UIViewController that uses all this:

class MyViewController: UIViewController, SpeechKitDelegate, SKRecognizerDelegate
{
    var voiceSearch: SKRecognizer?

    override func viewDidLoad()
    {
       //Setup SpeechKit
       SpeechKit.setupWithID("...", host: "sandbox.nmdp.nuancemobility.net", port: 443, useSSL: false, delegate: self)
    }

    func someAction()
    {
        self.voiceSearch = SKRecognizer(type: SKSearchRecognizerType, detection: UInt(SKLongEndOfSpeechDetection), language:"eng-USA", delegate: self)

    }

    func recognizerDidBeginRecording(recognizer: SKRecognizer!)
    {
        //The recording has started
    }

    func recognizerDidFinishRecording(recognizer: SKRecognizer!)
    {
        //The recording has stopped
    }

    func recognizer(recognizer: SKRecognizer!, didFinishWithResults results: SKRecognition!)
    {
        //The voice recognition process has understood something
    }

    func recognizer(recognizer: SKRecognizer!, didFinishWithError error: NSError!, suggestion: String!)
    {
       //an error has occurred
    }
}

There is nothing else to it, check every step, this part is pretty straight forward



回答2:

Try let objCDelegate = self as SKRecognizerDelegate and then use objCDelegate as delegate parameter



回答3:

Since things have changed a bit I thought I would add my 2 cents:

 var listening = false
var transaction: SKTransaction?
var session: SKSession?

override func viewDidLoad() {
    super.viewDidLoad()

    session = SKSession(URL: NSURL(string: serverURL), appToken: appKey)

    let audioFormat = SKPCMFormat()
    audioFormat.sampleFormat = .SignedLinear16;
    audioFormat.sampleRate = 16000;
    audioFormat.channels = 1;

    print("\(NSHomeDirectory())/start.mp3")

    // Attach them to the session
    session!.startEarcon = SKAudioFile(URL: NSURL(fileURLWithPath: "\(NSHomeDirectory())/start.mp3"), pcmFormat: audioFormat)
    session!.endEarcon = SKAudioFile(URL: NSURL(fileURLWithPath: "\(NSHomeDirectory())/stop.mp3"), pcmFormat: audioFormat)

}

@IBAction func speechButtonDidClick(sender: AnyObject) {

    if listening == false {
        transaction = session?.recognizeWithType(SKTransactionSpeechTypeDictation,
                                                    detection: .Short,
                                                    language: "eng-USA",
                                                    delegate: self)

    }else{
        transaction?.stopRecording()
    }
}

// SKTransactionDelegate
func transactionDidBeginRecording(transaction: SKTransaction!) {
    messageText.text = "listening"
    listening = true
    indicator.startAnimating()
    startPollingVolume()
}
func transactionDidFinishRecording(transaction: SKTransaction!) {
    messageText.text = "stopped"
    listening = false
    indicator.stopAnimating()
    stopPollingVolume()
}

func transaction(transaction: SKTransaction!, didReceiveRecognition recognition: SKRecognition!) {

    print("got something")

    //Take the best result
    if recognition.text != nil{
        speechTextField.text = recognition.text
    }
}
func transaction(transaction: SKTransaction!, didReceiveServiceResponse response: [NSObject : AnyObject]!) {
    print ("service response")
    print(response)
}
func transaction(transaction: SKTransaction!, didFinishWithSuggestion suggestion: String!) {
}
func transaction(transaction: SKTransaction!, didFailWithError error: NSError!, suggestion: String!) {
    print ("error")
    print(error)
}


var timer = NSTimer()
var interval = 0.01;

func startPollingVolume() {
    timer = NSTimer.scheduledTimerWithTimeInterval(interval,
                                                   target: self,
                                                   selector: #selector(ViewController.pollVolume),
                                                   userInfo: nil,
                                                   repeats: true)
}

func pollVolume() {
    if transaction != nil{
        let volumeLevel:Float = transaction!.audioLevel
        audioLevelIndicator.progress = volumeLevel / 90
    }
}

func stopPollingVolume() {
    timer.invalidate()
    audioLevelIndicator.progress = 0
}

hope this helps someone!