音频录制和Speech语音识别(ios10)
之前做的项目中有语音识别的需求, 是用讯飞语音SDK实现的。 有很多服务商提供声音转文字的服务,有收费的有免费。
2016年苹果在发布的上iOS10增加了一个语音识别功能,并且将其封装到了SpeechFramework库中。苹果手机上Siri的语音识别就是基于Speech实现的。
下面就开始动手敲代码实践录音和Speech的用法吧
1. 引入Speech 和AVFoundation
#import // 录音
#import // 语音识别
2. 申请用户权限
想要使用录音和语音识别功能必须先配置info.plist文件,在其中增加麦克风和语音识别授权属性
NSMicrophoneUsageDescription
App需要您的同意,才能使用麦克风
NSSpeechRecognitionUsageDescription
App需要您的同意,才能使用语音识别
加完之后是这样的
3. 录音
激活AVAudioSession
_session = [AVAudioSession sharedInstance];
NSError *categoryError = nil;
//设置为播放和录音状态,以便可以在录制完之后播放录音
[_session setCategory:AVAudioSessionCategoryPlayAndRecord error:&categoryError];
if (_session) {
[_session setActive:YES error:nil]; // 此处手动激活
}
else {
NSLog(@"Error creating session: %@",[categoryError description]);
}
创建录音器, 设置代理(可以监听录制的状态)
- (void)createAudioRecorder
{
// 实例化录音器对象
NSError *errorRecord = nil;
_recorder = [[AVAudioRecorder alloc] initWithURL:[NSURL fileURLWithPath:_filePath] settings:[self getAudioSetting] error:&errorRecord];
_recorder.delegate = self;
_recorder.meteringEnabled = YES; //如果要监控声波则必须设置为YES
// 准备录音
[_recorder prepareToRecord];
}
实例化录音对象, 要设置音频的编码参数
- (NSDictionary *)getAudioSetting
{
//录音设置
NSMutableDictionary *recordSettings = [[NSMutableDictionary alloc] init];
//音频质量,采样质量
[recordSettings setValue:[NSNumber numberWithInt:AVAudioQualityMax] forKey:AVEncoderAudioQualityKey];
//通道数 编码时每个通道的比特率
[recordSettings setValue:[NSNumber numberWithInt:2] forKey: AVNumberOfChannelsKey];
//录音格式 无法使用
// [recordSettings setValue:[NSNumber numberWithInt:kAudioFormatLinearPCM] forKey: AVFormatIDKey];
//LinearPCM 是iOS的一种无损编码格式,但是体积较为庞大
//采样率
[recordSettings setValue:[NSNumber numberWithFloat:44100.0] forKey: AVSampleRateKey];//44100.0
//线性采样位数
[recordSettings setValue:[NSNumber numberWithInt:32] forKey: AVLinearPCMBitDepthKey];
// 编码时的比特率,是每秒传送的比特(bit)数单位为bps(Bit Per Second),比特率越高传送数据速度越快值是一个整数
[recordSettings setValue:[NSNumber numberWithInt:128000] forKey:AVEncoderBitRateKey];
return recordSettings;
}
开始录制
- (void)recorderSoundStart:(NSString *)path
{
// 停止播放
[self stopPlayRecorderSound];
// 停止之前的录音
if ([_recorder isRecording]) {
[_recorder stop];
}
// 删除旧的录音文件
[APPUtil deleteFile:path];
// 不删除也可以, 同一会路径下会被覆盖
if (!_recorder) {
// 实例化录音对象
[self createAudioRecorder];
}
if (![_recorder isRecording]){
[_recorder record];
// 设定 录制 最长时间 60s
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self recorderSoundEnd];
});
}
}
由于设置了最长录制时间60s, 所以要加上下面录制完成代理代码
#pragma mark - AVAudioRecorderDelegate 录音机代理方法
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
NSLog(@"录音完成!");
[self recorderSoundEnd];
}
停止录制 , 在停止录制之前, 可能会有暂停录制,此处略过
- (void)recorderSoundEnd
{
// 停止录音
if ([_recorder isRecording]) {
[_recorder stop];
// [_recorder pause]; // 暂停录制
}
// 更新UI按钮
_recodeSound.selected = NO;
}
开始播放及停止播放
// 播放
- (void)recorderSoundPlay:(NSString *)path
{
// 先停止录音
if (_recorder) {
[_recorder stop];
}
if (!_player) {
// 创建播放器
[self createAudioPlayer];
}
[_session setCategory:AVAudioSessionCategoryPlayback error:nil];
// 播放
[_player play];
}
// 停止
- (void)stopPlayRecorderSound
{
if ([_player isPlaying]) {
[_player stop];
}
// 更新UI播放按钮
_playSound.selected = NO;
}
4. 语音识别
语音识别是iOS10增加的新特性,Xcode8之前的版本没有SpeechFramework库,所以此功能只能在Xcode8以上和iOS10以上运行。
请求语音识别权限
// 请求语音识别权限
[SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {
NSLog(@"status %@", status == SFSpeechRecognizerAuthorizationStatusAuthorized ? @"语音识别权限授权成功" : @"语音识别权限授权失败"); }];
所谓语音识别, 就是用户说话然后马上把用户说的话转成文字显示!这才是理想中的语音识别, 当然也是支持识别一个本地音频文件
打开Speech kit库,找到语音识别请求文件 SFSpeechRecognitionRequest.h, 发现 识别请求的API有两种 SFSpeechAudioBufferRecognitionRequest 和 SFSpeechURLRecognitionRequest 都继承于SFSpeechRecognitionRequest类
SFSpeechAudioBufferRecognitionRequest 实时识别音频流 也就是现说现译
SFSpeechURLRecognitionRequest 识别路径URL的音频文件
既然语音识别配置工作上面都已经做好了, 下面就看下这两种识别请求吧 ()
5. 语音识别--现说现译
激活AVAudioSession
_session = [AVAudioSession sharedInstance];
[_session setCategory:AVAudioSessionCategoryRecord mode:AVAudioSessionModeMeasurement options:AVAudioSessionCategoryOptionDuckOthers error:nil];
[_session setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
AVAudioSessionCategoryRecord : 设置录音(现说现译, 要录制说的话)
AVAudioSessionModeMeasurement:减少系统提供信号对应用程序输入和/或输出音频信号的影响
AVAudioSessionCategoryOptionDuckOthers: 在实时通话的场景,降低别的声音。比如QQ音乐,当进行视频通话的时候,会发现QQ音乐自动声音降低了,此时就是通过设置这个选项来对其他音乐App进行了压制
AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation:判断当前是否有其他App在播放音频
多媒体引擎的建立
- (void)createAudioEngine
{
if (!_speechRecognizer) {
// 设置语言
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"zh-CN"];
_speechRecognizer = [[SFSpeechRecognizer alloc] initWithLocale:locale];
}
// 初始化引擎
if (!_audioEngine) {
_audioEngine = [[AVAudioEngine alloc] init];
}
}
创建语音识别请求, 创建并开启语音识别任务
// 创建语音识别请求
- (void)createSpeechRequest
{
if (_speechRequest) {
[_speechRequest endAudio];
_speechRequest = nil;
}
_speechRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
_speechRequest.shouldReportPartialResults = YES; // 实时翻译
__weak typeof(self) weakSelf = self;
// 建立语音识别任务, 并启动. block内为语音识别结果回调
[_speechRecognizer recognitionTaskWithRequest:_speechRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
// 语音识别结果回调
__strong typeof(weakSelf) strongSelf = weakSelf;
if (error) {
NSLog(@"语音识别解析失败,%@",error);
}
else {
// 识别的内容
NSString *text = result.bestTranscription.formattedString;
// 实时打印说话的内容
NSLog(@"is final: %d result: %@", result.isFinal, result.bestTranscription.formattedString);
if (result.isFinal) { // 结束时 显示内容
// 显示说话的内容
strongSelf.content.text = text;
// 多次说话的内容拼接到一起显示
// strongSelf.content.text = [NSString stringWithFormat:@"%@%@", strongSelf.content.text, text];
}
}
}];
}
语音识别任务及回调结果有2中实现方法, 一种是代理, 一种block, 此处选择了block
// Recognize speech utterance with a request
// If request.shouldReportPartialResults is true, result handler will be called
// repeatedly with partial results, then finally with a final result or an error.
- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request
resultHandler:(void (^)(SFSpeechRecognitionResult * __nullable result, NSError * __nullable error))resultHandler;
// Advanced API: Recognize a custom request with with a delegate
// The delegate will be weakly referenced by the returned task
- (SFSpeechRecognitionTask *)recognitionTaskWithRequest:(SFSpeechRecognitionRequest *)request
delegate:(id )delegate;
开始语音识别
- (IBAction)stardRecorder:(UIButton *)sender
{
// 开始录音前清空显示的内容, 如果需要拼接多次录音的内容,不要清空,
_content.text = @"";
// 创建新的语音识别请求
[self createSpeechRequest];
__weak typeof(self) weakSelf = self;
// 录音格式配置 -- 监听输出流 并拼接流文件
AVAudioFormat *recordingFormat = [[_audioEngine inputNode] outputFormatForBus:0];
// 创建一个Tap,(创建前要先删除旧的)
// 文档注释: Create a "tap" to record/monitor/observe the output of the node.
[[_audioEngine inputNode] installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
__strong typeof(weakSelf) strongSelf = weakSelf;
// 拼接流文件
[strongSelf.speechRequest appendAudioPCMBuffer:buffer];
}];
// 准备并启动引擎
[_audioEngine prepare];
NSError *error = nil;
if (![_audioEngine startAndReturnError:&error]) {
NSLog(@"%@",error.userInfo);
};
[sender setTitle:@"语音识别中..." forState:UIControlStateNormal];
}
重置多媒体引擎
- (void)releaseEngine
{
// 销毁tap
[[_audioEngine inputNode] removeTapOnBus:0];
[_audioEngine stop];
[_speechRequest endAudio];
_speechRequest = nil;
}
到这里 现说现译-语音识别就完成了。
6. 语音识别--本地音频文件
这个需要个音频文件, 上面做的录音功能, 就可以录制语音caf文件, 那就直接在录音功能基础上, 加个语音识别吧。这样就集录制、播放、语音识别于一体了。
直接看代码
- (IBAction)speechSound:(UIButton *)sender
{
// 识别的录音文件是否存在
NSFileManager* manager = [NSFileManager defaultManager];
if (![manager fileExistsAtPath:_filePath]){
NSLog(@"音频文件不存在");
return ;
}
_speechContent.text = @"";
//转化过后的MP3文件位置
// NSString *mp3Path = [NSString stringWithFormat:@"%@/%@", [APPUtil speechPath], @"lame.mp3"];
// [APPUtil lameCafToMp3:_filePath mp3:mp3Path];
// [self speechSoundRecord:mp3Path]; // 语音识别失败
// 不转成mp3也可以 识别成功
[self speechSoundRecord:_filePath]; // 能识别成功
}
- (void)speechSoundRecord:(NSString *)path
{
// 设置语言中文
NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
SFSpeechRecognizer *localRecognizer =[[SFSpeechRecognizer alloc] initWithLocale:local];
NSURL *url = [NSURL fileURLWithPath:path];
if (!url) return;
SFSpeechURLRecognitionRequest *res =[[SFSpeechURLRecognitionRequest alloc] initWithURL:url];
__weak typeof(self) weakSelf = self;
[localRecognizer recognitionTaskWithRequest:res resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (error) {
NSLog(@"语音识别解析失败,%@",error);
}
else {
// 显示 识别的内容
NSString *text = result.bestTranscription.formattedString;
strongSelf.speechContent.text = text;
}
}];
}
历时一天半终于写完了实现录音和语音识别功能的代码 , 现在运行看下效果吧,
直接看图:
录音.png
语音识别.png
可以看到, 录音和语音识别功能, 除了识别内容会有些错别字, 效果还是挺完美的。
音频录制和Speech语音识别(ios10)相关推荐
- AVFoundation 文本转语音和音频录制 播放
现在你应该对AVFoundation有了比较深入的了解,并且对数字媒体的细节也有了一定认识,下面介绍一下 AVFoundation的文本转语音功能 AVSpeechSynthesizer 开发者可以使 ...
- .NET NAudio音频录制方法 2021-02-13
.NET NAudio音频录制方法 写在前面 文章主要内容 说明 检测录音电平 调节录音电平 开始录音 调整音频 保存音频 关于作者 讨论 SomeONe Clint Nate Greenwood C ...
- audiorecord怎么释放_Android 开发 AudioRecord音频录制
前言 Android SDK 提供了两套音频采集的API,分别是:MediaRecorder 和 AudioRecord,前者是一个更加上层一点的API,它可以直接把手机麦克风录入的音频数据进行编码压 ...
- 有关于iphone 音频 录制 播发
有关于iphone 音频 录制 播发 1,音频格式相关: http://www.raywenderlich.com/204/audio-101-for-iphone-developers-file-a ...
- Android多媒体学习八:调用Android自带的音频录制程序,实现录制
Android中有自带的音频录制程序,我们可以通过指定一个Action为MediaStore.Audio.Media.RECORD_SOUND_ACTION的Intent来 启动它就可以了.然后在on ...
- 如何进行音频录制?实用的音频录制方法合集
音频录制是一种重要的技能,可以用于各种场合,比如我们可以使用音频录制技术录制不同乐器和声音的音频,并在后期进行处理和混音,制作出完整的音乐作品等等.但是,要想录制出高质量的音频并不容易,需要掌握一些专 ...
- 如何录制音频文件mp3?给你推荐好用的几款音频录制软件
其实我们生活中对于音频录制的需求是比较大的,比如开会的时候为了防止漏掉要点,又或者在上课的时候老师语速过快我们来不及记笔记,这些情况出现的时候我们都可以用录音来解决这些问题.那今天在这里我也跟 ...
- android Q屏幕录制,设备音频录制无声
Android q 之后google添加了音频录制的api 在状态栏中可以开启录制功能. 使用中发现,选择音源为设备内部音频的时候,录制的视频无声. 内部音乐录制时android Q版本之后googl ...
- android AudioRecord 音频录制 噪音消除
android AudioRecord 音频录制 噪音消除 因为公司APP做适配,一些低端机的噪音比较严重,所以再一些低端机上做了简单除噪音功能, 1,由于APP使用场景的限制,所以一般噪音基本上都 ...
最新文章
- cpythonjava解释xml_详解python使用lxml操作xml格式文件
- 【Groovy】集合遍历 ( 使用 for 循环遍历集合 | 使用集合的 each 方法遍历集合 | 集合的 each 方法返回值分析 )
- 数据库开发——MySQL——数据的增删改查
- Java库可以软件著作权,(最新整理)软件著作权-源代码范本
- 调用python接口并画图_【PySpark源码解析】教你用Python调用高效Scala接口
- Codeforces 671C Ultimate Weirdness of an Array 线段树 (看题解)
- c语言模拟试题快速排序,快速排序(东软喜欢考类似的算法填空题,又如堆排序的算法等)...
- CubeMX 的使用实例详细(04.6)- STM32F103的 - 定时器设定 - callback调用 - 实现1S的定时更新LED灯
- poj 1325 Machine Schedule 解题报告
- axios.post请求出错:Request header field content-type is not allowed by Access-Control-Allow-Headers in……
- 非阻塞IO发送http请求
- Mysql表的过滤查询
- Java丨基础:十三、集合
- niceScroll相关配置参数
- 计算机毕业设计JAVA便利店系统mybatis+源码+调试部署+系统+数据库+lw
- 条令考试小程序辅助器_微信小程序条令考试刷分 微信小程序答题刷分软件
- 编出个区块链:数据结构的序列化,看看数字货币如何传输数据
- python 线程锁_Python线程锁的实现
- 网页生成pdf文件。(html转pdf)(带效果图)
- WCF学习经验分享,如何更好地学习WCF?