グループ通話のメディアサブスクリプション
Planet Cloudプラットフォームにグループ通話のメディアサブスクリプションをリクエストし、メディアデータを受信するための連携方法について説明します。
概要
グループ通話のメディアサブスクリプションをリクエストするためには、サブスクリプションクライアント(WebSocketクライアント)を実装する必要があります。グループ通話のメディアサブスクリプションは、以下のように動作します。
- サブスクリプションクライアントがグループ通話のメディアサブスクリプションをリクエストするために、Planet Cloudのゲートウェイサーバーに認証をリクエストします。
- ゲートウェイサーバーは、認証後にサブスクリプショントークンを作成し、サブスクリプションクライアントに送ります。
- サブスクリプションクライアントがPlanet Cloudのサブスクリプションサーバーにグループ通話のメディアサブスクリプションをリクエストします。
- サブスクリプションサーバーは、サブスクリプションクライアントからのリクエストによって設定されたWebSocketの接続を使用して、グループ通話のメディアをサブスクリプションクライアントに送ります。
下図は、グループ通話のメディアサブスクリプションの連携構造を示しています。
アプリサーバーにサブスクリプションクライアントの機能を含める実装も可能です。この場合、アプリサーバーがゲートウェイサーバーやサブスクリプションサーバーと直接相互作用することになります。
このドキュメントでは、アプリサーバーとサブスクリプションクライアントが別々に実装されていることを前提に連携方法を説明します。
APIの呼び出し順
下図は、グループ通話のメディアサブスクリプションをリクエストし、メディアデータを受信するためのAPIの呼び出し順を示しています。
ゲートウェイサーバーAPIの仕様
ここでは、認証のためにゲートウェイサーバーからサブスクリプショントークンを取得するAPIについて説明します。
アクセス情報
環境 | 基準URL |
---|---|
Evaluation | https://vpnx-stn-api.line-apps-rc.com |
認証について詳しくは、基本プロトコルを参照してください。
API説明
サブスクリプションサーバーに接続するためのサブスクリプショントークンを取得します。
トークンの有効期間は、以下のとおりです。
環境 | トークンの有効期間 |
---|---|
Evaluation | 1日 |
Real | 1日 |
メソッドとエンドポイント
-
メソッド:GET
-
エンドポイント
/tas/v1/gcall/{serviceId}/{roomId}/subs/token
ヘッダー
- Authorization:
Basic {your credential}
- Content-Type:text/plain
パスパラメーター
パラメーター | 説明 |
---|---|
serviceId | サービスID |
roomId | ルームID |
クエリ
なし
レスポンス
サブスクリプショントークン
サンプルコード
curl --location --request GET 'https://vpnx-stn-api.line-apps-rc.com/tas/v1/gcall/planetkit-inhouse/1024/subs/token' \
--header 'Authorization: Basic em45eEkxRnROYlZwYlNXWFo1U2ZCWmhucF85dHFGaXBod2h0TjdNLTdTWHlFbllQalB2dUVKRXBDdkx5OU1tRWlHUEI2clpITjdvSVA3UXVWSE5sN3BmeHlObkxlRld0dkFCT2p4MkpCbXBROFZPVXZmMU11dVZ3QWtfdGU2cUh0OFVpV250TzZaZzZqdWIteWdtRnNBOjc4YTQwN2JjOGM0NjljZjE3MjI2MWVmY2E0MWJmODBlYzY5ODM1ZTY1MDk0YTJjZjc2YzAxYWE5N2U5Y2Q1MWU=' \
--header 'Content-Type: text/plain'
eea3091e49674a13a3091e49671a13c7
発生し得るHTTPステータスコード
発生する可能性のあるHTTPステータスコードは、以下のとおりです。詳しくは、エラー処理を参照してください。
- 400、401、403、404、429、500、503
サブスクリプションサーバーAPIの仕様
ここでは、グループ通話のメディアサブスクリプションを処理するAPIについて説明します。
アクセス情報
環境 | 基準URL |
---|---|
Evaluation | wss://voipnx-rhea.line-apps-rc.com |
API説明
session_id
をパスパラメーターとしてWebSocketの接続をリクエストします。
- WebSocket接続後、1秒以内に有効なメッセージが受信されない場合、接続が終了します。
- サブスクリプションクライアントがサーバーからPING(opcode 0x09)メッセージを受信したら、接続を維持するためにサブスクリプションクライアントは、即時にPONG(opcode 0x0a)メッセージでレスポンスしなければなりません。
サブスクリプションサーバーは、高可用性をサポートしていません。サブスクライブ中にネットワークやサーバーのトラブルによりWebSocketの接続が切断した場合、サブスクリプションクライアントはWebSocketの接続を再設定し、サブスクリプションを再度リクエストしなければなりません。
メソッドとエンドポイント
-
メソッド:GET
-
エンドポイント
/subs_gcall/{session-id}
制御メッセージ
制御メッセージは、WebSocketのテキストopcodeを使用して転送されます。制御メッセージには、以下のような特徴があります。
- JSON形式を使用する
- ヘッダーと本文とで構成される
ヘッダー
フィールド | データ型 | 説明 |
---|---|---|
msg_id | Number | - SubscribeGroupcallMediaReq = 1- SubscribeGroupcallMediaRsp = 2- UnsubscribeGroupcallMediaReq = 3- UnsubscribeGroupcallMediaRsp = 4- AbortGroupcallMediaSubscriptionRpt = 5- ChangeGroupcallMediaSubscriptionReq = 6- ChangeGroupcallMediaSubscriptionRsp = 7- UpdateGroupcallMediaContributorsRpt = 8- NotifyGroupcallUserStatusRpt = 9 |
sess_id | String | サブスクリプションクライアントが作成したセッションID |
SubscribeGroupcallMediaReq
(msg_id
:1)
このメッセージは、Planet Cloudにグループ通話のメディアデータをサブスクライブするようリクエストします。
このメッセージでリクエストする前に、Planet Cloudゲートウェイサーバーに認証をリクエストし、subsToken
を取得する必要があります。
メッセージ本文
フィールド | データ型 | 説明 | 備考 |
---|---|---|---|
service_id | String | サービスID | |
room_id | String | ルームID | |
credential | String | Base64でエンコードされた文字列 | |
media_type | Array(String要素) | メディアタイプのリスト、A はオーディオ、V はビデオを示す | 対応可能な値は、以下のとおりです。 - A - A, V ビデオのみのモードには対応していません。 |
stream_type | String | 受信するストリームのタイプ - MIX :リクエストした対象に対する混合ストリームを提供- MULTI :リクエストした対象に対し、IDごとのストリームを提供 | media_type による対応の可否は、以下のとおりです。- A :MIX 、MULTI - A, V :MIX |
target_type | String | サブスクリプション対象タイプ - MAIN_ROOM :メインルームのサブスクリプション- SUBGROUP :サブグループのサブスクリプション- TRANSLATE :翻訳ルームおよびサブグループのサブスクリプション | このフィールドは、stream_type がMIX のときのみ有効になります。 |
subgroup_name | String | サブスクライブするサブグループの名前 | このフィールドは、target_type がSUBGROUP のときのみ有効になります。 |
target_user_ids | Array(String要素) | サブスクライブするユーザーIDリスト | target_user_ids フィールドが存在しない、または該当フィールドに項目がない場合、すべての参加者がサブスクリプションの対象になります。target_type がMAIN_ROOM の場合はメインルームの参加者が選択されます。SUBGROUP の場合は、サブグループの参加者が選択されます。target_type がTRANSLATE の場合、target_user_ids は許可されません。target_user_ids に設定できる最大の要素数は16です。 |
layout_type | String | ビデオミキシングのためのレイアウトタイプ。詳しくは、レイアウトタイプを参照してください。 | このフィールドは、media_type にV (ビデオ)が含まれているときのみ有効になります。 |
max_display_num | Number | - グリッドビュー:1 - フォーカスビュー:1 - プレゼンテーションビュー:1~8 | ビデオに表示できる参加者の最大数は、レイアウトタイプによって異なります。グリッドビューの場合、最大で16です。 |
auto_screenshare | Bool | 画面共有を開始する際に自動でプレゼンテーションビューに切り替えるかどうか | |
no_target_users_timeout | Number | target_user_ids パラメーターが設定されている場合、ルームに対象ユーザーが存在しなかったときにサブスクリプションのセッションを維持する最大時間(秒単位) | サブスクリプションクライアントがこの値を設定しなかった場合、サブスクリプションセッションはシステム設定によって終了されます。 |
target_type
がSUBGROUP
の場合の注意事項1つのサブスクリプションセッションでは、1つのサブグループのみをサブスクライブできます。
メインルームに作成された他のサブグループをサブスクライブするためには、新しいサブスクリプションセッションを設定し、そのサブグループに対してサブスクリプションをリクエストする必要があります。
レイアウトタイプ
layout_type
フィールドに使用できる値は、以下のとおりです。
layout_type の値 | target_user_ids 値の有無 | 説明 |
---|---|---|
TALKER_GRID_VIEW | N | 新しい発言者が優先になるグリッドビューです。 新しい発言者がレイアウトに入る必要がある状況で、スペースがない場合、最も長い間発言していない参加者が除外されます。 |
Y | target_user_ids が指定されている場合、該当ユーザーのみレイアウトに含まれます。 | |
ORDERED_GRID_VIEW | N | 使用不可 |
Y | target_user_ids 要素の順番によって、レイアウト順が決まるグリッドビューです。 | |
TALKER_FOCUS_VIEW | N | 新しい発言者が優先になるフォーカスビューです。 新しい発言者は全画面領域に表示され、以前の発言者は1番目のサムネイル領域に移動します。 サムネイルビューがいっぱいになった場合は、最も長い間発言していない参加者が除外されます。 |
Y | target_user_ids が指定されている場合、該当ユーザーのみレイアウトに含まれます。新しい発言者は全画面領域に表示され、以前の発言者は1番目のサムネイル領域に移動します。 | |
ORDERED_FOCUS_VIEW | N | 使用不可 |
Y | target_user_ids 要素の順番によって、レイアウト順が決まるフォーカスビューです。target_user_ids の1番目のユーザーが全画面領域に表示され、以前の発言者は1番目のサムネイル領域へ移動します。 |
サンプルコード
{
"header": {
"msg_id": 1,
"sess_id": "sid343213"
},
"body": {
"service_id": "planet",
"room_id": "RID_xlkjds",
"credential": "YW55IGNhcm5hbCBwbGVhcw==",
"media_type": ["A"],
"stream_type": "MULTI",
"target_type": "MAIN_ROOM"
}
}
{
"header": {
"msg_id": 1,
"sess_id": "sid343213"
},
"body": {
"service_id": "planet",
"room_id": "RID_xlkjds",
"credential": "YW55IGNhcm5hbCBwbGVhcw==",
"media_type": ["A", "V"],
"stream_type": "MIX",
"target_type": "MAIN_ROOM",
"layout_type": "TALKER_GRID_VIEW"
}
}
サブスクリプションリクエストの認証情報の計算
グループ通話のメディアサブスクリプションをリクエストする際には、リクエスト本文にcredential
フィールドの値として、以下の計算値を含める必要があります。
credential
値:Planetゲートウェイサーバーで作成されたsubsToken
値とグループ通話関連の情報を入力値とし、SHA-256ハッシュアルゴリズムで計算した値
サブスクリプションサーバーは、リクエスト本文のcredential
値を使用して、認証されたサブスクリプションリクエストであるかどうかを確認します。
入力値
serviceID
roomID
subsToken
実装サンプルの擬似コード
credential calculation
#define AUTH_DELIM "::"
#define SHA256_HASHLEN 32
typedef unsigned char SHA256_HASH[SHA256_HASHLEN];
SHA256_CTX ctx;
SHA256_HASH SHA256_HA;
SHA256_Init(&ctx);
SHA256_Update(&ctx, svc_id, strlen(svc_id));
SHA256_Update(&ctx, AUTH_DELIM, strlen(AUTH_DELIM));
SHA256_Update(&ctx, room_id, strlen(room_id));
SHA256_Update(&ctx, AUTH_DELIM, strlen(AUTH_DELIM));
SHA256_Update(&ctx, subs_token, strlen(subs_token));
SHA256_Final(SHA256_HA, &ctx)
Javaサンプルコード
import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.binary.Base64;
import com.google.common.hash.Hashing;
public class SubsUtils {
public static final String del = "::";
public static String makeCredential(String svcId, String roomId, String subsToken) {
byte[] hash = Hashing.sha256()
.newHasher()
.putString(svcId, StandardCharsets.UTF_8)
.putString(del, StandardCharsets.UTF_8)
.putString(roomId, StandardCharsets.UTF_8)
.putString(del, StandardCharsets.UTF_8)
.putString(subsToken, StandardCharsets.UTF_8)
.hash()
.asBytes();
String base64EncodedCredential = new String(Base64.encodeBase64(hash));
return base64EncodedCredential;
}
}
SubscribeGroupcallMediaRsp
(msg_id
:2)
グループ通話のメディアサブスクリプションのリクエストに対するレスポンスメッセージです。サブスクリプションサーバーで作成されたsubs_id
と、転送可能なメディアフォーマットの詳細情報が含まれています。メディアデータがWebSocketのバイナリopcodeを通じて転送される際には、メディアデータメッセージ形式で渡されます。
メッセージ本文
フィールド | データ型 | 説明 | 備考 |
---|---|---|---|
result | String | APIの結果 - success - fail | |
subs_id | Number | サブスクリプションサーバーによって作成されたサブスクリプションID | result がsuccess の場合に値が存在します。 |
audio_payload_info | Array(Audio PayloadInfo Object要素) | オーディオパケットを示すpt (ペイロードタイプ)値に関する詳細情報 | result がsuccess の場合に値が存在します。 |
video_payload_info | Array(Video PayloadInfo Object 要素) | オーディオパケットを示すpt 値に関する詳細情報 | result がsuccess の場合に値が存在します。 |
error_code | Number | エラーコード。詳しくは、エラーコードを参照してください。 | result がfail の場合に値が存在します。 |
error_desc | String | エラーに関する詳細な説明 | result がfail の場合に値が存在します。 |
Audio PayloadInfo Object
名前 | タイプ | 説明 | 例示 |
---|---|---|---|
pt | Number | ペイロードタイプID | 120 |
codec | String | オーディオコーデック名 | "opus" |
clock_rate | Number | クロックレート | 48000 |
channels | Number | オーディオチャネル数 | 1 |
ptime | Number | パケット化の間隔時間(ミリ秒) | 20 |
Video PayloadInfo Object
名前 | タイプ | 説明 | 例示 |
---|---|---|---|
pt | Number | ペイロードタイプID | 121 |
codec | String | ビデオコーデック名 | "H264" |
clock_rate | Number | クロックレート | 90000 |
サンプルコード
{
"header": {
"msg_id": 2,
"sess_id": "sid343213"
},
"body": {
"result": "success",
"subs_id": 2394872139847981,
"audio_payload_info": [
{
"pt": 120,
"codec": "opus",
"clock_rate": 48000,
"channels": 1,
"ptime": 20
}
]
}
}
{
"header": {
"msg_id": 2,
"sess_id": "sid343213"
},
"body": {
"result": "success",
"subs_id": 2394872139847981,
"audio_payload_info": [
{
"pt": 120,
"codec": "opus",
"clock_rate": 48000,
"channels": 1,
"ptime": 20
}
],
"video_payload_info": [
{
"pt": 121,
"codec": "H264",
"clock_rate": 90000
}
]
}
}
{
"header": {
"msg_id": 2,
"sess_id": "sid343213"
},
"body": {
"result": "fail",
"error_code": 100,
"error_desc": "Authentication failed"
}
}
UnsubscribeGroupcallMediaReq
(msg_id
:3)
グループ通話のメディアサブスクリプションの中断をリクエストするメッセージです。
メッセージ本文
フィールド | データ型 | 説明 |
---|---|---|
service_id | String | サービスID |
room_id | String | ルームID |
subs_id | Number | サブスクリプションサーバーで作成されたサブスクリプションID |
サンプルコード
{
"header": {
"msg_id": 3,
"sess_id": "sid343213"
},
"body": {
"service_id": "planet",
"room_id": "RID_xlkjds",
"subs_id": 2394872139847981
}
}
UnsubscribeGroupcallMediaRsp
(msg_id
:4)
グループ通話のメディアサブスクリプションの中断リクエストに対するレスポンスメッセージです。
メッセージ本文
フィールド | データ型 | 説明 | 備考 |
---|---|---|---|
result | String | APIの結果 - success - fail | |
error_code | Number | エラーコード。詳しくは、エラーコードを参照してください。 | result がfail の場合に値が存在します。 |
error_desc | String | エラーに関する詳細な説明 | result がfail の場合に値が存在します。 |
サンプルコード
{
"header": {
"msg_id": 4,
"sess_id": "sid343213"
},
"body": {
"result": "success",
}
}
AbortGroupcallMediaSubscriptionRpt
(msg_id
:5)
Planet Cloud GroupCallサーバーで発生したイベントによってサブスクリプションが中断された場合、サブスクリプションクライアントにそれを通知するためのメッセージです。
メッセージ本文
フィールド | データ型 | 説明 |
---|---|---|
error_code | Number | エラーコード。詳しくは、エラーコードを参照してください。 |
error_desc | String | エラーの詳細な説明 |
サンプルコード
{
"header": {
"msg_id": 5,
"sess_id": "sid343213"
},
"body": {
"error_code": 2,
"error_desc": "Group call has been ended"
}
}
ChangeGroupcallMediaSubscriptionReq
(msg_id
:6)
このメッセージは、メディアサブスクリプション情報を変更する際に使用されます。以下の項目をアップデートできます。
- ビデオミキシングのレイアウトタイプ
メッセージ本文
フィールド | データ型 | 説明 | 備考 |
---|---|---|---|
service_id | String | サービスID | |
room_id | String | ルームID | |
subs_id | Number | サブスクリプションサーバーで作成されたサブスクリプションID | |
layout_type | String | ビデオミキシングのためのレイアウトタイプ | このフィールドは、media_type にV (ビデオ)が含まれている場合のみ有効となります。 |
サンプルコード
{
"header": {
"msg_id": 6,
"sess_id": "sid343213"
},
"body": {
"service_id": "planet",
"room_id": "RID_xlkjds",
"subs_id": 2394872139847981,
"layout_type": "TALKER_FOCUS_VIEW"
}
}
ChangeGroupcallMediaSubscriptionRsp
(msg_id
:7)
サブスクリプション情報の変更結果を返すメッセージです。
メッセージ本文
フィールド | データ型 | 説明 | 備考 |
---|---|---|---|
result | String | APIの結果 - success - fail | |
error_code | Number | エラーコード。詳しくは、エラーコードを参照してください。 | result がfail の場合に値が存在します。 |
error_desc | String | エラーに関する詳細な説明 | result がfail の場合に値が存在します。 |
サンプルコード
{
"header": {
"msg_id": 7,
"sess_id": "sid343213"
},
"body": {
"result": "success",
}
}
UpdateGroupcallMediaContributorsRpt
(msg_id
:8)
stream_type
がMIX
で、混合メディアに含まれているuser_id
リストに変更がある場合、アップデートされたuser_id
リストが、このメッセージを通じてサブスクリプションクライアントに転送されます。
メッセージ本文
フィールド | データ型 | 説明 | 例 |
---|---|---|---|
pt | Number | ペイロードタイプID | 120 (オーディオ)または121 (ビデオ) |
ts | Number | RTPタイムスタンプ | |
seq | Number | RTPシーケンス番号 | |
user_ids | Array(String要素) | user_id リスト |
サンプルコード
{
"header": {
"msg_id": 8,
"sess_id": "sid343213"
},
"body": {
"pt": 120,
"ts": 3475364964,
"seq": 30968,
"user_ids": ["user1", "user2", "user3"]
}
}
NotifyGroupcallUserStatusRpt
(msg_id
:9)
サブスクリプションをリクエスト(SubscribeGroupcallMediaReq
)する際にtarget_user_ids
パラメーターが設定されている場合、このパラメーターに含まれているユーザーがルームに参加またはルームから退出すると、ユーザーのステータス情報がこのメッセージを通じてサブスクリプションクライアントに転送されます。
メッセージ本文
フィールド | データ型 | 説明 |
---|---|---|
enter | Array(String要素) | ルームに参加したユーザーのIDリスト |
leave | Array(String要素) | ルームから退出したユーザーのIDリスト |
サンプルコード
{
"header": {
"msg_id": 9,
"sess_id": "sid343213"
},
"body": {
"enter": ["user1", "user2", "user3"],
"leave": ["user4", "user5"]
}
}
エラーコード
エラーコード | 原因 | 備考 |
---|---|---|
0 | UNDEFINED | |
1 | NO_ERROR | |
2 | GROUPCALL_END | |
100 | AUTHENTICATION_FAIL | |
101 | ROOM_NOT_FOUND | |
102 | SUBSCRIPTION_NOT_SUPPORT | |
103 | INVALID_PARAMETER | |
104 | SUBSCRIPTION_NOT_FOUND | |
105 | INVALID_STATE | |
106 | INVALID_MSG_FORMAT | |
107 | SUBS_CAPA_FULL | |
200 | INTERNAL_SERVER_ERROR | |
201 | WS_DISCONNECTED_BY_PEER | |
202 | WS_PING_PONG_FAIL | |
203 | WS_INITIAL_REQUEST_TIMEOUT | |
1000 | UNKNOWN |
メディアデータメッセージ
メディアデータメッセージは、WebSocketのバイナリopcodeを使用して転送されます。リクエストされたstream_type
によって、以下の2つのタイプで転送されます。
メディアデータメッセージの形式
メディアデータメッセージの形式は、以下のとおりです。
順番 | プロパティ | サイズ | 説明 |
---|---|---|---|
1 | type | 1バイト | データ型 1:RTP(混合オーディオまたはビデオ) 2: user_id が含まれているRTP |
2 | data | 可変長 |
タイプ1:混合オーディオまたはビデオRTP
- 対象
stream_type
:MIX
- 対象
media_type
:A
(オーディオ)またはA, V
(オーディオおよびビデオ) - 混合されたオーディオとビデオは、接続されたWebSocketのセッションを通じて、RTP形式のデータで転送されます。
- オーディオとビデオは、転送されたRTPヘッダーの
pt
(ペイロードタイプ)で区別します。
タイプ1のメディアデータメッセージの形式は、以下のとおりです。
順番 | プロパティ | サイズ |
---|---|---|
1 | オーディオまたはビデオRTP | 可変長 |
タイプ2:特定ユーザーのオーディオRTP
- 対象
stream_type
:MULTI
- 対象
media_type
:A
(オーディオ) - グループ通話に参加する各ユーザーのオーディオデータは、
user_id
情報(ヘッダー)とRTPの形式でサブスクリプションクライアントに転送されます。
タイプ2のメディアデータメッセージの形式は、以下のとおりです。
順番 | プロパティ | サイズ |
---|---|---|
1 | user_id_length | 1バイト |
2 | user_id | 可変長 |
3 | オーディオRTP | 可変長 |
特定ユーザー(グループ通話の参加者)のRTPコンテキスト(タイムスタンプ、シーケンス)は、次の場合に再開されることがあります。
- ユーザーが一定時間発話を中断し、その後発話を再開したとき
- ユーザーが通話ルームに参加、または退出後に再参加し発話を始めたとき