使用场景:我们的产品需求是当多个顾客同时向商户发起支付时,App 收到多条推送,客户端需要逐一语音播报。
解决存在的问题:当出现多条推送时只有最后一条语音会被完整播报,前面的语音会被中断
。
解决方案:这里就简单的介绍一下实现推送语音播报的一种方案,已上线运行。
一、当我们需要实现这么一个需求时,无非需要考虑以下几种条件:
1、如何获取每条语音的时长;
2、如何监听语音何时播报结束;
3、如何从队列取出和删除。
我们项目中项目处于前台时语音播报采用的是讯飞的方案,因此我们可以在讯飞的 API 里面看到有一个开始播报和结束回调的方法:
/*!
* 开始合成(播放)
* 调用此函数进行合成,如果发生错误会回调错误`onCompleted`
*
* @param text 合成的文本,最大的字节数为1k
*/
- (void) startSpeaking:(NSString *)text;
/**
* 结束回调
* 当整个合成结束之后会回调此函数
*
* @param error 错误码
*/
- (void) onCompleted:(IFlySpeechError*) error;
有了这个方法,我们只需要考虑好上面提出的第三个因素。
二、实现的步骤:
①首先我们需要接收到需要播报的内容;
@property (nonatomic , copy) NSString *voiceContent;
②声明一个播报的方法;
- (void)play;
③初始化并调用播报方法;
- (void)setTitleVoice:(NSString *)titleVoice
{
[self.voiceArr addObject:titleVoice];
_titleVoice = titleVoice;
[self play];
}
/**
实现队列播报,并从数据源中删除已经播报的语音
*/
- (void)play
{
NSOperationQueue *queue = [NSOperationQueue mainQueue];
if (self.isPlay) {
_titleVoice = self.voiceArr[0];
[queue addOperation:[self customOperation:_titleVoice]];
self.isPlay = false;
[self.voiceArr removeObjectAtIndex:0];
}
}
- (NSOperation *)customOperation:(NSString *)content {
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
@autoreleasepool {
if (content.length == 0) {
return;
}
[self.iFlySpeechSynthesizer startSpeaking:content];
}
}];
return operation;
}
/**
合成结束(完成)回调
****/
- (void)onCompleted:(IFlySpeechError *) error
{
self.isPlay = true;
if (self.voiceArr.count > 0) {
[self play];
}
}
至此,我们就简单的实现了队列播报的这么一个需求,使用第三方可以减少工作量。如果发现上面内容有出入在留言提出,有更好的方案也可以交流。