You need to enable JavaScript to run this app.
导航

通过媒体内容发送补充信息

最近更新时间2024.04.10 20:49:58

首次发布时间2021.07.18 15:06:49

在音视频流媒体应用中,除了可以收发音视频内容外,可能还需要收发一些与音视频内容同步的文本消息。
你可以 H.264 视频流中插入 SEI (Supplemental Enhancement Information,媒体补充增强信息),并在订阅端接收这些信息。
此外,你也可以通过音频 RTP 扩展头发送数据信息。

适用场景

  • 在线 K 歌场景中,用于同步歌词,进度等。

  • 连麦 PK 场景中,两个直播主播发起 PK 活动,观众感知当前的流画面是否连麦 PK,加载或卸载 PK 场景。基于 SEI 实时展示 PK 血条。

  • 连麦游戏中

    • 通过 SEI 来传输压缩后的人脸识别算法数据,对端通过这些数据进行相应的特效绘制。

    • 直播答题,主持人口播题目时,题目信息可以同步传到远端,用户可以通过互动提交答案。

    • 观众感知流画面的布局信息,判断有无嘉宾,加载或卸载嘉宾麦位组件。

    • 获取每路流的音量信息,并在合流转推中,显示用户音量。

  • 使用自定义编解码器时,用来传递编码器参数。

  • 使用自定义视频采集时,用来传递摄像头参数。

前提条件

你已经集成 RTC SDK,实现了基本的音视频通话。

功能实现

根据你的业务要求,选择适用的实现方案。

SEI 通用方案

通过 SDK 内部视频采集时,可在视频、纯音频应用插入多种客户端的信息,例如歌词、进度、题目等。
在转推直播场景中,通过本方案添加的 SEI 也将被透传到合流中,可用于显示各自的音量、PK 血条等。
SEI

  1. 确保当前使用内部视频采集模块: VIDEO_SOURCE_TYPE_INTERNAL。默认为内部采集,如果当前为外部采集应先调用 setVideoSourceType 设置视频源及屏幕流。

  2. 发送端调用 SEI 发送接口 sendSEIMessage,随视频帧发送 SEI。

对于纯音频应用,SDK 将自动生成视频黑帧,用于携带 SEI 消息。手动发布模式下,需要手动发布该黑帧视频流。

  • 支持 4KB 长度
  • 支持消息重发
  • 以视频 15 fps 为例,同步精度为 0~66 ms,如对精度有更高要求,请参看 通过音频 RTP 扩展头
// 创建引擎
rtcVideo = RTCVideo.createRTCVideo(this, Constants.APP_ID, rtcVideoEventHandler, null, null);
// 开启音视频采集
rtcVideo.startAudioCapture();
rtcVideo.startVideoCapture();
// 插入 SEI
rtcVideo.sendSEIMessage(StreamIndex.STREAM_INDEX_MAIN, msg.getBytes(StandardCharsets.UTF_8), 3, SEICountPerFrame.SEI_COUNT_PER_FRAME_SINGLE);
  1. 接收端会收到 SEI 回调: onSEIMessageReceived

  2. 对于纯音频应用,通过黑帧视频流发送 SEI 数据时。流的发送状态会通过 onSEIStreamUpdate 通知远端用户。 手动订阅模式下,需要订阅该黑帧视频流。

IRTCVideoEventHandler rtcVideoEventHandler = new IRTCVideoEventHandler() {
    @Override
    public void onSEIMessageReceived(RemoteStreamKey remoteStreamKey, ByteBuffer message) {
        // 处理接收到的 SEI,以下为示例
        Charset charset = Charset.defaultCharset();
        String dataString = charset.decode(message).toString();
        ToastUtil.showLongToast(SEIMessageActivity.this, "onSEIMessageReceived:" + dataString);
    }
};

使用外部视频源

如果你的应用使用外部视频源,可以通过以下接口收发 SEI。

External

  1. 调用 GLTextureVideoFrameBuilder-setExternalDataInfo,可设置纹理格式视频数据返回帧的 SEI 数据。

  2. 调用 CpuBufferVideoFrameBuilder-setExternalDataInfo ,可设置 CpuBuffer 视频帧的 SEI 数据。

  3. 调用 pushExternalVideoFrame,可将视频帧数据用 VideoFrame 类封装后传递给 SDK。

  4. 调用 getExternalDataInfo,可获取 SEI 数据。

纯音频通话方案

纯音频通话应用除了可以采用通用方案通过黑帧发送 SEI,也可以通过音频 RTP 扩展头发送数据信息。本方案可实现比通用方案更高的同步精度,理论上可以做到 0~20ms。

RTP

  1. 调用 sendStreamSyncInfo 发送 SEI 。
  • 支持的最大 SEI 传输长度为 255B,如对消息长度有更高要求,请参看通用方案。
  • RTC 用户的 SEI 数据不会推到 CDN 流中。
  • 调用频率为单个 SDK 50 次每秒。
private void sendMsg(String msg) {
    StreamSycnInfoConfig config = new StreamSycnInfoConfig(StreamIndex.STREAM_INDEX_MAIN, 0, StreamSycnInfoConfig.SyncInfoStreamType.SYNC_INFO_STREAM_TYPE_AUDIO); //0 表示不重复
    rtcVideo.sendStreamSyncInfo(msg.getBytes(StandardCharsets.UTF_8), config);
}
  1. 调用成功后,远端收到 SEI 回调: onStreamSyncInfoReceived
