In audio and video streaming, supplemental enhancement information (SEI) is the text data inserted into the audio and video bitstream to convey extra information, which can be received in accurate synchronization with the related audio and video content.
You can use SEI for various purposes. For example:
For more details about SEI, see How to understand and use supplementation enhancement information.
Before you begin, make sure you complete the following:
Create a project in ZEGOCLOUD Admin Console and get the AppID and AppSign of your project.
Refer to the Quick Start doc to complete the SDK integration and basic function implementation.
The following diagram shows the API call sequence of sending and receiving SEI messages.
On the stream publisher side, follow these steps to send SEI messages:
Call the createEngine
method to create a ZegoExpressEngine
instance.
Call the loginRoom
method to log in to a room.
Call the startPublishingStream
method to start publishing a stream.
After the stream publishing starts successfully, call the sendSEI
method to send SEI messages when needed.
On the stream subscriber side, follow these steps to receive SEI messages:
createEngine
method to create a ZegoExpressEngine
instance.IZegoEventHandler
instance, and override the onPlayerRecvSEI
method to implement your SEI message processing logic. setEventHandler
method with the IZegoEventHandler
instance created in the previous step passed in as the eventHandler
parameter.loginRoom
method to log in to a room.startPlayingStream
method to start playing a stream.onPlayerRecvSEI
callback to process the message.By default, the ZEGO Express SDK uses a ZEGO-defined SEI type (NALU Type = 6, Payload Type = 243) for packaging SEI messages. This SEI type isn't defined in the SEI types of the SDK's video codes and doesn't mix up with the existing SEI data of the source video file.
But if you use a third-party decoder like FFmpeg, the SEI messages with the ZEGO-defined SEI type can't be decoded correctly. To solve this issue, you need to call the setSEIConfig
method to change the SEI type to the UserUnregister type (NALU Type = 6, Payload Type = 5).
As SEI data with Payload Type 5 can also be generated by the video encoder or may exist in the source video file, when you send SEI with Payload Type 5, you need a mechanism to differentiate your SEI data from the SEI data generated by the video encoder itself. For this purpose, you can configure a UUID (16 bytes in length) as an SEI filtering keyword for the ZegoExpressEngine
. On the stream publisher side, pass "UUID + message content" as the buffer to the sendSEI
method when sending SEI messages. On the stream subscriber side, the SDK only throws out those SEI messages that start with the configured UUID. If no UUID is configured, the SDK throws out all received SEI messages.
Function prototype:
/**
* Sets the supplemental enhancement information (SEI) type
*
* The SEI type must be set before stream publishing starts.
*
* @param config: The SEI configuration object. By default, the ZEGO Express SDK uses the ZEGO-defined SEI type to package SEI messages.
*/
public void setSEIConfig(ZegoSEIConfig config);
Sample code:
// Configure the SDK to use the UserUnregister SEI type (NALU Type = 6, Payload Type = 5).
ZegoSEIConfig seiConfig = new ZegoSEIConfig();
seiConfig.type = ZegoSEIType.USER_UNREGISTER;
engine.setSEIConfig(seiConfig);
// Set up the advancedConfig property to configure a UUID for filtering SEI messages. With this setup, the SDK on the stream subscriber side only throws out those SEI messages of which the first 12 bytes match the configured UUID.
ZegoEngineConfig engineConfig = new ZegoEngineConfig();
// The first 12 bytes of SEI messages by the stream subscribers through the [onPlayerRecvSEI] callback are always "zegozegozego".
engineConfig.advancedConfig.put("unregister_sei_filter", "zegozegozego");
ZegoExpressEngine.setEngineConfig(engineConfig);
// Start publishing a stream.
engine.startPublishingStream("STREAM_ID");
On the stream publisher side, after the stream publishing starts successfully, you can call the sendSEI
method to send SEI messages when needed.
Funcation prototype:
/**
* Sends supplemental enhancement information (SEI)
*
* You can use this method to send extra text information alongside the audio and video stream being published for various purposes.
* For example, you can use SEI to include video layout information in a video stream or send lyrics text in synchronization with the audio and video content.
* After the stream publisher sends an SEI message, the stream subscribers can receive it by listening for the [onPlayerRecvSEI] callback.
* SEI messages are packaged as part of the bitstream of the audio/video frames, which can be lost because of network problems. To solve such potential issues, you can send the same SEI message several times with a limited frequency.
* Frequency limit: No more than 30 times per second.
* The maximum length of the SEI data is 4096 bytes.
* @param data: SEI data
*/
public void sendSEI(byte[] data)
Sample code:
/** Define a ZegoExpressEngine object */
ZegoExpressEngine engine;
ZegoEngineProfile profile = new ZegoEngineProfile();
/** AppID format: 123456789L */
profile.appID = appID;
/** General scenario */
profile.scenario = ZegoScenario.GENERAL;
/** Set application object of App */
profile.application = getApplication();
/** Create a ZegoExpressEngine instance */
engine = ZegoExpressEngine.createEngine(profile, null);
// Log in to a room.
engine.loginRoom("roomid", new ZegoUser("userid_1"));
// Start publishing a stream.
engine.startPublishingStream("streamid");
// Implement other business logic.
...;
// Send SEI messages when needed.
engine.sendSEI("12345".getBytes());
On the stream subscriber side, after the stream playback starts successfully, the SDK triggers the onPlayerRecvSEI
callback when an SEI message is received.
Function prototype:
/**
* The callback triggered when a supplemental enhancement information (SEI) message is received
*
* After the stream playback starts successfully, the SDK triggers this callback when an SEI message is received.
* If a subscriber subscribes to the audio stream only, it can't receive any SEI messages.
* @param data: SEI content
* @param streamID: Stream ID
*/
public void onPlayerRecvSEI(String streamID, byte[] data){
}
Sample code:
/** Define a ZegoExpressEngine object */
ZegoExpressEngine engine;
ZegoEngineProfile profile = new ZegoEngineProfile();
/** AppID format: 123456789L */
profile.appID = appID;
/** General scenario */
profile.scenario = ZegoScenario.GENERAL;
/** Set application object of App */
profile.application = getApplication();
/** Create a ZegoExpressEngine instance */
engine = ZegoExpressEngine.createEngine(profile, null);
// Create an IZegoEventHandler object, and override the onPlayerRecvSEI method to implement your SEI message processing logic.
IZegoEventHandler handler = new IZegoEventHandler(){
// Listen for other callbacks.
...;
// Listen for the callback that is triggered when an SEI message is received.
public void onPlayerRecvSEI(String streamID, byte[] data) {
// Implement your SEI processing logic. For example, present the related UI components.
...;
}
}
// Set up the event handler.
engine.setEventHandler(handler);
// Log in to a room.
engine.loginRoom("roomid", new ZegoUser("userid_2"));
// Start playing a stream.
engine.startPlayingStream("streamid", canvas);
// Implement other business logic.
...;