본문으로 건너뛰기

그룹 통화 미디어 구독

Planet Cloud 플랫폼에 그룹 통화 미디어 구독을 요청하고 미디어 데이터를 수신하기 위한 연동 방법을 설명합니다.

개요

그룹 통화 미디어 구독을 요청하려면 구독 클라이언트(WebSocket 클라이언트)를 구현해야 합니다. 그룹 통화 미디어 구독은 다음과 같이 작동합니다.

  1. 구독 클라이언트가 그룹 통화 미디어 구독을 요청하기 위해 Planet Cloud의 게이트웨이 서버에 인증을 요청합니다.
  2. 게이트웨이 서버는 인증 후 구독 토큰을 생성하여 구독 클라이언트에게 보냅니다.
  3. 구독 클라이언트가 Planet Cloud의 구독 서버에 그룹 통화 미디어 구독을 요청합니다.
  4. 구독 서버는 구독 클라이언트의 요청에 따라 설정된 WebSocket 연결을 사용하여 그룹 통화 미디어를 구독 클라이언트에게 보냅니다.

다음 그림은 그룹 통화 미디어 구독의 연동 구조를 보여줍니다.

그룹 통화 미디어 구독 연동 구조 다이어그램

Note

앱 서버가 구독 클라이언트 기능을 포함하도록 구현할 수도 있습니다. 이 경우 앱 서버가 게이트웨이 서버 및 구독 서버와 직접 상호 작용하게 됩니다.

이 문서에서는 앱 서버와 구독 클라이언트가 별도로 구현되어 있다고 가정하고 연동 방법을 설명합니다.

API 호출 순서

아래 다이어그램은 그룹 통화 미디어 구독을 요청하고 미디어 데이터를 수신하기 위한 API 호출 순서를 보여줍니다.

그룹 통화 미디어 구독 API 호출 순서

게이트웨이 서버 API 사양

여기서는 인증을 위해 게이트웨이 서버에서 구독 토큰을 가져오는 API에 대해 설명합니다.

접근 정보

환경기준 URL
Evaluationhttps://vpnx-stn-api.line-apps-rc.com

인증과 관련된 상세 정보는 기본 프로토콜을 참고하세요.

API 설명

구독 서버에 연결하기 위한 구독 토큰을 가져옵니다.

토큰 유효 기간은 다음과 같습니다.

환경토큰 유효 기간
Evaluation1일
Real1일

메서드와 엔드포인트

  • 메서드: 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
Evaluationwss://voipnx-rhea.line-apps-rc.com

API 설명

session_id를 경로 파라미터로 사용하여 WebSocket 연결을 요청합니다.

  • WebSocket 연결 후 1초 이내에 유효한 메시지가 수신되지 않으면 연결이 종료됩니다.
  • 구독 클라이언트는 서버로부터 PING(opcode 0x09) 메시지를 수신하면 연결을 유지하기 위해 즉시 PONG(opcode 0x0a) 메시지로 응답해야 합니다.
Warning

구독 서버는 고가용성을 지원하지 않습니다. 구독 중에 네트워크나 서버 문제로 인해 WebSocket 연결이 끊어진 경우 구독 클라이언트는 WebSocket 연결을 다시 설정하고 구독을 다시 요청해야 합니다.

메서드와 엔드포인트

  • 메서드: GET

  • 엔드포인트

    /subs_gcall/{session-id}

제어 메시지

제어 메시지는 WebSocket의 텍스트 opcode를 사용하여 전달됩니다. 제어 메시지에는 다음과 같은 특징이 있습니다.

  • JSON 형식을 사용합니다.
  • 헤더와 본문으로 구성됩니다.

헤더

필드데이터 유형설명
msg_idNumber- SubscribeGroupcallMediaReq = 1
- SubscribeGroupcallMediaRsp = 2
- UnsubscribeGroupcallMediaReq = 3
- UnsubscribeGroupcallMediaRsp = 4
- AbortGroupcallMediaSubscriptionRpt = 5
- ChangeGroupcallMediaSubscriptionReq = 6
- ChangeGroupcallMediaSubscriptionRsp = 7
- UpdateGroupcallMediaContributorsRpt = 8
- NotifyGroupcallUserStatusRpt = 9
sess_idString구독 클라이언트가 생성한 세션 ID

