赞
踩
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
下载百度语音合成的SDK,我们需要BDSClientLib中的libBaiduSpeechSDK,Headers中的TTS文件夹下的文件,Resource文件夹的资源。将这些文件放到NotificationService文件夹下
如图所示
使用到的依赖库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
在NotificationService上实现代码
- - (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
- self.contentHandler = contentHandler;
- self.bestAttemptContent = [request.content mutableCopy];
-
- // 语音合成,使用AVAudioPlayer播放,成功
- [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
-
- [self configureSDK];
-
- // 这个info 内容就是通知信息携带的数据,后面我们取语音播报的文案,通知栏的title,以及通知内容都是从这个info字段中获取
- NSString *alert = self.bestAttemptContent.userInfo[@"alert"];
-
- // 播报语音
- //百度语音TTS
- NSError *err = nil;
- NSInteger sentenceID = [[BDSSpeechSynthesizer sharedInstance] speakSentence: alert withError:&err];
- NSLog(@"sentenceID:%ld error:%@",(long)sentenceID,err);
-
- self.contentHandler(self.bestAttemptContent);
- }
-
-
- -(void)configureSDK{
- NSLog(@"TTS version info: %@", [BDSSpeechSynthesizer version]);
-
- if (!self.baiduPlayer) {
- self.baiduPlayer = [[BDSBuiltInPlayer alloc] init];
- self.baiduPlayer.delegate = self;
- }
-
- [BDSSpeechSynthesizer setLogLevel:BDS_PUBLIC_LOG_VERBOSE];
- [[BDSSpeechSynthesizer sharedInstance] setSynthesizerDelegate:self];
- [self configureOnlineTTS];
- [self configureOfflineTTS];
- }
-
- -(void)configureOnlineTTS {
- [[BDSSpeechSynthesizer sharedInstance] setApiKey:NS_Baidu_API_KEY withSecretKey:NS_Baidu_SECRET_KEY];
- [[BDSSpeechSynthesizer sharedInstance] setSynthParam:@(BDS_SYNTHESIZER_SPEAKER_FEMALE) forKey:BDS_SYNTHESIZER_PARAM_SPEAKER];
- }
-
- -(void)configureOfflineTTS {
-
- NSError *err = nil;
- // 在这里选择不同的离线音库(请在XCode中Add相应的资源文件),同一时间只能load一个离线音库。根据网络状况和配置,SDK可能会自动切换到离线合成。
- NSString* offlineEngineSpeechData = [[NSBundle mainBundle] pathForResource:@"Chinese_And_English_Speech_Female" ofType:@"dat"];
-
- NSString* offlineChineseAndEnglishTextData = [[NSBundle mainBundle] pathForResource:@"Chinese_And_English_Text" ofType:@"dat"];
-
- err = [[BDSSpeechSynthesizer sharedInstance] loadOfflineEngine:offlineChineseAndEnglishTextData speechDataPath:offlineEngineSpeechData licenseFilePath:self.localPath withAppCode:NS_Baidu_APP_ID];
- if(err){
- return;
- }
- }
首先选中主app运行到手机上,之后运行NotificationService
最后在极光上进行推送。
最后收到播放声音。
下面是关于iOS12.1之后:在12.1之后,在这个推送扩展就无法在后台进行播放了.
1、在12.1之后 推送扩展就无法在后台进行播放
下图是官方给出的说明,之前给出这个拓展推送主要是为了丰富推送的UI样式,推送信息加密之类的,结果却被用做推送语音播报,所以就发了这个声明,在12.1之后,在这个推送扩展就无法在后台进行播放了.
所以 iOS12.1使用百度语音无法播报。
2、测试遇到的现象
- / 12.1版本,AVAudioPlayer后台播放会失败
-
- NSString *path = [[NSBundle mainBundle] pathForResource:@"audio" ofType:@"mp3"];
-
- NSURL *url = [NSURL fileURLWithPath:outPutFilePath];
-
- self.myPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
-
- self.myPlayer.delegate = self;
- [self.myPlayer play];
-
- // 12.1版本,AudioServicesPlayAlertSoundWithCompletion后台播放会失败
-
- static SystemSoundID soundID = 0;
-
- AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
-
- AudioServicesPlayAlertSoundWithCompletion(soundID, ^{
- NSLog(@"播放完成");
- });
既然12.1,NotificationService中无法进行后台播报,所以使用AVAudioPlayer、AudioServicesCreateSystemSoundID都会失败
如果在NotificationService中info.plist文件中加入
plist里面需要加UIBackgroundModes的 audio 就可以播放了
但是:
这个当打包上传到Appstore上就会出现错误了,提示说NotificationService中的UIBackgroundModes的Audio这个字段是非法的,无法添加的。
3、解决方案之修改通知的UNNotificationSound
在收到推送后,我们可以将消息拆成多个本地,每个通知NotificationContent的Sound都对应工程资源的一个音频文件。
代码所示:
- - (void)playWithRegisterNotifications:(NSString *)content {
- NSArray *array = @[@"shoukuan",@"2",@"bai",@"5",@"shi",@"dian",@"0",@"8",@"yuan"];
- for (NSString *string in array) {
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- [self registerNotificationWithString:string completeHandler:^{
- //延迟大于1秒感觉更好一点
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
- dispatch_semaphore_signal(semaphore);
- });
- }];
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- }
- }
-
- - (void)registerNotificationWithString:(NSString *)string completeHandler:(dispatch_block_t)complete {
- [[UNUserNotificationCenter currentNotificationCenter] requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionSound | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
-
- if (granted) {
- UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc]init];
-
- content.title = @"";
- content.subtitle = @"";
- content.body = @"";
- content.sound = [UNNotificationSound soundNamed:[NSString stringWithFormat:@"%@.mp3",string]];
-
- content.categoryIdentifier = [NSString stringWithFormat:@"categoryIndentifier%@",string];
-
- UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:0.01 repeats:NO];
-
- UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[NSString stringWithFormat:@"categoryIndentifier%@",string] content:content trigger:trigger];
-
- [[UNUserNotificationCenter currentNotificationCenter] addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
-
- if (error == nil) {
-
- if (complete) {
- complete();
- }
- }
- }];
- }
- }];
- }
经过测试,可以播放,但是:
dispatch_after在0.25秒后执行一个本地通知,但是这个情况很容易出现第语音播放不完整的情况,如果时间设置过大,语音播放的语速就很慢,体验极差。声音的大小也无法调整。
这种情况下可以采用通用的提示,如:您有一笔收款。这样的语音提示体验会好点,但是不是最优的方式
4、关于支付宝或者微信语音播报
经过查找,大概率支付宝、微信使用的使用voip模式,通过查找微信与支付宝的ipa,ipa中配置的文件都UIBackgroundModes(后台模式)包含voip。
所以大概率支付宝与微信都使用的是Voip PushKit实现的收款的语音播报功能
之后也会调查下Voip PushKit实现的收款的语音播报功能,PushKit和极光推送还不太一样。持续关注中。。。
本文地址:http://www.laileshuo.com/?p=1347
博客地址:www.laileshuo.com
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。