Android

媒体补充增强信息

更新时间: 2022/01/21 08:37:53

通过 NERTC SDK,您可以将包括音量信息在内的自定义信息作为 SEI 的一部分,封装在视频码流中,并将其发送至远端用户解码查看,可用于音画同步等场景。

功能描述

在音视频流媒体应用中,用户的消息分发通道和音视频或直播通道是分开的,通常情况下难以保证消息与视频数据的同步性。NERTC 支持将时间戳等自定义数据作为流媒体补充增强信息 (SEI Supplemental Enhancement Information)的一部分,通过流媒体通道将其与视频内容打包在一起,发送给远端用户,以此实现文本数据与音视频内容的精准同步的目的。

直播场景中,互动直播 2.0 会自动将音视频房间中参与互动直播成员的 SEI 信息进行重新封装,通过网易云信自定义的 SEI 类型打包,推流至播放端,您可以通过网易云信播放器 SDK 自动解析视频流 SEI 中封装的自定义数据。

SEI 一般用于以下场景:

  • 在线教育场景,知识竞答等教育教学工具中需要老师的声音和需要作答的题目进行同步。
  • 电商购物场景,需要将商品信息和主播的声音及画面进行同步。
  • 泛娱乐场景的在线 KTV 玩法中,需要在合唱场景中歌词和声音及画面进行同步。

注意事项

  • 默认通过主流发送 SEI 信息。您也可以在调用 sendSEIMsg 时指定通过辅流发送 SEI,发送前需确保该通道为开启状态。
  • 纯音频场景的 SEI 帧通过 Fake Video 形式发送,不涉及视频流数据计费。

实现方法

音视频直播场景

本端:

  1. 本端加入房间后,通过 enableLocalVideo 开启视频流。
  2. 视频流成功开启后,调用 sendSEIMsg 接口发送 SEI 信息。

远端:

  1. 注册一个 NERtcEngineVideoSEIObserver 观测器用于接收远端流的 SEI 内容回调。
  2. 远端接收到本端发送的 SEI 信息后,触发 onNERtcEngineRecvSEIMsg 回调。

纯音频通话场景

纯音频通话场景下,如果需要发送 SEI 信息到远端,SDK 会自动采取 Fake Video 方案。实现过程如下:

  1. 本端调用「sendSEIMsg」发送SEI信息。

    此时SDK内部会自动生成一个 Fake Video 的视频流,并携带 SEI 信息发送至远端。Fake Video 的分辨率为 16×16,画面为纯黑色。

  2. 远端接收到纯音频流下发送的 Fake Video 的信令通知,通过 NERtcVideoProfileType 中的 kNERtcVideoProfileFake 字段判断该视频流为 Fake Video。

    此时需要订阅该视频流,但无需展示该视频流画面。

  3. 远端注册一个 NERtcEngineVideoSEIObserver 观测器用于接收远端流的 SEI 内容回调。

  4. 远端接收到本端发送的SEI信息后,触发 onNERtcEngineRecvSEIMsg 回调。

当您在纯音频通话场景下,通过发送 Fake Video 的方式实现 SEI 帧发送后,如果需要开启视频流正常发送视频数据,可以通过 enableLocalVideo 开启视频流,并调用 sendSEIMsg 继续发送 SEI 信息。此时SDK会自动判断之前是否开启了 Fake Video,如果开启了就会关闭 Fake Video,然后再开启视频。

示例代码

/**
 NERtcEngine 扩展回调
 */
@protocol NERtcEngineDelegateEx <NERtcEngineDelegate, NERtcEngineVideoFrameObserver, NERtcEngineAudioSessionObserver,NERtcEngineLiveStreamObserver, NERtcEngineVideoSEIObserver>
@end


//实现SEI的回调注册
- (NERtcEngine *)coreEngine {
    if (!_coreEngine) {
        _coreEngine = [NERtcEngine sharedEngine];
        
        //video codec
        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        NSDictionary *keyMap = NTESToNERtcSettingsKeyMap();
        fillNERtcParams(params, keyNRTCDemoPreferHWEncode, keyMap);
        fillNERtcParams(params, keyNRTCDemoPreferHWDecode, keyMap);
        [_coreEngine setParameters:params];

        //context
        NERtcEngineContext *context = [[NERtcEngineContext alloc] init];
        context.engineDelegate = self;
        //
        NSString *settingsKey = [NTESDemoSettings stringForKey:keyNRTCDemoAppKey];
        NSString *appKey = settingsKey.length > 5 ? settingsKey : [NTESDemoConfig sharedConfig].appKey;
        context.appKey = appKey;
        //
        NERtcLogSetting *logSetting = [[NERtcLogSetting alloc] init];
        logSetting.logDir = [NTESDemoConfig sharedConfig].rootDir;
        if (![NTESDemoSettings boolForKey:keyNRTCDemoAppLogEnabled defaultVal:YES]) {
            logSetting.logLevel = kNERtcLogLevelOff;
        }
        else {
            logSetting.logLevel = kNERtcLogLevelDetailInfo;
        }
        
        context.logSetting = logSetting;
        [_coreEngine setupEngineWithContext:context];
    }
    
    return _coreEngine;
}


