iOS 集成文档
最近更新时间:2023-06-26 15:35:11 前往 Coding 编辑 导出文档
语音命令(commands)
要开始在iOS上使用语音命令,我们建议您下载SpeechRecognition。
功能介绍
SpeechRecognition 是一个语音命令识别应用程序,演示了如何在iOS上使用PyTorch C++库。该代码是用Objective-C编写。
要求
- Xcode 12.4 or later
- iOS 12.0或更高版本
- iOS Cocoapods LibTorch-Lite 1.13.0.1
集成步骤
1.准备模型
将模型文件speechcommand-demo.ptl
保存到SpeechRecognition
文件夹。
模型下载地址
https://qpt-dev-voices-1251626569.cos.ap-beijing.myqcloud.com/ican/speechcommand-demo.ptl
2.通过Cocoapods安装LibTorch-Lite
要将PyTorch C++库集成到我们的项目中,只需运行
在Podfile中引用
pod 'LibTorch-Lite', '~>1.13.0'
执行
pod install
然后在XCode中打开SpeechRecognition.xcworkspace
,选择一个iOS模拟器并启动它(cmd + R)。如果一切顺利,我们应该在模拟器屏幕上看到录音识别页面。
代码简介
在这一部分中,我们将逐步完成代码。
模型
将模型加载到应用程序中。
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"speechcommand-demo" ofType:@"ptl"];
if (filePath) {
m_module = [[ForwardModule alloc] initWithFileAtPath:filePath];
messageLog = [messageLog stringByAppendingString:@"模型加载成功 \n"];
}else {
messageLog = [messageLog stringByAppendingString:@"找不到模型文件!\n"];
}
请注意,ForwardModule
类是torch::jit::mobile::Module
的Objective-C包装器。
torch::jit::mobile::Module module = torch::jit::_load_for_mobile(filePath.UTF8String);
由于Swift不能直接与C++交谈,必须使用Objective-C类作为桥接器,或者为C++库创建C包装器。为了演示,我们将在这个Objective-C类中包装所有内容。
静音检测
获取音频输入语音流,通过_vad
逐帧检测是否静音,如果满足有效的音频条件,就会进行识别
1s 16K采样率 16位 单声道的音频所采集数据大小为 1s -> 16000 * 16 * 1 = 256000bit = 32000 byte = 16000 short
正常的音频传输为 20ms 一帧,即 20ms -> 640 byte -> 320 short
//检测是否静音
int voice = 0;
voice = [_vad isVoice:&stateInp.audioBufferI16[buffIndex * 320] sample_rate:16000 length:320];
buffIndex += 1;
if(voice == 1){
muteTempCount = 0;
soundCount += 1;
isContainSpeechBuffer = true;
}else{
muteTempCount += 1;
//持续0.5s没有声音,认为当前是 静音 状态 (25: 25帧 -> 25 * 320 short -> 0.5s)
if(muteTempCount >= 25){
if(isContainSpeechBuffer){
//语音最少时长为0.3s认为是有效时长 (16000 * 0.3)
if(soundCount * 320 >= 16000 * 0.3){
[self onTranscribe];
}
}
muteTempCount = 0;
soundCount = 0;
return;
}
}
语音命令识别
进行语音命令识别并获得结果。
NSString *result = [self->m_module recognize: self->stateInp.audioBufferF32 bufLength:self->stateInp.n_samples];
recognize
方法只是一个Objective-C包装器。在引擎盖下,它调用C++forward
函数。实现方法如下:
at::Tensor tensorInputs = torch::from_blob((void*)wavBuffer, {1, bufLength}, at::kFloat);
float* floatInput = tensorInputs.data_ptr<**float**>();
if (!floatInput) {
return nil;
}
NSMutableArray* inputs = [[NSMutableArray alloc] init];
for (int i = 0; i < bufLength; i++) {
[inputs addObject:@(floatInput[i])];
}
c10::InferenceMode guard;
CFTimeInterval startTime = CACurrentMediaTime();
auto result = _impl.forward({ tensorInputs }).toStringRef();
C++函数torch::from_blob
将从wav缓冲区创建一个输入Tensor。
c10::InferenceMode guard;
最后,调用这个forward
函数来获取语音命令识别结果。
auto result = _impl.forward({ tensorInputs }).toStringRef();