当前位置:   article > 正文

IOS开发 百度语音实现播报及IOS12.1后的播报功能问题与实现_收款百度语音播报tts

收款百度语音播报tts

iOS 百度语音实现播报及iOS12.1后的播报功能问题与实现

 

最近碰到个接收到推送要实现语音播报的需求,需要后台推送通知,APP客户端收到通知之后语音播放:“您的账户收到一笔巨款”的功能。使用到了Notification Service Extension服务。

在之前的记录使用AVSpeechUtterance 来进行语音播报。
文章地址:http://www.laileshuo.com/?p=1324

经过实验AVSpeechUtterance语音声音很奇怪,于是考虑使用百度语音合成来实现播报。使用到的即是语音合成系统(TTS):语音合成(Text To Speech,TTS):将文本合成为语音,即声音文件。

集成百度语音合成地址:https://ai.baidu.com/docs#/TTS-iOS-SDK/top

 

一、集成百度TTS

 

  • 加入sdk

下载百度语音合成的SDK,我们需要BDSClientLib中的libBaiduSpeechSDK,Headers中的TTS文件夹下的文件,Resource文件夹的资源。将这些文件放到NotificationService文件夹下

如图所示

alt text

  • 添加依赖库

使用到的依赖库libsqlite3.0.tbd、libiconv.2.4.0.tbd、libc++.tbd、libz.1.2.5.tbd、GLKit.framework、SystemConfiguration.framework、AudioToolbox.framework、AVFoundation.framework、CFNetwork.framework、CoreLocation.framework、CoreTelephony.framework

alt text

 

二、代码实现

 

在NotificationService上实现代码

  1. - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
  2. self.contentHandler = contentHandler;
  3. self.bestAttemptContent = [request.content mutableCopy];
  4. // 语音合成,使用AVAudioPlayer播放,成功
  5. [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
  6. [self configureSDK];
  7. // 这个info 内容就是通知信息携带的数据,后面我们取语音播报的文案,通知栏的title,以及通知内容都是从这个info字段中获取
  8. NSString *alert = self.bestAttemptContent.userInfo[@"alert"];
  9. // 播报语音
  10. //百度语音TTS
  11. NSError *err = nil;
  12. NSInteger sentenceID = [[BDSSpeechSynthesizer sharedInstance] speakSentence: alert withError:&err];
  13. NSLog(@"sentenceID:%ld error:%@",(long)sentenceID,err);
  14. self.contentHandler(self.bestAttemptContent);
  15. }
  16. -(void)configureSDK{
  17. NSLog(@"TTS version info: %@", [BDSSpeechSynthesizer version]);
  18. if (!self.baiduPlayer) {
  19. self.baiduPlayer = [[BDSBuiltInPlayer alloc] init];
  20. self.baiduPlayer.delegate = self;
  21. }
  22. [BDSSpeechSynthesizer setLogLevel:BDS_PUBLIC_LOG_VERBOSE];
  23. [[BDSSpeechSynthesizer sharedInstance] setSynthesizerDelegate:self];
  24. [self configureOnlineTTS];
  25. [self configureOfflineTTS];
  26. }
  27. -(void)configureOnlineTTS {
  28. [[BDSSpeechSynthesizer sharedInstance] setApiKey:NS_Baidu_API_KEY withSecretKey:NS_Baidu_SECRET_KEY];
  29. [[BDSSpeechSynthesizer sharedInstance] setSynthParam:@(BDS_SYNTHESIZER_SPEAKER_FEMALE) forKey:BDS_SYNTHESIZER_PARAM_SPEAKER];
  30. }
  31. -(void)configureOfflineTTS {
  32. NSError *err = nil;
  33. // 在这里选择不同的离线音库(请在XCode中Add相应的资源文件),同一时间只能load一个离线音库。根据网络状况和配置,SDK可能会自动切换到离线合成。
  34. NSString* offlineEngineSpeechData = [[NSBundle mainBundle] pathForResource:@"Chinese_And_English_Speech_Female" ofType:@"dat"];
  35. NSString* offlineChineseAndEnglishTextData = [[NSBundle mainBundle] pathForResource:@"Chinese_And_English_Text" ofType:@"dat"];
  36. err = [[BDSSpeechSynthesizer sharedInstance] loadOfflineEngine:offlineChineseAndEnglishTextData speechDataPath:offlineEngineSpeechData licenseFilePath:self.localPath withAppCode:NS_Baidu_APP_ID];
  37. if(err){
  38. return;
  39. }
  40. }

 

