设置音视频SEI

在直播场景中,播放端(观众)想了解当前主播的连麦状态,且在界面上用不同元素进行呈现。例如主播进入PK状态的高亮显示;主播处于连麦状态时,不同连麦方的音量、网络状态、麦克风是否关闭等信息。我们需要保证这类信息与当前的直播画面同步,否则就失去了时效性。在视频编解码标准中,SEI(Supplemental Enhancement Information)可以实现让画面帧携带额外的信息,使得接收端获得与画面同步的关键信息。本文为您介绍在实时音视频中如何基于SEI实现在画面帧中携带与此画面同步的关键信息。

客户端SEI

调用客户端SDK发送SEI的接口,可以在视频帧中插入SEI,并携带用户自定义信息。与主播连麦的观众以及非连麦的普通观众,均可收到自定义信息。

  • 主播和麦上观众调用阿里云直播SDK发送SEI和接收SEI的示例代码如下:

    • Android示例代码:

      //发送SEI:AlivcLivePusher#sendMessage,推流端发送自定义消息
      public void sendSEI(String text) {
          mAlivcLivePusher.sendMessage(text, 0, 0, false);
      }
      
      //接收SEI:AlivcLivePlayInfoListener#onReceiveSEIMessage,收到媒体扩展信息回调
      @Override
      public void onReceiveSEIMessage(int payload, byte[] data) {
          //Log.d(TAG, "onReceiveSEIMessage: " + payload + ", " + new String(data, StandardCharsets.UTF_8));
      }
    • iOS示例代码:

      //发送SEI:AlivcLivePusher中sendMessage方法
      [self.rtcPusher sendMessage:data repeatCount:1 delayTime:0 KeyFrameOnly:false];
      
      //主播和麦上观众接收SEI:AliLivePlayerDelegate中onReceiveSeiMessage回调
      - (void)onReceiveSeiMessage:(AlivcLivePlayer *)player payloadType:(int)payloadType data:(NSData *)data
      {
          if (data.bytes){
              NSString *str = [NSString stringWithUTF8String:data.bytes];
          } 
      }
      
  • 麦下普通观众使用阿里云播放器打开解析SEI帧的示例代码如下:

    • Android示例代码:

      mAliPlayer = AliPlayerFactory.createAliPlayer(mContext);
      
      PlayerConfig playerConfig = mAliPlayer.getConfig();
      // 纯音频 或 纯视频 的flv 需要设置 以加快起播
      // 起播缓存,越大起播越稳定,但会影响起播时间,可酌情设置
      playerConfig.mStartBufferDuration = 1000;
      // 卡顿恢复需要的缓存,网络不好的情况可以设置大一些,当前纯音频设置500还好,视频的话建议用默认值3000.
      playerConfig.mHighBufferDuration = 500;
      // 需要开启SEI监听
      playerConfig.mEnableSEI = true;
      mAliPlayer.setConfig(playerConfig);
      
      mAliPlayer.setAutoPlay(true);
      
      mAliPlayer.setOnErrorListener(errorInfo -> {
          mAliPlayer.prepare();
      });
      
      mAliPlayer.setOnSeiDataListener(new IPlayer.OnSeiDataListener() {
          @Override
          public void onSeiData(int i, byte[] bytes) {
      
          }
      });
    • iOS示例代码:

      self.cdnPlayer = [[AliPlayer alloc] init];
      self.cdnPlayer.delegate = self;
      AVPConfig *config = [self.cdnPlayer getConfig];
      config.enableSEI = YES;
      [self.cdnPlayer setConfig:config];
      
      //监听SEI相关回调
      - (void)onSEIData:(AliPlayer*)player type:(int)type data:(NSData *)data {
          if (data.bytes){
              NSString *str = [NSString stringWithUTF8String:data.bytes];
              //处理SEI信息
          }
      }

服务端SEI

服务端SEI分为系统SEI和服务端自定义SEI。

  • 系统SEI:由实时音视频服务端自动生成,用来描述画面布局、主播麦克风状态、音量状态、摄像头状态、网络状态等信息。

  • 服务端自定义SEI:由业务方调用服务端OpenAPI来发送业务自定义信息。

系统SEI

当主播切换到连麦状态,或者由连麦状态切换回单主播状态时,直播画面的布局会发生变化,此时云端的合流服务器会自动在视频帧中插入SEI,以便让播放端准确感知画面布局的变化。在直播的过程中,可以让系统SEI周期性发送,或者跟随关键帧发送。

  • 当使用客户端SDK来发起混流转推任务时,可以在应用管理控制台,设置系统SEI的发送策略,详情请参见配置旁路转推中的全局自动SEI设置

  • 当使用服务端OpenAPI来发起混流转推任务时,请参考创建混流转推任务(新)/更新混流转推任务(新)的SeiParams.LayoutVolume参数:

    • FollowIdr表示是否跟随关键帧发送。

    • Interval表示系统SEI的发送周期。

    当FollowIdr参数值为0且不填写Interval参数时,表示系统SEI只在布局发生变化、麦克风状态发生变化、摄像头状态发生变化时才发送系统SEI,不会周期性发送SEI。

服务端自定义SEI

服务端自定义SEI用来发送用户自定义消息,只能调用服务端OpenAPI发送。请参考创建混流转推任务(新)/更新混流转推任务(新)的SeiParams.PassThrough参数:

  • PayloadContent携带自定义消息。

  • FollowIdr表示是否跟随关键帧发送。

  • Interval表示系统SEI的发送周期。

当FollowIdr参数值为0且不填写Interval参数时,表示自定义SEI只在调用的时刻发送一次,不会周期性发送。

SEI的数据格式

SEI的数据格式如下图所示,当前版本SEI Payload Type固定为5,即UserDataUnregistered。

image

SEI Payload Content详细参数请参考创建混流转推任务(新)