Send and receive SEI messages

Updated at:
Copy as MD

The ARTC SDK supports sending and receiving SEI messages. Use this feature to transmit custom messages from the RTC system to Alibaba Cloud CDN or third-party live streaming platforms.

Overview

In video encoding, supplemental enhancement information (SEI) is part of the H.264/AVC and H.265/HEVC standards. SEI carries additional data alongside video content to enable functions such as content synchronization and error recovery. Common use cases include precise video layouts, synchronized lyrics, and live interactive quizzes.

image

SEI is the recommended method for sending custom messages. It embeds messages into the video stream for delivery to other users in the channel.

  • Benefits:

    • Real-time synchronization: Messages are synchronized with the video stream.

    • Unlimited receivers: Any user who subscribes to the stream can receive the messages.

  • Limitations:

    • Maximum message size is 4 KB to avoid impacting the video stream.

Sample code

ARTC provides open-source sample projects. Download or view the code in the following repositories:

Android: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/SEIUsage/SEIActivity.java.

iOS: iOS/ARTCExample/BasicUsage/SEIUsage/SEIUsageVC.swift.

Harmony: Harmony/ARTCExample/entry/src/main/ets/pages/basicusage/SEIPage.ets.

Before you begin

Ensure that you meet the following requirements:

Implementation

Send an SEI message

After publishing a video stream, call the sendMediaExtensionMsg API to send SEI data.

API reference

The ARTC SDK provides two APIs for sending SEI messages.

API

Description

sendMediaExtensionMsg

Parameters:

  • message: The media extension message. Maximum size: 4,096 bytes. Use JSON or plain string format.

  • repeatCount: The number of times to repeat the message for redundancy against packet loss. A value of -1 sends the message indefinitely.

  • delay: The delay in milliseconds between calling the API and sending the message.

  • isKeyFrame: Specifies whether to attach the message only to a keyframe.

sendMediaExtensionMsgEx

Extends sendMediaExtensionMsg with a payloadType parameter for the SEI message type. Valid values: 5 or 100-254. Setting payloadType=5 is equivalent to calling sendMediaExtensionMsg.

Note

Only one media extension message can be in transit at a time. Subsequent calls to sendMediaExtensionMsg overwrite the previous message.

Examples

The following examples send a string as an SEI message by using the sendMediaExtensionMsg API.

Android

// You must have already joined a channel and started publishing a video stream (which is enabled by default).
mSendSEIButton.setOnClickListener(v -> {
    if(mAliRtcEngine == null) {
        return;
    }
    String seiMessage = mEditText.getText().toString();
    if (TextUtils.isEmpty(seiMessage)) {
        return;
    }
    byte[] seiData = seiMessage.getBytes();
    mAliRtcEngine.sendMediaExtensionMsg(seiData,1,0,false);
    // mAliRtcEngine.sendMediaExtensionMsgEx(seiData,1,0,false, 5);
});

iOS

// Send an SEI message.
func sendSEI(seiMessage: String) -> Bool {
    guard let data = seiMessage.data(using: .utf8) else {
        return false
    }
    let repeatCount: Int32 = 1
    let delay: Int32 = 0
    let payloadType: Int32 = 5
    let isKeyFrameOnly = false
    let ret = self.rtcEngine?.sendMediaExtensionMsg(data, repeatCount: repeatCount, delay: delay, isKeyFrame: isKeyFrameOnly)
    // let ret = self.rtcEngine?.sendMediaExtensionMsgEx(data, repeatCount: repeatCount, delay: delay, isKeyFrame: isKeyFrameOnly, payloadType: payloadType)
    debugPrint("sendSEI: \(ret ?? -1)")
    return ret == 0
}

Harmony

const seiData = this.stringToArrayBuffer(this.SendText);
// Send an SEI message.
this.rtcEngine.sendMediaExtensionMsg(seiData, 1, 0, false);

Mac

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
NSDate *datenow = [NSDate date];
NSString *currentTimeString = [formatter stringFromDate:datenow];
NSString *str =@"SEI Test time:" ;

NSString * ExtensionMsg = [str stringByAppendingString:currentTimeString];

NSData *data =[ExtensionMsg dataUsingEncoding:NSUTF8StringEncoding];

int code = [self.engine sendMediaExtensionMsg:data repeatCount:repectCount delay:100 isKeyFrame:true];
NSLog(@"--%d",code);

Windows

/* Specify the following parameters as needed. */
char * data = "xxxxx";
int length = strlen(data);
mAliRtcEngine->SendMediaExtensionMsg(data, length, 1,0,true);

Receive an SEI message

After subscribing to a video stream, receive SEI data by registering the appropriate callback.

API reference

Callback

Description

onMediaExtensionMsgReceived

Triggered when the SDK receives an SEI message.

Parameters:

  • uid: The user ID of the user who sent the message.

  • payloadType: The SEI message type. The value is 5 for messages sent by sendMediaExtensionMsg. For sendMediaExtensionMsgEx, the value matches the specified type.

  • message: The received SEI message.

Examples

Android

@Override
public void onMediaExtensionMsgReceived(String uid, int payloadType, byte[]message) {
    super.onMediaExtensionMsgReceived(uid,payloadType, message);

    handler.post(new Runnable() {
        @Override
        public void run() {
            // Process the message.
            String receivedMsg = new String(message);
            ToastHelper.showToast(SEIActivity.this, receivedMsg, Toast.LENGTH_SHORT);
            
        }
    });
}

iOS

extension SEIUsageMainVC: AliRtcEngineDelegate {
    
    // Callback for receiving an SEI message.
    func onMediaExtensionMsgReceived(_ uid: String, payloadType: Int32, message data: Data) {
        // Process the message.
        guard let message = String(data: data, encoding: .utf8) else {
            print("Failed to parse the message")
            return
        }
        self.showToast(message: "Received SEI: \(message), from uid: \(uid), payloadType: \(payloadType)")
    }
    // Other callbacks...

}

Harmony

// Callback for receiving an SEI message.
listener.onMediaExtensionMsgReceived((uid: string, payloadType: number, message: ArrayBuffer) => {
  console.info(`Received SEI message: uid=${uid}, payloadType=${payloadType}, message=${message}`);
});

Mac

- (void)onMediaExtensionMsgReceived:(NSString *)uid payloadType:(int)payloadType message:(NSData *)data {
    
    NSString * string_message  = [[NSString alloc] initWithBytes:data.bytes length:data.length encoding:NSUTF8StringEncoding];

    NSLog(@"received uid:%@, payloadType: %d, message:%@ size:%lu \n\n", uid, payloadType, string_message, (unsigned long)data.length);
    dispatch_async(dispatch_get_main_queue(), ^{
        NSString *showString = [NSString stringWithFormat:@" uid:%@\n payloadtype:%d message:%@\n size:%lu\n",
                                uid, payloadType, string_message, (unsigned long)data.length];
        _extendinfoL.stringValue = showString;
    });
    
}

Windows

public:
virtual void OnMediaExtensionMsgReceived(const char* uid, const int8_t * message, uint32_t size) override {
    /* TODO: Add your processing logic here based on your business requirements. */
}