SubscribeGroupcallMediaReq (msg_id: 1)

이 메시지는 Planet Cloud에 그룹 통화의 미디어 데이터를 구독하도록 요청합니다.

이 메시지로 요청하기 전에 Planet Cloud 게이트웨이 서버에 인증을 요청하여 subsToken을 얻어야 합니다.

메시지 본문
필드데이터 유형설명비고
service_idString서비스 ID
room_idString방 ID
credentialStringBase64 인코딩된 문자열
media_typeArray (String 요소)미디어 유형 목록, A는 오디오를, V는 비디오를 나타냄지원 가능한 값은 다음과 같습니다.
- A
- A, V
비디오만 있는 모드는 지원하지 않습니다.
stream_typeString수신하려는 스트림의 유형
- MIX: 요청한 대상에 대한 혼합 스트림 제공
- MULTI: 요청한 대상에 대해 ID별로 별도의 스트림 제공
media_type에 따른 지원 여부는 다음과 같습니다.
- A: MIX, MULTI
- A, V: MIX
target_typeString구독 대상 유형
- MAIN_ROOM: 기본 방 구독
- SUBGROUP: 서브그룹 구독
- TRANSLATE: 번역 방 및 서브그룹 구독
이 필드는 stream_typeMIX일 때만 유효합니다.
subgroup_nameString구독하고자 하는 서브그룹의 이름이 필드는 target_typeSUBGROUP일 때만 유효합니다.
target_user_idsArray (String 요소)구독하고자 하는 사용자 ID 목록target_user_ids 필드가 없거나 해당 필드에 항목이 없는 경우, 모든 참가자가 구독 대상입니다.
target_typeMAIN_ROOM인 경우 기본 방의 참가자가 선택되고, SUBGROUP인 경우 서브그룹의 참가자가 선택됩니다.
target_typeTRANSLATE인 경우 target_user_ids는 허용되지 않습니다.
target_user_ids에 설정할 수 있는 최대 요소 수는 16입니다.
layout_typeString비디오 믹싱을 위한 레이아웃 유형. 자세한 정보는 레이아웃 유형을 참조하세요.이 필드는 media_typeV(비디오)가 포함될 때만 유효합니다.
max_display_numNumber- 그리드 뷰: 1~16
- 포커스 뷰: 1~8
- 프레젠테이션 뷰: 1~8
비디오에 표시할 수 있는 참가자의 최대 수는 레이아웃 유형에 따라 다르며, 그리드 뷰의 경우 최대 16입니다.
auto_screenshareBool화면 공유 시작 시 자동으로 프레젠테이션 뷰로 전환할지 여부
no_target_users_timeoutNumbertarget_user_ids 파라미터가 설정된 경우, 방에 대상 사용자가 없을 때 구독 세션을 유지하는 최대 시간(초 단위)구독 클라이언트가 이 값을 설정하지 않으면 구독 세션은 시스템 설정에 따라 종료됩니다.
target_typeSUBGROUP인 경우의 주의사항

하나의 구독 세션에서는 하나의 서브그룹만 구독할 수 있습니다.

기본 방에 생성된 다른 서브그룹을 구독하려면, 새로운 구독 세션을 설정하고 해당 서브그룹에 대한 구독을 요청해야 합니다.

레이아웃 유형

layout_type 필드에 사용 가능한 값은 다음과 같습니다.