//发送SEI:
- (void)onMenuSendSEI:(id)sender {
    static int index = 0;
    NSString *msg = [NSString stringWithFormat:@"index:%d,msg:%.f", ++index, [[NSDate date] timeIntervalSince1970]];
    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    
    NERtcStreamChannelType type = kNERtcStreamChannelTypeMainStream;
    if ([NTESDemoSettings objectForKey:keyNRTCDemoLocalSEISendPrefer]) {
        type = (NERtcStreamChannelType)([NTESDemoSettings integerForKey:keyNRTCDemoLocalSEISendPrefer]);
    }
    
    [[[NTESDemoLogic sharedLogic] getCoreEngine] sendSEIMsg:data streamChannelType:type];
}


//接受SEI
- (void)onNERtcEngineRecvSEIMsg:(uint64_t)userID message:(NSData *)message {
    NSString *msg = [[NSString alloc] initWithData:message encoding:NSUTF8StringEncoding];
    NSString *seiMsg = [NSString stringWithFormat:@"userID:%llu,message:%@",userID, msg];
    MakeToast(seiMsg);
}

互动直播视频流的 SEI 格式

在互动直播场景中,互动直播 2.0 服务端转码推流时,在转码后的 H264/H265 的 SEI 中增加当前视频的编码信息,其中包含客户端 SDK 上传的自定义 SEI 信息,封装类型为网易云信自定义的 SEI 类型。您可以通过网易云信播放器 SDK 自动解析视频流 SEI 中封装的自定义数据。

SEI 格式

SEI 的格式为 JSON 格式的字符串,例如:

{
    "canvas":{
        "w":640,
        "h":360,
        "bgnd":"#000000"
    },
    "regions":[
        {
            "uid":1,
            "alpha":1,
            "zorder":1,
            "volume":50,
            "x":0,
            "y":0,
            "w":320,
            "h":360
        },
        {
            "uid":2,
            "alpha":1,
            "zOrder":1,
            "volume":89,
            "x":320,
            "y":0,
            "w":320,
            "h":360
        }
    ],
    "rtc_sei":[
        {
            "uid":1,
            "mainSei":"xxxxx",
            "subSei":"xxxxx"
        },
        {
            "uid":2,
            "mainSei":"xxxxx",
            "subSei":"xxxxx"
        }
    ],
    "ver":"20190611",
    "ts":1535385600000,
    "app_data":"abc"
}

字段说明

参数 概述
canvas - 画布信息。
w 画布的宽度,单位为像素。其值为推流端在 NERtcLiveStreamLayout 结构体中设置的 width 参数。
h 画布的高度,单位为像素。其值为推流端在 NERtcLiveStreamLayout 结构体中设置的 height 参数。
bgnd bgnd:画布的背景颜色,格式为 RGB 定义下的十六进制整数。其值为推流端在 NERtcLiveStreamLayout 结构体中设置的 background_color 参数。
regions - 所有参与互动直播房间成员的信息(包含布局信息),为 region 的列表。 其值为推流端在 NERtcLiveStreamLayout 结构体中设置的 users 参数。
uid 该区域对应成员的 ID。其值为推流端在 NERtcLiveStreamUserTranscoding 结构体中设置的 uid 参数。
alpha 预留参数,暂未启用。
zorder 直播视频上用户视频帧的图层编号。
volume 该区域对成员的音量。
x 该区域在画布中对应的 x 坐标。其值为推流端在 NERtcLiveStreamUserTranscoding 结构体中设置的 x 参数。
y 该区域在画布中对应的 y 坐标。其值为推流端在 NERtcLiveStreamUserTranscoding 结构体中设置的 y 参数。
w 该区域的宽度,单位为像素。其值为推流端在 NERtcLiveStreamUserTranscoding 结构体中设置的 width 参数。
h 该区域的高度,单位为像素。其值为推流端在 NERtcLiveStreamUserTranscoding 结构体中设置的 height 参数。
rtc_sei - 参与互动直播的房间成员上传的 SEI。即其客户端 SDK 在 sendSEIMsg 中设置的 data 数据。
uid 发送 SEI 的用户 ID。
mainSei 客户端 SDK 在主流通道中封装的 SEI。
subSei 客户端 SDK 在辅流通道中封装的 SEI。
ver 预留参数,暂未启用。
ts 生成该信息时的 Unix 时间戳,单位为毫秒。
app_data 自定义的媒体补充增强信息。为创建推流任务时传入的 extraInfo 字段。
此文档是否对你有帮助?
有帮助
去反馈
  • 功能描述
  • 注意事项
  • 实现方法
  • 音视频直播场景
  • 纯音频通话场景
  • 示例代码
  • 互动直播视频流的 SEI 格式
  • SEI 格式
  • 字段说明