文档

基于SEI实现布局平滑切换

本文介绍普通观众(CDN观众)如何感知主播视频画面从单主播切换成连麦布局。普通观众播放CDN流有一定的延时,可以使用周期性SEI来解决该问题。当画面从单主播画面切换成混流画面后,阿里云媒体服务会在播放的视频流中自动插入SEI帧,SEI帧中包含每个成员的布局信息,用户可以在普通观众播放端开启SEI监听,并根据布局信息的变化来感知主播视频画面从单主播切换成连麦布局。具体您可以登录视频直播控制台,开启SEI配置。

阿里云媒体服务自动插入SEI帧格式如下:

数据类型

参数名称

数值

视频流信息

stream

主播信息:

uid:对应主播的用户ID。

主播所在窗格区域的布局信息,仅需关注以下参数:

  • paneid: 该区域在窗格编号,取值[0,8]。

  • zorder:该区域的叠放层级,取值范围 [0,99]。

  • x:该区域在画布中对应的 x 坐标,归一化百分比。

  • y:该区域在画布中对应的 y 坐标,归一化百分比。

  • w:该区域的宽度,归一化百分比。

  • h:该区域的高度,归一化百分比。

  • vol : 主播的音量(分贝),取值 [0,255]

  • vad :语音检测,取值 [0,150],150是有人声,非150就是从有人声到无声的拖尾时间。

如果只是单主播,观众端接收的SEI信息里stream集合只有一个成员信息;如果是主播正在连麦或者PK,观众端接收的SEI信息里stream集合会有多个成员信息。

例如,当主播111单主播推流时,观众端收到的SEI帧格式如下:

{"stream":[{"uid":"111","paneid":-1,"zorder":0,"x":0,"y":0,"w":0,"h":0,"type":0,"ms":0,"vol":0,"vad":0}]}

当主播111和观众222进行连麦时,观众端收到的SEI帧格式如下:

{"stream":[{"uid":"111","paneid":0,"zorder":1,"x":0,"y":0.25,"w":0.5,"h":0.5,"type":0,"ms":0,"vol":1,"vad":119},{"uid":"222","paneid":1,"zorder":1,"x":0.5018382,"y":0.25,"w":0.5,"h":0.5,"type":0,"ms":0,"vol":60,"vad":123}]}

判断stream数组的个数可以知道当前直播布局是否发生切换,stream数组的个数为1时,则是单主播推流;stream数组的个数大于1,则主播在连麦或PK中。通过成员的布局信息,知道每个成员在混流布局中的具体位置。

阿里云播放器打开解析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信息
    }
}