1. 程式人生 > >iOS語音聽寫、語音合成

iOS語音聽寫、語音合成

本文語音聽寫以及語音合成基於訊飛科技提供的sdk

根據官方文件,下載sdk,建立自己的應用,獲取appid。

sdk放進自己的工程裡面,然後新增需要的庫。

編譯一下 ,如果編譯報錯,修改Targets -》 Build Settings -》Build Options -》Enable Bitcode 設定為No  編譯通過,sdk環境整合成功。

在程式入口,配置使用者資訊:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    NSString *initString = [[NSString alloc] initWithFormat:@"appid=%@",@"000000"];//此處填寫自己申請應用的appId
    [IFlySpeechUtility createUtility:initString];
}

一、語音合成,也就是閱讀文字,把文字訊息轉化成語音輸出:

1.匯入相關的標頭檔案

#import <iflyMSC/IFlySpeechSynthesizerDelegate.h>
#import <iflyMSC/IFlySpeechSynthesizer.h>
#import <iflyMSC/IFlySpeechConstant.h>
2.控制器遵守協議 ,實現協議回撥方法:
@interface ViewController ()<IFlySpeechSynthesizerDelegate>

@property (strong, nonatomic) IFlySpeechSynthesizer *synthesizer;
@property (nonatomic , strong) UITextView *textView;
@property (nonatomic , strong) UIButton *startBtn;
@property (nonatomic , strong) UIButton *cancelBtn;

@end

3.建立文字識別物件,
    self.synthesizer = [IFlySpeechSynthesizer sharedInstance];
    self.synthesizer.delegate = self;

並可以自定義設定該物件的關鍵屬性,不設定將會是預設值
    [self.synthesizer setParameter:@"50" forKey:[IFlySpeechConstant SPEED]];
    
    [self.synthesizer setParameter:@"50" forKey:[IFlySpeechConstant VOLUME]];
    
    [self.synthesizer setParameter:@"VIXR" forKey:[IFlySpeechConstant VOICE_NAME]];
    
    [self.synthesizer setParameter:@"8000" forKey:[IFlySpeechConstant SAMPLE_RATE]];
    
    [self.synthesizer setParameter:@"temp.pcm" forKey:[IFlySpeechConstant TTS_AUDIO_PATH]];
    
    [self.synthesizer setParameter:@"custom" forKey:[IFlySpeechConstant PARAMS]];

4.功能啟動的呼叫方法
- (void)startBtnCliked {
    [self.synthesizer startSpeaking:self.textView.text];
}
5.實現協議的方法:
- (void)onCompleted:(IFlySpeechError *)error {
    NSLog(@"講完了");
}
這樣簡單的語音合成就實現了。


二、語音識別,將語音翻譯成文字訊息。

sdk中提供了兩種方式,一種是帶介面的語音識別,也就是有一個小話筒的介面效果。另一種是無介面的。

先說有介面的,也比較簡單。

1.匯入標頭檔案

#import "iflyMSC/IFlyMSC.h"
#import "ISRDataHelper.h"

2.遵守協議
@interface ViewController ()<IFlyRecognizerViewDelegate> {
    IFlyRecognizerView *_iflyRecognizerView;
}

@property (nonatomic , strong) UITextView *textView;
@property (nonatomic , strong) UIButton *startBtn;
@property (nonatomic , strong) UIButton *cancelBtn;

@end

3.建立物件
    _iflyRecognizerView = [[IFlyRecognizerView alloc] initWithCenter:self.view.center];
    _iflyRecognizerView.delegate = self;
    [_iflyRecognizerView setParameter: @"iat" forKey: [IFlySpeechConstant IFLY_DOMAIN]];
    [_iflyRecognizerView setParameter:@"asrview.pcm " forKey:[IFlySpeechConstant ASR_AUDIO_PATH]];

4.開始語音識別
- (void)startBtnCliked {
    [_textView resignFirstResponder];
    //啟動識別服務
    [_iflyRecognizerView start];
}

5.實現代理回撥,處理識別的結果
/*識別結果返回代理
 @param resultArray 識別結果
 @ param isLast 表示是否最後一次結果
 */
