iOS12.1語音播報問題

問題描述:
業物需求,需要使用類似支付寶收款到賬的通知,之前采用iOS10.0的原線上ServiceExtension進行收到通知修改通知內容然后采用系統AVSpeechSynthesizer 進行播放,iOS10-12.1之前通知一切正常,當12.1一更新之后APP通知會只有通知欄沒有通知語音,因此查閱文檔采坑終于找到了解決方案 ,時間短任務重沒時間寫太多,寫文章半小時前剛搞定,所以暫時先附上代碼有需要的先解決,之后再修改詳細文章。

解決思想

1.先使用訊飛語音合成SDK將文字轉化為PCM格式文件(訊飛只支持這玩意)

2.然后用lame工具轉為MP3格式

3.使用AudioService進行MP3播放(試過其他播放方式不行。。。)

代碼(先湊合看后續更新)

//  NotificationService.m
//  JZServiceExtension
//
//  Created by Jincang Lu on 2018/11/13.
//  Copyright ? 2018年 shanghai KaoPush Network Technology Co., Ltd. All rights reserved.
//

#import "NotificationService.h"
#import <AVFoundation/AVFoundation.h>
#import <iflyMSC/iflyMSC.h>
#import "lame.h"
#define kTime 0.6
static SystemSoundID soundID = 10;
#define IF_APPID                            @"自己申請"

API_AVAILABLE(ios(10.0))
@interface NotificationService ()<AVSpeechSynthesizerDelegate,IFlySpeechSynthesizerDelegate>

@property (nonatomic, strong) void (^contentHandler)(UNNotificationContent *contentToDeliver);
@property (nonatomic, strong) UNMutableNotificationContent *bestAttemptContent;
@property (nonatomic, strong) IFlySpeechSynthesizer *iFlySpeechSynthesizer;

@end

@implementation NotificationService

- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler  API_AVAILABLE(ios(10.0)){
    self.contentHandler = contentHandler;
    self.bestAttemptContent = [request.content mutableCopy];
    
    NSString *initString = [[NSString alloc] initWithFormat:@"appid=%@", IF_APPID];
    [IFlySpeechUtility createUtility:initString];
    
    // Modify the notification content here...
    self.bestAttemptContent.title = [NSString stringWithFormat:@"%@", self.bestAttemptContent.title];
    self.bestAttemptContent.body = [NSString stringWithFormat:@"%@", self.bestAttemptContent.body];
     self.bestAttemptContent.sound = nil;
    [self syntheticVoice:[NSString stringWithFormat:@"%@",self.bestAttemptContent.body]];
//    self.bestAttemptContent.sound = [UNNotificationSound soundNamed:@"xindong.caf"];
    
}


- (void)syntheticVoice:(NSString *)string {
    
    //獲取語音合成單例
    _iFlySpeechSynthesizer = [IFlySpeechSynthesizer sharedInstance];
    //設置協議委托對象
    _iFlySpeechSynthesizer.delegate = self;
    //設置合成參數
    //設置在線工作方式
    [_iFlySpeechSynthesizer setParameter:[IFlySpeechConstant TYPE_CLOUD]
                                  forKey:[IFlySpeechConstant ENGINE_TYPE]];
    //設置音量,取值范圍 0~100
    [_iFlySpeechSynthesizer setParameter:@"100"
                                  forKey: [IFlySpeechConstant VOLUME]];
    //發音人,默認為”xiaoyan”,可以設置的參數列表可參考“合成發音人列表”
    [_iFlySpeechSynthesizer setParameter:@"xiaoyan"
                                  forKey: [IFlySpeechConstant VOICE_NAME]];
    //保存合成文件名,如不再需要,設置為nil或者為空表示取消,默認目錄位于library/cache下
    [_iFlySpeechSynthesizer setParameter:@"xfffs.pcm"
                                  forKey: [IFlySpeechConstant TTS_AUDIO_PATH]];
    //啟動合成會話
    //        [_iFlySpeechSynthesizer startSpeaking: @"接著到賬111111111110元"];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
    NSString *path = [paths objectAtIndex:0];
    NSLog(@"psth==%@",path);
    [_iFlySpeechSynthesizer synthesize: string toUri:[NSString stringWithFormat:@"%@/xfffss.pcm",path]];
    
}