layout_type의 값target_user_ids 값 존재 여부설명
TALKER_GRID_VIEWN새로운 발언자가 우선인 그리드 뷰입니다.
새로운 발언자가 레이아웃에 들어가야 할 필요가 있지만 공간이 없는 경우, 가장 오랫동안 발언하지 않은 참가자가 제외됩니다.
Ytarget_user_ids가 지정된 경우, 해당 사용자만 레이아웃에 포함됩니다.
ORDERED_GRID_VIEWN사용 불가
Ytarget_user_ids 요소의 순서에 따라 레이아웃 순서가 결정되는 그리드 뷰입니다.
TALKER_FOCUS_VIEWN새로운 발언자가 우선인 포커스 뷰입니다.
새로운 발언자는 전체화면 영역에 표시되고, 이전 발언자는 첫 번째 썸네일 영역으로 이동합니다.
썸네일 뷰가 꽉 찬 경우, 가장 오랫동안 발언하지 않은 참가자가 제외됩니다.
Ytarget_user_ids가 지정된 경우, 해당 사용자만 레이아웃에 포함됩니다.
새로운 발언자는 전체화면 영역에 표시되고, 이전 발언자는 첫 번째 썸네일 영역으로 이동합니다.
ORDERED_FOCUS_VIEWN사용 불가
Ytarget_user_ids 요소의 순서에 따라 레이아웃 순서가 결정되는 포커스 뷰입니다.
target_user_ids의 첫 번째 사용자가 전체화면 영역에 표시되고, 이전 발언자는 첫 번째 썸네일 영역으로 이동합니다.
예제
{
"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을 통해 전송될 때는 미디어 데이터 메시지 형식으로 전달됩니다.

메시지 본문
필드데이터 유형설명비고
resultStringAPI의 결과
- success
- fail
subs_idNumber구독 서버에 의해 생성된 구독 IDresultsuccess일 때 값이 존재합니다.
audio_payload_infoArray (Audio PayloadInfo Object 요소)오디오 패킷을 나타내는 pt(페이로드 타입) 값에 대한 세부 정보resultsuccess일 때 값이 존재합니다.
video_payload_infoArray (Video PayloadInfo Object 요소)비디오 패킷을 나타내는 pt 값에 대한 세부 정보resultsuccess일 때 값이 존재합니다.
error_codeNumber오류 코드. 자세한 정보는 오류 코드를 참고하세요.resultfail일 때 값이 존재합니다.
error_descString오류에 대한 세부 설명resultfail일 때 값이 존재합니다.
Audio PayloadInfo Object
이름유형설명예시
ptNumber페이로드 타입 ID120
codecString오디오 코덱 이름"opus"
clock_rateNumber클럭 레이트48000
channelsNumber오디오 채널 수1
ptimeNumber패킷화 간격 시간(밀리초)20
Video PayloadInfo Object
이름유형설명예시
ptNumber페이로드 타입 ID121
codecString비디오 코덱 이름"H264"
clock_rateNumber클럭 레이트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_idString서비스 ID
room_idString방 ID
subs_idNumber구독 서버에서 생성된 구독 ID
예제
{
"header": {
"msg_id": 3,
"sess_id": "sid343213"
},
"body": {
"service_id": "planet",
"room_id": "RID_xlkjds",
"subs_id": 2394872139847981
}
}

UnsubscribeGroupcallMediaRsp (msg_id: 4)

그룹 통화 미디어 구독 중단 요청에 대한 응답 메시지입니다.

메시지 본문
필드데이터 유형설명비고
resultStringAPI의 결과
- success
- fail
error_codeNumber오류 코드. 자세한 정보는 오류 코드를 참고하세요.resultfail일 때 값이 존재합니다.
error_descString오류에 대한 세부 설명resultfail일 때 값이 존재합니다.
예제
{
"header": {
"msg_id": 4,
"sess_id": "sid343213"
},
"body": {
"result": "success",
}
}

AbortGroupcallMediaSubscriptionRpt (msg_id: 5)

Planet Cloud GroupCall 서버에서 발생한 이벤트로 인해 구독이 중단된 경우 구독 클라이언트에게 이를 알리기 위한 메시지입니다.

메시지 본문
필드데이터 유형설명
error_codeNumber오류 코드. 자세한 정보는 오류 코드를 참고하세요.
error_descString오류에 대한 세부 설명
예제
{
"header": {
"msg_id": 5,
"sess_id": "sid343213"
},
"body": {
"error_code": 2,
"error_desc": "Group call has been ended"
}
}

ChangeGroupcallMediaSubscriptionReq (msg_id: 6)

이 메시지는 미디어 구독 정보를 변경하는 데 사용됩니다. 다음 항목을 업데이트할 수 있습니다.

  • 비디오 믹싱 레이아웃 유형
메시지 본문
필드데이터 유형설명비고
service_idString서비스 ID
room_idString방 ID
subs_idNumber구독 서버에서 생성된 구독 ID
layout_typeString비디오 믹싱을 위한 레이아웃 유형이 필드는 media_typeV(비디오)가 포함된 경우에만 유효합니다.
예제
{
"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)

구독 정보 변경 결과를 반환하는 메시지입니다.

메시지 본문
필드데이터 유형설명비고
resultStringAPI의 결과
- success
- fail
error_codeNumber오류 코드. 자세한 정보는 오류 코드를 참고하세요.resultfail일 때 값이 존재합니다.
error_descString오류에 대한 세부 설명resultfail일 때 값이 존재합니다.
예제
{
"header": {
"msg_id": 7,
"sess_id": "sid343213"
},
"body": {
"result": "success",
}
}

UpdateGroupcallMediaContributorsRpt (msg_id: 8)

stream_typeMIX이고 혼합 미디어에 포함된 user_id 목록에 변경이 있는 경우 업데이트된 user_id 목록이 이 메시지를 통해 구독 클라이언트에게 전달됩니다.

메시지 본문
필드데이터 유형설명예시
ptNumber페이로드 유형 ID120(오디오) 또는 121(비디오)
tsNumberRTP 타임스탬프
seqNumberRTP 시퀀스 번호
user_idsArray (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 파라미터가 설정된 경우, 이 파라미터에 포함된 사용자가 방에 들어오거나 나갈 때 사용자의 상태 정보가 이 메시지를 통해 구독 클라이언트에게 전달됩니다.

메시지 본문
필드데이터 유형설명
enterArray (String 요소)방에 들어온 사용자의 ID 목록
leaveArray (String 요소)방에서 나간 사용자의 ID 목록
예제
{
"header": {
"msg_id": 9,
"sess_id": "sid343213"
},
"body": {
"enter": ["user1", "user2", "user3"],
"leave": ["user4", "user5"]
}
}

오류 코드

오류 코드이유비고
0UNDEFINED
1NO_ERROR
2GROUPCALL_END
100AUTHENTICATION_FAIL
101ROOM_NOT_FOUND
102SUBSCRIPTION_NOT_SUPPORT
103INVALID_PARAMETER
104SUBSCRIPTION_NOT_FOUND
105INVALID_STATE
106INVALID_MSG_FORMAT
107SUBS_CAPA_FULL
200INTERNAL_SERVER_ERROR
201WS_DISCONNECTED_BY_PEER
202WS_PING_PONG_FAIL
203WS_INITIAL_REQUEST_TIMEOUT
1000UNKNOWN

미디어 데이터 메시지

미디어 데이터 메시지는 WebSocket의 바이너리 opcode를 사용하여 전달되며, 요청 받은 stream_type에 따라 아래와 같은 두 가지 유형으로 전달됩니다.

미디어 데이터 메시지 형식

미디어 데이터 메시지의 형식은 다음과 같습니다.

순서속성크기설명
1type1 바이트데이터 유형
1: RTP (혼합 오디오 또는 비디오)
2: user_id가 포함된 RTP
2data가변 길이

유형 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의 미디어 데이터 메시지의 형식은 다음과 같습니다.

순서속성크기
1user_id_length1 바이트
2user_id가변 길이
3오디오 RTP가변 길이
Warning

특정 사용자(그룹 통화 참가자)의 RTP 컨텍스트(타임스탬프, 시퀀스)는 다음 경우에 재시작될 수 있습니다.

  • 사용자가 일정 시간 동안 말을 멈춘 후 다시 말을 시작할 때
  • 사용자가 통화 방에 들어오거나 나갔다가 다시 들어와서 말을 시작할 때