- (void)onResult: (NSArray *)resultArray isLast:(BOOL) isLast
{
    NSMutableString *resultString = [[NSMutableString alloc] init];
    NSDictionary *dic = resultArray[0];
    for (NSString *key in dic) {
        [resultString appendFormat:@"%@",key];
    }
    NSString * resultFromJson =  [ISRDataHelper stringFromJson:resultString];
    _textView.text = [NSString stringWithFormat:@"%@%@", _textView.text,resultFromJson];
}


/*識別會話錯誤返回代理
 @ param  error 錯誤碼
 */
- (void)onError: (IFlySpeechError *) error
{
    NSLog(@"%s",__func__);
    
    NSString *text ;
    
    if (error.errorCode ==0 ) {
        
    }
    else
    {
        text = [NSString stringWithFormat:@"發生錯誤:%d %@",error.errorCode,error.errorDesc];
        NSLog(@"%@",text);
        [_iflyRecognizerView cancel];
    }
    
    self.startBtn.enabled = YES;
}

然後是不帶介面的語音識別。

1.同樣匯入標頭檔案

#import <iflyMSC/IFlySpeechRecognizerDelegate.h>
#import <iflyMSC/IFlySpeechRecognizer.h>
#import <iflyMSC/IFlySpeechError.h>
#import "ISRDataHelper.h"

2.建立物件 遵守協議
@interface ViewController ()<IFlySpeechRecognizerDelegate>

@property (nonatomic , strong) IFlySpeechRecognizer *iFlySpeechRecognizer;
@property (nonatomic , strong) UITextView *textView;
@property (nonatomic , strong) UIButton *startBtn;
@property (nonatomic , strong) UIButton *cancelBtn;

@end

    self.iFlySpeechRecognizer = [IFlySpeechRecognizer sharedInstance];
    self.iFlySpeechRecognizer.delegate = self;

3.按鈕方法,功能啟動入口
- (void)startBtnCliked {
    BOOL ret = [self.iFlySpeechRecognizer startListening];
    if (ret) {
        NSLog(@"成功");
    } else {
        NSLog(@"啟動失敗");
    }
}

- (void)cancelBtnCliked {
    [self.iFlySpeechRecognizer cancel];
}

4.實現代理回撥方法
- (void) onError:(IFlySpeechError *)errorCode {
    NSLog(@"%@",errorCode.errorDesc);
}

- (void) onResults:(NSArray *) results isLast:(BOOL)isLast {
    NSMutableString *resultString = [[NSMutableString alloc] init];
    NSDictionary *dic = results[0];
    for (NSString *key in dic) {
        [resultString appendFormat:@"%@",key];
    }
    NSString * resultFromJson =  [ISRDataHelper stringFromJson:resultString];
    _textView.text = [NSString stringWithFormat:@"%@%@", _textView.text,resultFromJson];
}

這個ISRDataHelper是訊飛demo裡面封裝好的一個類,用來處理翻譯過來的文字。實際上可以這樣解析預設的json串:
- (void) onResults:(NSArray *) results isLast:(BOOL)isLast {
    
    NSArray * temp = [[NSArray alloc]init];
    NSString * str = [[NSString alloc]init];
    NSMutableString *result = [[NSMutableString alloc] init];
    NSDictionary *dic = results[0];
    for (NSString *key in dic) {
        [result appendFormat:@"%@",key];
        
    }
    NSLog(@"聽寫結果:%@",result);
    //---------訊飛語音識別JSON資料解析---------//
    NSError * error;
    NSData * data = [result dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"data: %@",data);
    NSDictionary * dic_result =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];
    NSArray * array_ws = [dic_result objectForKey:@"ws"];
    //遍歷識別結果的每一個單詞
    for (int i=0; i<array_ws.count; i++) {
        temp = [[array_ws objectAtIndex:i] objectForKey:@"cw"];
        NSDictionary * dic_cw = [temp objectAtIndex:0];
        str = [str  stringByAppendingString:[dic_cw objectForKey:@"w"]];
        NSLog(@"識別結果:%@",[dic_cw objectForKey:@"w"]);
    }
    NSLog(@"最終的識別結果:%@",str);
    //去掉識別結果最後的標點符號
    if ([str isEqualToString:@"。"] || [str isEqualToString:@"?"] || [str isEqualToString:@"!"]) {
        NSLog(@"末尾標點符號:%@",str);
    }
    else{
        self.textView.text = str;
    }
}

目前只整理了這兩個功能的程式碼,後續需要會再研究其他功能的程式碼。