//合成結束
- (void) onCompleted:(IFlySpeechError *) error {
    NSLog(@"合成完成--%@-%d",error.errorDesc,error.errorCode);
    [self convertToMp3];
    self.contentHandler(self.bestAttemptContent);
}


- (void)convertToMp3
{
    NSString *fileName = [NSString stringWithFormat:@"/%@.mp3", @"yuyin"];
    NSString *filePath = [[NSHomeDirectory() stringByAppendingFormat:@"/Documents/"] stringByAppendingPathComponent:fileName];
    NSLog(@"%@",filePath);
//    NSString *mp3Url = [NSURL URLWithString:filePath];
    @try {
        int read,write;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES);
        NSString *path = [paths objectAtIndex:0];
        //只讀方式打開被轉換音頻文件
        FILE *pcm = fopen([[NSString stringWithFormat:@"%@/xfffss.pcm",path] cStringUsingEncoding:1], "rb");
        fseek(pcm, 4 * 1024, SEEK_CUR);//刪除頭,否則在前一秒鐘會有雜音
        //只寫方式打開生成的MP3文件
        FILE *mp3 = fopen([filePath cStringUsingEncoding:1], "wb");
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE * 2];
        unsigned char mp3_buffer[MP3_SIZE];
        //這里要注意,lame的配置要跟AVAudioRecorder的配置一致,否則會造成轉換不成功
        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, 11025.0);//采樣率
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        
        do {
            //以二進制形式讀取文件中的數據
            read = (int)fread(pcm_buffer, 2 * sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            //二進制形式寫數據到文件中  mp3_buffer:數據輸出到文件的緩沖區首地址  write:一個數據塊的字節數  1:指定一次輸出數據塊的個數   mp3:文件指針
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
        
    } @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    } @finally {
        NSLog(@"MP3生成成功!!!");
        //    NSString *str = [_iFlySpeechSynthesizer parameterForKey:[IFlySpeechConstant TTS_AUDIO_PATH]];
        //    NSString *str = [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@/xfff",path] ofType:@"mp3"];
        NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/yuyin.mp3",[NSHomeDirectory() stringByAppendingFormat:@"/Documents/"]]];
        AudioServicesCreateSystemSoundID((__bridge CFURLRef _Nonnull)(url), &soundID);
        AudioServicesPlayAlertSound(soundID);
        AudioServicesPlayAlertSoundWithCompletion(soundID, ^{
            NSLog(@"播放完成");
        });
    }
}

//合成開始
- (void) onSpeakBegin {
    
}
//合成緩沖進度
- (void) onBufferProgress:(int) progress message:(NSString *)msg {
    NSLog(@"-----進度---------%@",msg);
}
//合成播放進度
- (void) onSpeakProgress:(int) progress beginPos:(int)beginPos endPos:(int)endPos {
    NSLog(@"====%d==%d=====",beginPos,endPos);
}



- (void)serviceExtensionTimeWillExpire {
    // Called just before the extension will be terminated by the system.
    // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used.
//    self.contentHandler(self.bestAttemptContent);
}






@end```

extension  plist里面需要加就可以播放了 如果音質變化需要自己去調試參數
<key>UIBackgroundModes</key>
    <array>
        <string>audio</string> 
    </array>


QQ 873702616

截止11.16號 支付寶 收錢吧 12.1也沒解決此問題 希望大家盡量先不要在這個方法上浪費太多時間了,上邊這個方法提交版本會有問題,提供一種解決思路 希望大家有后續方案進行探討
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容