'Android 实时音视频接入教程:媒体补充增强信息(SEI)'
Android 实时音视频接入教程:媒体补充增强信息(SEI)
本文主要介绍了「媒体补充增强信息(SEI)」的基础接入流程,并结合官方文档梳理了环境准备、核心 API 调用、媒体处理和结果验证等关键环节。
笔者简介
长期关注 RTC 实时音视频领域的技术演进,参与过音视频算法工程化、接入实现与效果评估等相关工作。
在实际项目中,持续关注包括腾讯 TRTC、即构 ZEGO、声网 Agora 在内的多家 RTC 厂商在实时通信能力与工程落地层面的实践,重点关注 SDK 接入、通话链路实现与场景化应用。
本系列文章将围绕 RTC SDK 接入与实时互动能力实现,持续输出工程实践与场景分析。
本文将以 ZEGO 官方 SDK 文档为基础,围绕「媒体补充增强信息(SEI)」梳理完整接入流程,帮助开发者理解环境准备、初始化、核心 API 调用、媒体处理和常见问题排查。
功能简介#
在音视频流媒体应用中,除了可以流媒体通道推拉音视频内容外,还可以使用流 SEI(Supplemental Enhancement Information,媒体补充增强信息)通过流媒体通道将文本信息与音视频内容打包在一起,从主播端(推流端)推出,并从观众端(拉流端)接收,以此实现文本数据与音视频内容的精准同步的目的。
一般可用于视频画面的精准布局、远端歌词同步、直播答题等应用场景。
⚠ 说明
SEI 的相关概念及原理请参考 如何理解和使用 SEI(媒体补充增强信息)。
示例源码下载#
请参考 下载示例源码 获取源码。
相关源码请查看 “/ZegoExpressExample/Others/src/main/java/im/zego/others/sei” 目录下的文件。
前提条件#
在实现 SEI 功能之前,请确保:
- 已在 ZEGO 控制台 创建项目,并申请有效的 AppID 和 AppSign,详情请参考 控制台 - 项目信息。
- 已在项目中集成 ZEGO Express SDK,并实现了基本的音视频推拉流功能,详情请参考 快速开始 - 集成 和 快速开始 - 实现流程。
使用步骤#
发送与接收 SEI 信息功能,需要在推流端发送 SEI 信息,在拉流端接收 SEI 信息,如下图所示:
推流端:
- 调用 createEngine 接口创建 engine 对象。
- 调用 loginRoom 接口登录房间。
- 调用 startPublishingStream 接口推流。
- 在推流成功后,调用 sendSEI 接口发送 SEI 信息。
拉流端: - 调用 createEngine 接口创建 engine 对象。
- 创建 IZegoEventHandler 对象,并重写接收 SEI 信息的 onPlayerRecvSEI 方法,调用 setEventHandler 接口传入创建的 IZegoEventHandler 监听 onPlayerRecvSEI 的回调。
- 调用 loginRoom 接口登录房间。
- 调用 startPlayingStream 接口拉流。
- 在拉流成功后,接收到推流端发送的 SEI 信息之后触发 onPlayerRecvSEI 回调。说明拉流时,如果开发者通过调用
mutePlayStreamVideo或muteAllPlayStreamVideo接口,设置了只拉音频流时,将无法接收 SEI 信息。
1(可选)设置 SEI 类型#
设置 SEI 类型
由于 SDK 默认使用 ZEGO 自行定义的 SEI(nalu type = 6, payload type = 243)类型打包,且此类型是 SEI 标准未规定的类型,因此跟视频编码器或者视频文件中的 SEI 不存在冲突。但当开发者需要使用第三方解码器解码时(如 FFmpeg),会导致解不出正确的 SEI,此时需要在推流前调用
setSEIConfig
接口更换 SDK 发送 SEI 的类型,使用 UserUnregister 的 SEI(nalu type = 6, payload type = 5)类型打包。
⚠ 说明
仅当开发者使用第三方解码器解码 SEI 时需要执行该步骤。
ZegoSEIConfig seiConfig = new ZegoSEIConfig();
class=class="hljs-string">"hljs-comment">// 采用 H.class="hljs-number">264 的 SEI (nalu type = class="hljs-number">6,payload type = class="hljs-number">5) 类型打包,因为视频编码器自身会产生 payload type 为 class="hljs-number">5 的 SEI,或者使用视频文件推流时,视频文件中也可能存在这样的 SEI,所以使用此类型时,用户需要把 uuid + content 当作 buffer 塞给 SEI 发送接口;此时为了区别视频编码器自身产生的 SEI, App 在发送此类型 SEI 时,可以填写业务特定的 uuid(uuid 长度为 class="hljs-number">16 字节),接收方使用 SDK 解析 payload type 为 class="hljs-number">5 的 SEI 时,会根据设置的过滤字符串过滤出 uuid 相符的 SEI 抛给业务,如果没有设置过滤字符串,SDK 会把所有收到的 SEI 都抛给开发者。
seiConfig.type = ZegoSEIType.USER_UNREGISTER;
engine.setSEIConfig(seiConfig);
class=class="hljs-string">"hljs-comment">// 通过 advancedConfig 设置 uuid 过滤字段,设置之后 SDK 只会抛出前 class="hljs-number">12 个字节为开发者所设置 uuid 的 SEI。
ZegoEngineConfig engineConfig = new ZegoEngineConfig();
class=class="hljs-string">"hljs-comment">// 其他用户通过 [onPlayerRecvSEI] 收到的 SEI 信息前 class="hljs-number">12 个字节一定是 zegozegozego,其他会被过滤。
engineConfig.advancedConfig.put(class="hljs-string">"unregister_sei_filter", class="hljs-string">"zegozegozego");
ZegoExpressEngine.setEngineConfig(engineConfig);
class=class="hljs-string">"hljs-comment">// 开始推流。
engine.startPublishingStream(class="hljs-string">"STREAM_ID");2 推流方#
发送 SEI 信息的接口需要在推流成功之后调用,接口原型如下:
接口原型
/**
- 发送媒体增强补充信息。
- 此接口可在开发者推流传输音视频流数据同时,发送流媒体增强补充信息来同步一些其他附加信息。
- 一般如同步音乐歌词或视频画面精准布局等场景,可选择使用发送 SEI。
- 当推流方发送 SEI 后,拉流方可通过监听 [onPlayerRecvSEI] 的回调获取 SEI 内容。
- 由于 SEI 信息跟随视频帧或音频帧,由于网络问题有可能丢帧,因此 SEI 信息也有可能丢,为解决这种情况,应该在限制频率内多发几次。
- 限制频率:1 秒钟不要超过 30 次。
- SEI 数据长度限制为 4096 字节。
- @param data SEI 内容。 */ public void sendSEI(byte[] data)
调用示例
// 定义 SDK 引擎对象。 ZegoExpressEngine engine;
ZegoEngineProfile profile = new ZegoEngineProfile(); // 请通过官网注册获取,格式为 123456789L。 profile.appID = appID; // 请通过官网注册获取,格式为:@"0123456789012345678901234567890123456789012345678901234567890123"(共 64 个字符)。 profile.appSign = appSign; // 通用场景接入。 profile.scenario = ZegoScenario.DEFAULT; // 设置app的application 对象。 profile.application = getApplication(); // 创建引擎。 engine = ZegoExpressEngine.createEngine(profile, null); // 登录房间。 engine.loginRoom("roomid", new ZegoUser("userid_1")); // 推流。 engine.startPublishingStream("streamid"); // 开发者的其他业务逻辑。 ...; // 在业务场景需要的时机发送 SEI 信息。 engine.sendSEI("12345".getBytes());
3 拉流方#
接收 SEI 信息的回调接口需要在拉流成功之后触发,接口原型如下:
接口原型
/**
- 收到远端流的 SEI 内容。
- 拉流成功后,当远端流调用 sendSEI 后,本端会收到此回调。
- 若只拉纯音频流,将收不到推流端发送的 SEI 信息。
- @param streamID 拉流的流 ID。
- @param data SEI 内容。 */ public void onPlayerRecvSEI(String streamID, byte[] data){
}
调用示例
// 定义 SDK 引擎对象。 ZegoExpressEngine engine;
ZegoEngineProfile profile = new ZegoEngineProfile(); // 请通过官网注册获取,格式为 123456789L。 profile.appID = appID; // 请通过官网注册获取,格式为:@"0123456789012345678901234567890123456789012345678901234567890123"(共 64 个字符)。 profile.appSign = appSign; // 通用场景接入。 profile.scenario = ZegoScenario.DEFAULT; // 设置 app 的 application 对象。 profile.application = getApplication(); // 创建引擎。 engine = ZegoExpressEngine.createEngine(profile, null);
// 创建 IZegoEventHandler 对象, 并重写 onPlayerRecvSEI 方法。 IZegoEventHandler handler = new IZegoEventHandler(){ // 监听其他回调。 ...; // 监听接收 SEI 信息的回调, 当发送端调用 sendSEI 发送信息时会触发此回调。 public void onPlayerRecvSEI(String streamID, byte[] data) { // 在这里实现业务场景相关的逻辑, 例如展现相关的 UI 等。 ...; }
} // 添加监听的回调对象。 engine.setEventHandler(handler); // 登录房间。 engine.loginRoom("roomid", new ZegoUser("userid_2")); // 拉流, canvas 为 ZegoCanvas 类型的索引 UI 渲染控件的对象。 engine.startPlayingStream("streamid", canvas); // 开发者的其他业务逻辑。 ...;
相关文档#
结语
本文主要介绍了「媒体补充增强信息(SEI)」的基础接入流程,并结合官方文档梳理了环境准备、核心 API 调用、媒体处理和结果验证等关键环节。
通过这类能力,开发者可以更快搭建实时音视频、在线互动、远程协作、直播连麦、视频通话等典型场景,并在后续根据业务需要扩展更多互动能力。
围绕实时音视频能力,后续还可以继续关注:
- RTC SDK 完整接入流程与关键参数配置
- 推流、拉流、房间与回调机制解析
- 权限、Token、设备兼容和网络异常排查
- 多人通话、语聊房、互动直播等进阶场景
- 跨端场景下的实时互动能力对比
本系列将围绕「RTC SDK 接入与实时互动能力实现」持续更新,适合需要构建实时音视频、在线互动、AI 实时通信等能力的开发者参考。
常见问题
1. SEI 适合解决什么业务问题?#
SEI 适合把文本类附加信息与音视频流同步传输,例如视频画面精准布局、远端歌词同步、直播答题等。它通过流媒体通道随音视频内容发送,适合对音视频画面和业务数据同步性要求较高的场景。
2. sendSEI 应该在什么时候调用?#
文档中说明,发送 SEI 信息的接口需要在推流成功之后调用。典型流程是先创建 engine、登录房间、调用 startPublishingStream 推流,再在业务需要的时机调用 sendSEI 发送数据。
3. 为什么只拉音频流时收不到 SEI?#
SEI 信息跟随音视频流中的视频相关数据传递。文档特别说明,如果拉流端通过 mutePlayStreamVideo 或 muteAllPlayStreamVideo 设置只拉音频流,将无法接收推流端发送的 SEI 信息。
4. SEI 发送频率和数据大小有什么限制?#
sendSEI 的限制频率是 1 秒钟不要超过 30 次,SEI 数据长度限制为 4096 字节。由于 SEI 跟随音视频帧传输,网络问题可能导致丢帧,因此业务上可以在限制频率内重复发送关键 SEI 信息。
5. 默认 SEI 类型和 USER_UNREGISTER 类型有什么区别?#
SDK 默认使用 ZEGO 自定义 SEI 类型打包,通常不会与视频编码器或视频文件中的 SEI 冲突。如果需要使用第三方解码器如 FFmpeg 解码 SEI,可以在推流前调用 setSEIConfig,改用 UserUnregister 类型。
6. 使用 FFmpeg 等第三方解码器时为什么要配置 setSEIConfig?#
默认 ZEGO 自定义 SEI 类型属于标准未规定的类型,第三方解码器可能无法解析出正确 SEI。此时可通过 setSEIConfig 将 SDK 发送 SEI 的类型更换为 UserUnregister,以便第三方解码器按 H.264 SEI 方式处理。
7. unregister_sei_filter 的作用是什么?#
unregister_sei_filter 用于设置 uuid 过滤字段。配置后,SDK 只会抛出前 12 个字节与过滤字段匹配的 SEI,避免业务收到视频编码器自身或视频文件中其他不相关的 SEI 数据。
相关文章
评论