すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo Live:SEI メッセージの送受信

最終更新日:Mar 26, 2026

ARTC SDK は、付帯情報 (SEI) メッセージの送受信をサポートしています。この機能により、RTC システムから Alibaba Cloud CDN ライブストリーミングまたはサードパーティのライブストリーミングプラットフォームにカスタムメッセージを送信できます。

概要

ビデオエンコーディングにおいて、付帯情報 (SEI) は H.264/AVC や H.265/HEVC などのビデオエンコーディング標準の一部であり、ビデオコンテンツに関連する追加情報を送信するために使用されます。この情報により、コンテンツ同期やエラー回復など、受信側で補助機能が有効になります。一般的なユースケースには、正確なビデオレイアウト、同期された歌詞、ライブインタラクティブクイズなどがあります。

image

SEI は、カスタムメッセージを送信するための推奨される方法です。この方法では、メッセージをビデオストリームに埋め込み、ビデオデータとともにチャンネル内の他のユーザーに送信します。

  • メリット:

    • リアルタイム同期: メッセージはビデオストリームと同期されます。

    • 無制限の受信者: ストリームをサブスクライブするすべてのユーザーがメッセージを受信できます。

  • 制限事項:

    • ビデオストリームへの影響を避けるため、各メッセージの最大サイズは 4 KB です。

サンプルコード

ARTC は、ご参照いただけるオープンソースのサンプルプロジェクトを提供しています。プロジェクトをダウンロードするか、以下のリポジトリでコードを表示できます。

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.

事前準備

この機能を実装する前に、以下の要件を満たしていることを確認してください。

実装

SEI メッセージの送信

ビデオストリームを公開した後、sendMediaExtensionMsg API を呼び出して SEI データを送信できます。

API リファレンス

ARTC SDK は、SEI メッセージを送信するための 2 つの API を提供しています。

API

説明

sendMediaExtensionMsg

パラメーター:

  • message: メディア拡張メッセージ。最大サイズは 4096 バイトです。JSON またはプレーンな文字列形式を使用することを推奨します。

  • repeatCount: メッセージを繰り返す回数。これは、ネットワークパケットのドロップによるメッセージ損失を防ぐために冗長性を追加します。-1 の値は、メッセージを無期限に送信します。

  • delay: API の呼び出しからメッセージの送信までのミリ秒単位の遅延。

  • isKeyFrame: メッセージをキーフレームにのみアタッチするかどうかを指定します。true の場合、メッセージはキーフレームにのみアタッチされます。

sendMediaExtensionMsgEx

この API は、payloadType パラメーターを含めることで sendMediaExtensionMsg を拡張し、SEI メッセージタイプを設定します。有効な値は 5 または 100 から 254 までの任意の整数です。payloadType=5 を使用することは、sendMediaExtensionMsg API を呼び出すことと同等です。

説明

一度に転送できるメディア拡張メッセージは 1 つのみです。後続の sendMediaExtensionMsg の呼び出しは、以前のメッセージを上書きします。

以下の例は、sendMediaExtensionMsg API を使用して文字列を SEI メッセージとして送信する方法を示しています。

Android

// チャンネルに参加し、ビデオストリームの公開を開始している必要があります (デフォルトで有効)。
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

// SEI メッセージを送信します。
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);
// SEI メッセージを送信します。
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

/* 必要に応じて以下のパラメーターを指定します。 */
char * data = "xxxxx";
int length = strlen(data);
mAliRtcEngine->SendMediaExtensionMsg(data, length, 1,0,true);

SEI メッセージの受信

チャンネル内のビデオストリームをサブスクライブした後、適切なコールバックを登録することで SEI データを受信できます。

API リファレンス

コールバック

説明

onMediaExtensionMsgReceived

SDK は、SEI メッセージを受信するとこのコールバックをトリガーします。

パラメーター:

  • uid: メッセージを送信したユーザーのユーザーID。

  • payloadType: SEI メッセージのタイプです。 sendMediaExtensionMsg で送信されたメッセージの場合、値は 5 です。 sendMediaExtensionMsgEx で送信されたメッセージの場合、値は特定のタイプです。

  • メッセージ:受信した SEI メッセージ。

Android

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

    handler.post(new Runnable() {
        @Override
        public void run() {
            // メッセージを処理します。
            String receivedMsg = new String(message);
            ToastHelper.showToast(SEIActivity.this, receivedMsg, Toast.LENGTH_SHORT);
            
        }
    });
}

iOS

extension SEIUsageMainVC: AliRtcEngineDelegate {
    
    // SEI メッセージを受信するためのコールバック。
    func onMediaExtensionMsgReceived(_ uid: String, payloadType: Int32, message data: Data) {
        // メッセージを処理します。
        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)")
    }
    // その他のコールバック...

}

Harmony

// SEI メッセージを受信するためのコールバック。
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: ビジネス要件に基づいて処理ロジックをここに追加します。 */
}