三、测试

 

首先选中主app运行到手机上,之后运行NotificationService

最后在极光上进行推送。

alt text

最后收到播放声音。

 

四、特别注意的事情

 

下面是关于iOS12.1之后:在12.1之后,在这个推送扩展就无法在后台进行播放了.

 

1、在12.1之后 推送扩展就无法在后台进行播放

 

下图是官方给出的说明,之前给出这个拓展推送主要是为了丰富推送的UI样式,推送信息加密之类的,结果却被用做推送语音播报,所以就发了这个声明,在12.1之后,在这个推送扩展就无法在后台进行播放了.

alt text

所以 iOS12.1使用百度语音无法播报。

 

2、测试遇到的现象

  1. / 12.1版本,AVAudioPlayer后台播放会失败
  2. NSString *path = [[NSBundle mainBundle] pathForResource:@"audio" ofType:@"mp3"];
  3. NSURL *url = [NSURL fileURLWithPath:outPutFilePath];
  4. self.myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
  5. self.myPlayer.delegate = self;
  6. [self.myPlayer play];
  7. // 12.1版本,AudioServicesPlayAlertSoundWithCompletion后台播放会失败
  8. static SystemSoundID soundID = 0;
  9. AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
  10. AudioServicesPlayAlertSoundWithCompletion(soundID, ^{
  11. NSLog(@"播放完成");
  12. });

既然12.1,NotificationService中无法进行后台播报,所以使用AVAudioPlayer、AudioServicesCreateSystemSoundID都会失败


如果在NotificationService中info.plist文件中加入

plist里面需要加UIBackgroundModes的 audio 就可以播放了


但是:
这个当打包上传到Appstore上就会出现错误了,提示说NotificationService中的UIBackgroundModes的Audio这个字段是非法的,无法添加的。

 

3、解决方案之修改通知的UNNotificationSound

 

在收到推送后,我们可以将消息拆成多个本地,每个通知NotificationContent的Sound都对应工程资源的一个音频文件。

alt text

代码所示:

  1. - (void)playWithRegisterNotifications:(NSString *)content {
  2. NSArray *array = @[@"shoukuan",@"2",@"bai",@"5",@"shi",@"dian",@"0",@"8",@"yuan"];
  3. for (NSString *string in array) {
  4. dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
  5. [self registerNotificationWithString:string completeHandler:^{
  6. //延迟大于1秒感觉更好一点
  7. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  8. dispatch_semaphore_signal(semaphore);
  9. });
  10. }];
  11. dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
  12. }
  13. }
  14. - (void)registerNotificationWithString:(NSString *)string completeHandler:(dispatch_block_t)complete {
  15. [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
  16. if (granted) {
  17. UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init];
  18. content.title = @"";
  19. content.subtitle = @"";
  20. content.body = @"";
  21. content.sound = [UNNotificationSound soundNamed:[NSString stringWithFormat:@"%@.mp3",string]];
  22. content.categoryIdentifier = [NSString stringWithFormat:@"categoryIndentifier%@",string];
  23. UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
  24. UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[NSString stringWithFormat:@"categoryIndentifier%@",string] content:content trigger:trigger];
  25. [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
  26. if (error == nil) {
  27. if (complete) {
  28. complete();
  29. }
  30. }
  31. }];
  32. }
  33. }];
  34. }

经过测试,可以播放,但是:
dispatch_after在0.25秒后执行一个本地通知,但是这个情况很容易出现第语音播放不完整的情况,如果时间设置过大,语音播放的语速就很慢,体验极差。声音的大小也无法调整。

这种情况下可以采用通用的提示,如:您有一笔收款。这样的语音提示体验会好点,但是不是最优的方式

 

4、关于支付宝或者微信语音播报

 

经过查找,大概率支付宝、微信使用的使用voip模式,通过查找微信与支付宝的ipa,ipa中配置的文件都UIBackgroundModes(后台模式)包含voip。

所以大概率支付宝与微信都使用的是Voip PushKit实现的收款的语音播报功能

之后也会调查下Voip PushKit实现的收款的语音播报功能,PushKit和极光推送还不太一样。持续关注中。。。

本文地址:http://www.laileshuo.com/?p=1347

博客地址:www.laileshuo.com

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/471640
推荐阅读
相关标签
  

闽ICP备14008679号