
2019-10-21 17.04.38.gif
權(quán)限

權(quán)限.png
開(kāi)始錄音
#pragma mark - 開(kāi)始錄音
- (void)startRecording{
[self.audioEngine stop];
if (_recognitionRequest) {
[_recognitionRequest endAudio];
}
if (_recognitionTask) {
[_recognitionTask cancel];
_recognitionTask = nil;
}
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
NSError *error;
[audioSession setCategory:AVAudioSessionCategoryRecord error:&error];
NSParameterAssert(!error);
[audioSession setMode:AVAudioSessionModeMeasurement error:&error];
NSParameterAssert(!error);
[audioSession setActive:YES withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
NSParameterAssert(!error);
if (@available(iOS 10.0, *)) {
_recognitionRequest = [[SFSpeechAudioBufferRecognitionRequest alloc] init];
} else {
// Fallback on earlier versions
}
AVAudioInputNode *inputNode = self.audioEngine.inputNode;
NSAssert(inputNode, @"錄入設(shè)備沒(méi)有準(zhǔn)備好");
NSAssert(_recognitionRequest, @"請(qǐng)求初始化失敗");
_recognitionRequest.shouldReportPartialResults = YES;
__weak typeof(self) weakSelf = self;
if (@available(iOS 10.0, *)) {
_recognitionTask = [self.speechRecognizer recognitionTaskWithRequest:_recognitionRequest resultHandler:^(SFSpeechRecognitionResult * _Nullable result, NSError * _Nullable error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
BOOL isFinal = NO;
if (result) {
NSString *resultString = result.bestTranscription.formattedString;
NSLog(@"resultString=%@",resultString);
if(resultString.length>0){
self.resultString=resultString;
self.viewTalk.resultString=self.resultString;
}
isFinal = result.isFinal;
//[strongSelf.viewTalk.threeWave changeAnimate];
}
if (error || isFinal) {
[self.audioEngine stop];
[inputNode removeTapOnBus:0];
strongSelf.recognitionTask = nil;
strongSelf.recognitionRequest = nil;
NSLog(@"(error || isFinal)=%@",error);
}
}];
} else {
// Fallback on earlier versions
}
AVAudioFormat *recordingFormat = [inputNode outputFormatForBus:0];
//在添加tap之前先移除上一個(gè) 不然有可能報(bào)"Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio',"之類(lèi)的錯(cuò)誤
[inputNode removeTapOnBus:0];
[inputNode installTapOnBus:0 bufferSize:1024 format:recordingFormat block:^(AVAudioPCMBuffer * _Nonnull buffer, AVAudioTime * _Nonnull when) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf.recognitionRequest) {
[strongSelf.recognitionRequest appendAudioPCMBuffer:buffer];
}
}];
[self.audioEngine prepare];
[self.audioEngine startAndReturnError:&error];
NSParameterAssert(!error);
}
結(jié)束錄音
#pragma mark - 結(jié)束錄音
- (void)endRecording{
[self.audioEngine stop];
if (_recognitionRequest) {
[_recognitionRequest endAudio];
}
if (_recognitionTask) {
[_recognitionTask cancel];
_recognitionTask = nil;
}
}
識(shí)別代理
#pragma mark - SFSpeechRecognizerDelegate 識(shí)別代理
- (void)speechRecognizer:(SFSpeechRecognizer *)speechRecognizer availabilityDidChange:(BOOL)available API_AVAILABLE(ios(10.0)){
if (available) {
NSLog(@"delegate :開(kāi)始錄音");
}
else{
NSLog(@"語(yǔ)音識(shí)別不可用");
}
}
??然而需要注意的卻是出發(fā)錄音和結(jié)束錄音的方法調(diào)用:保證從開(kāi)始到結(jié)束整個(gè)過(guò)程,各自只能調(diào)用一次。
#pragma warning - 保證整個(gè)過(guò)程,兩個(gè)代理各自只能調(diào)用一次
- (void)longPress:(UILongPressGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
[self buttonTouchDown];
} else if(gestureRecognizer.state == UIGestureRecognizerStateChanged) {
/*
NSLog(@"手勢(shì)位置發(fā)生變化");
CGPoint point = [gestureRecognizer locationInView:self];
if (![self.layer containsPoint:point]) {
[self buttonTouchCancel];
}
*/
} else if (gestureRecognizer.state == UIGestureRecognizerStateEnded){
//NSLog(@"結(jié)束手勢(shì)事件");
[self buttonTouchCancel];
} else if (gestureRecognizer.state == UIGestureRecognizerStateFailed){
//NSLog(@"無(wú)法識(shí)別的手勢(shì)");
}
}
----end.