IRTCVideoEventHandler rtcVideoEventHandler = new IRTCVideoEventHandler() {
    @Override
    public void onStreamSyncInfoReceived(RemoteStreamKey streamKey, StreamSycnInfoConfig.SyncInfoStreamType streamType, ByteBuffer data) {
    // 处理接收到的 SEI
        super.onStreamSyncInfoReceived(streamKey, streamType, data);
        Charset charset = Charset.defaultCharset();
        String dataString = charset.decode(data).toString();
    }
};

转推直播方案

随合流视频发送 SEI,适合更新频率低的信息,例如用户主播人数变化后切换布局、放置 PK 血条位置等。
转推直播的集成指南和完整示例代码参见转推直播。本节将着重介绍转推直播中的 SEI 插入和提取。

更新频率高的消息,例如音量、PK 血条等信息,建议在各嘉宾的客户端添加,参考通用方案。

  1. 构造 SEI 消息。合流的 SEI 结构示例如下,你可以将自定义消息赋值给 app_data
{
    "app_data": "自定义消息",
    "canvas": {
        "bgnd": "#000000",
        "h": 640,
        "w": 360
    },
    "regions": [
        {
            "alpha": 1.0,
            "contentControl": 0,
            "height": 640,
            "locationX": 0,
            "locationY": 50,
            "renderMode": 1,
            "uid": "user_343",
            "width": 360,
            "zorder": 0
        }
    ],
    "ts": 1705994199709
}
  1. 主持人端调用 startPushMixedStreamToCDNupdatePushMixedStreamToCDN 接口发起和更新转推直播任务时,合流布局和背景等信息作为 SEI 透传到 RTMP 流中。

合流的布局更新通知,也将通过 SEI 。

MixedStreamConfig.MixedStreamLayoutConfig layoutConfig = new MixedStreamConfig.MixedStreamLayoutConfig();
layoutConfig.setRegions(getLayoutRegions());
// 合流用户透传的额外数据,通过拉流端 SEI 接收
layoutConfig.setUserConfigExtraInfo(msg);
layoutConfig.setBackgroundColor("#000000");
mixedStreamConfig.setLayout(layoutConfig);
  1. 观众端解析 RTMP 流中的 SEI 信息,进行处理。你可以参考以下示例:

示例项目

SEI 通用方案

音频 RTP 扩展头

API 参考

AndroidiOSmacOSWindowsLinuxElectronFlutterUnityWeb
发送 SEIsendSEIMessagesendSEIMessage:andMessage:andRepeatCount:andCountPerFrame:sendSEIMessage:andMessage:andRepeatCount:andCountPerFrame:sendSEIMessagesendSEIMessagesendSEIMessagesendSEIMessageSendSEIMessagesendSEIMessage
接收 SEIonSEIMessageReceivedrtcEngine:onSEIMessageReceived:andMessage:rtcEngine:onSEIMessageReceived:andMessage:onSEIMessageReceivedonSEIMessageReceivedonSEIMessageReceivedonSEIMessageReceivedOnSEIMessageReceivedEventHandleronSEIMessageReceived
将 SEI 插入外部视频源GLTextureVideoFrameBuilder-setExternalDataInfoextendedDataextendedDataextra_data
获取外部视频源携带 SEIgetExternalDataInfoonFrame:onFrame:getExtraDataInfo
音频扩展头发送数据消息sendStreamSyncInfosendStreamSyncInfo:config:sendStreamSyncInfo:config:sendStreamSyncInfosendStreamSyncInfosendStreamSyncInfosendStreamSyncInfoSendStreamSyncInfo
接收音频扩展头数据消息onStreamSyncInfoReceivedrtcEngine:onStreamSyncInfoReceived:streamType:data:rtcEngine:onStreamSyncInfoReceived:streamType:data:onStreamSyncInfoReceivedonStreamSyncInfoReceivedonStreamSyncInfoReceivedonStreamSyncInfoReceivedOnStreamSyncInfoReceivedEventHandler
发起转推直播startPushMixedStreamToCDNstartPushMixedStreamToCDN:mixedConfig:observer:startPushMixedStreamToCDN:mixedConfig:observer:startPushMixedStreamToCDNstartPushMixedStreamToCDNstartPushMixedStreamToCDNstartLiveTranscoding
更新转推直播updatePushMixedStreamToCDNupdatePushMixedStreamToCDN:mixedConfig:updatePushMixedStreamToCDN:mixedConfig:updatePushMixedStreamToCDNupdatePushMixedStreamToCDNupdatePushMixedStreamToCDNupdateLiveTranscoding

功能变更日志

  1. 自客户端 SDK 3.27 起,支持在直播流中发送和接收 SEI 的功能。

常见问题

1. 使用外部采集和渲染收不到 onSEIMessageReceived 回调,如何获取 SEI 信息?

只有通过 sendSEIMessage 发送 SEI 消息时,才能通过 onSEIMessageReceived 获取 SEI。使用外部采集和渲染的收发 SEI 方法参见 外部视频源

2. 纯音频通话场景发送 SEI 收不到 onSEIMessageReceived 回调?

在纯音频通话下调用 sendSEIMessage 发送 SEI 时, SDK 将自动生成黑帧视频流。如果当前的发布、订阅模式为手动,需要分别发布和订阅携带 SEI 的黑帧视频流。否则,将无法收到 onSEIMessageReceived 回调。

3. Web 端发送 SEI 的兼容性

参见 Web SDK 浏览器兼容性和已知问题

4. 如何通过服务端 API 在转推直播流中插入 SEI

服务端 Open API StartTranscode 当前不支持插入 SEI。参考转推直播方案,在客户端发送 SEI。