在直播场景中,播放端(观众)想了解当前主播的连麦状态,且在界面上用不同元素进行呈现。例如主播进入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。
SEI Payload Content详细参数请参考创建混流转推任务(新)。