You need to enable JavaScript to run this app.
导航

常见问题

最近更新时间2023.10.24 14:14:41

首次发布时间2021.12.20 14:44:12

播放进度回调及其准确性

播放进度回调

SDK 支持细粒度的播放进度回调。开发者可以在收到 SETtsPlaybackProgress 状态回调时,解析附加的 data 字段,获得播放进度(单位:百分比),格式如下:

{
    "progress": 0.3,
    "reqid": "bb081d44-0671-4789-8df5-0050edae517b",
}

准确性

SDK 返回的播放进度是当句已播放的音频长度除以该句音频的总长度:

  • 如果正在播放的句子已经合成结束,那么它的总长度是准确的,计算出的播放进度也是准确的;
  • 如果正在播放的句子正在合成,即边合成边播放的情况,该句的总长度为算法预估值,与真实值有一定偏差,据其得出的播放进度也不完全准确;
  • 分句策略会影响预估的准确性

综上,如果开发者想要获得准确的播放进度,建议根据标点(;!?。!?;…)对文本进行分割,分句提前合成进行缓存。该策略下,已完成合成的句子,后续的播放进度为准确值。

触发鉴权证书下载的条件

SDK 支持鉴权证书下载功能,因为没有必要每次初始化都重新下载证书,所以下载只可能在以下几种情况才会触发:

  1. 指定的目录不存在证书文件;
  2. 证书文件损坏;
  3. 证书过期;
  4. 该证书可授权的功能中不包含当前申请的功能(只使用语音合成能力的客户不存在这种情况);
后台播放需做的特殊处理

如果需要语音合成 SDK 在后台播报,就可能遇到其他应用使用播放器或录音机的场景。针对这几种情况,我们推荐开发者参考下面的示例代码进行处理,篇幅有限故仅展示核心代码,完整样例程序可参考 Demo 源码。以下示例代码实现了几种效果:

  • 其他应用 需要录音 :开始录音,语音合成播报暂停;录音结束,语音合成播报恢复;
  • 其他应用 需要播放(微信消息) :开始播放,语音合成播报暂停;播放结束,语音合成播报恢复;
  • 其他应用 播放音乐(QQ 音乐) :开始播放歌曲,语音合成播报暂停;停止播放歌曲,语音合成播报不再恢复;

通过接收音频终端通知来完成相应的处理:

- (void)addNotification {
  [[NSNotificationCenter defaultCenter] addObserver:self
                       selector:@selector(audioInterruptionHandler:)
                         name:AVAudioSessionInterruptionNotification
                        object:nil];
}
- (void)audioInterruptionHandler:(NSNotification*)notification {
  AVAudioSessionInterruptionType interruptionType = (AVAudioSessionInterruptionType)[[notification.userInfo objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
  AVAudioSessionInterruptionOptions intertuptionOptions = [[notification.userInfo objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntValue];
  NSLog(@"Receive audio interruption notification, type: %lu, options: %lu.", (unsigned long)interruptionType, (unsigned long)intertuptionOptions);
  if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
    NSLog(@"Audio session interruption began");
    @synchronized (self) {
      int ret = [self.curEngine sendDirective:SEDirectivePausePlayer];
      NSLog(@"Pause player return value: %d", ret);
    }
  } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
    @synchronized (self) {
      NSLog(@"Audio session interruption ended");
      if (intertuptionOptions == AVAudioSessionInterruptionOptionShouldResume) {
        AVAudioSession *session = [AVAudioSession sharedInstance];
        AVAudioSessionCategoryOptions cur_options = session.categoryOptions;
        // AudioQueueStart() will return AVAudioSessionErrorCodeCannotInterruptOthers if options didn't contains AVAudioSessionCategoryOptionMixWithOthers
        if (!(cur_options & AVAudioSessionCategoryOptionMixWithOthers)) {
          AVAudioSessionCategoryOptions readyOptions = AVAudioSessionCategoryOptionMixWithOthers | cur_options;
          [session setCategory:AVAudioSessionCategoryPlayback withOptions:readyOptions error:nil];
        }

        int ret = [self.curEngine sendDirective:SEDirectiveResumePlayer];
        NSLog(@"Resume player return value: %d", ret);

        cur_options = session.categoryOptions;
        // Remove AVAudioSessionCategoryOptionMixWithOthers, or the playback will not be interrupted any more
        if (cur_options & AVAudioSessionCategoryOptionMixWithOthers) {
          [session setCategory:AVAudioSessionCategoryPlayback withOptions:((~AVAudioSessionCategoryOptionMixWithOthers) & cur_options) error:nil];
        }
      }
    }
  }
}