iOS原生自带的离线语音识别---speech framework

    xiaoxiao2021-04-17  41

    这阵子公司一直想要搞个语音发送命令!本来科达讯飞用的好好的,但是!价格简直有点小贵了!!8000元人民币识别2000台机子!四元一台的成本,公司舍不得钱所以!!!:

    speech是iOS10.0新出的开源框架!如果你需要使用的话建议你先更新XCODE,swift也可以使用哟!不过我的项目没有用到swift,所以没有贴出来,总之!功能还是相当强大的!也很好用,不过此框架比较呆,只能使用本地的文件,很有局限性!而且我看网上很多教程基本都是识别的本地的文件!!! EXM? 很LOW有没有! 所以如果你的需求本不是一个.MP3 识别音乐中的内容的话!可以看下去!如果是只需要识别.MP3的话,看到语音识别就能满足你的需求了!

    speechframework可以识别出MP3的语音。而且仅仅只能识别.MP3文件这种本地的音频文件(可播放的那种),但是我们需要的功能是识别麦克风自己说话的声音,所以还需要先获取麦克风的声音,使用AVAudioRecorder或许到本地的音频数据流。用AVAudioSession进行录制,再将录制得到的caf数据流转成MP3格式!存入字典上次本地的文件: 

    MP3生成成功: /var/mobile/Containers/Data/Application/5E32CD4F-6644-40BD-8AC7-6AC9836A65DD/Documents/myRecord.mp3

    需要注意的是URL的使用方式不能用write!下面这种是识别不出来的:

     [NSURL URLWithString:Str];

    以下两种是可行的URL:

     1.NSURL *url = [[NSBundle mainBundle] URLForResource:@"你好.mp3" withExtension:nil];

     2.NSURL *url= [NSURL fileURLWithPath:self.mp3PathStr];

    分享一段CAF转MP3代码免走弯路:

      @try {

            int read, write;

            

            FILE *pcm = fopen([self.cafPathStr cStringUsingEncoding:1], "rb");  //source被转换的音频文件位置

            fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header

            FILE *mp3 = fopen([self.mp3PathStr cStringUsingEncoding:1], "wb");  //output输出生成的Mp3文件位置

            

            const int PCM_SIZE = 8192;

            const int MP3_SIZE = 8192;

            short int pcm_buffer[PCM_SIZE*2];

            unsigned char mp3_buffer[MP3_SIZE];

            

            lame_t lame = lame_init();

            lame_set_in_samplerate(lame, 11025.0);

            lame_set_VBR(lame, vbr_default);

            lame_init_params(lame);

            

            do {

                read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);

                if (read == 0)

                    write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);

                else

                    write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);

                

                fwrite(mp3_buffer, write, 1, mp3);

                

            } while (read != 0);

            

            lame_close(lame);

            fclose(mp3);

            fclose(pcm);

        }

        @catch (NSException *exception) {

            NSLog(@"%@",[exception description]);

    }

        }

        @finally {

            NSLog(@"MP3生成成功: %@",self.mp3PathStr);

    开发者若要在自己的App中使用语音识别功能,需要获取用户的同意。首先需要在工程的Info.plist文件中添加一个Privacy-Speech Recognition Usage Description键,其实需要对应一个String类型的值,这个值将会在系统获取权限的警告框中显示,Info.plist文件中。使用SFSpeechRecognize类的requestAuthorization方法来进行用户权限的申请,用户的反馈结果会在这个方法的回调block中传入。

    //申请用户语音识别权限

    [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) { 

    }];

      如果申请用户语音识别权限成功,开发者可以通过SFSpeechRecognizer操作类来进行语音识别请求,示例如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    //创建语音识别操作类对象

    SFSpeechRecognizer * rec = [[SFSpeechRecognizer alloc]init];

    //通过一个音频路径创建音频识别请求

    SFSpeechRecognitionRequest * request = [[SFSpeechURLRecognitionRequest alloc]initWithURL:[[NSBundle mainBundle] URLForResource:@"7011" withExtension:@"m4a"]];

    //进行请求

    [rec recognitionTaskWithRequest:request resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {

     //打印语音识别的结果字符串

     NSLog(@"%@",result.bestTranscription.formattedString);

    }];

    测试代码,发现会出现自动识别多个。有汉字数字各种!反复测试代码,猜测原因有两个

    1.代码重复:传过来的MP3文件出现多次传入的问题  

    2.识别多次:框架会自动识别几个。

    // A recognized utterance, corresponding to a segment of recorded audio with speech and containing one 

    API_AVAILABLE(ios(10.0))

    @interface SFSpeechRecognitionResult :NSObject <NSCopying,NSSecureCoding>

    @property (nonatomic,readonly, copy) SFTranscription*bestTranscription;  //按升序识别,从识别的最好的开始!

    // Hypotheses for possible transcriptions, sorted in decending order of confidence (more likely first)

    @property (nonatomic,readonly, copy)NSArray<SFTranscription *>*transcriptions;     //按降序识别。

    // True if the hypotheses will not change; speech processing is complete.

    @property (nonatomic,readonly, getter=isFinal)BOOL final;//判断是否是最终完成的语音识别

    进行判断  

      if (result.isFinal)即可!

    至此离线语音识别已经完成!

    后期代码我会板上来的!因为项目还在做,有需要的可以加群!群号:622492955  !

    转载请注明原文地址: https://ju.6miu.com/read-673355.html

    最新回复(0)