Android
업무 프로세스
본 섹션에서 쇼 라이브 방송에서 자주 사용되는 업무 프로세스를 종합하여 전체 시나리오의 구현 프로세스를 더욱 쉽게 이해할 수 있도록 도와줍니다.
아래 그림은 스트리머(방주인)의 로컬 미리보기, 방 생성, 방 입장 및 방송 시작, 방 퇴장 및 방송 종료에 대한 프로세스를 보여줍니다.


아래 그림으로 스트리머 A가 스트리머 B를 초청하여 크로스 룸 PK 연결을 진행하는 프로세스를 보여줍니다. 크로스 룸 PK 과정에서 두 방의 시청자 모두 두 방주인의 PK 연결 라이브 방송 화면을 볼 수 있습니다.


아래 그림으로 RTC 실시간 인터랙션 라이브 방송실에서 시청자의 방 입장, 마이크 연결 신청, 연결 종료, 방 퇴장 프로세스를 보여줍니다.


접근 준비
단계1: 서비스 개통
쇼 라이브방송 시나리오는 일반적으로 RTC Engine과 뷰티 AR 두 가지 유료 PaaS 서비스를 활용하여 구축됩니다. 이 중에 RTC Engine 실시간 음성 및 비디오 상호 작용 기능을 제공하고, 뷰티 AR은 뷰티 효과 기능을 제공합니다. 타사 뷰티 제품을 사용하는 경우 뷰티 AR 통합 부분은 무시해도 됩니다.
1. 먼저 RTC Engine 콘솔에 로그인하여 애플리케이션을 생성해야 합니다. 필요에 따라 RTC Engine 애플리케이션 버전을 업그레이드할 수 있으며, 예를 들어 프로페셔널 버전은 더 많은 부가 기능 서비스를 이용할 수 있습니다.


설명:
두 개의 애플리케이션을 생성하고 각각 테스트 환경과 프로덕션 환경에 적용하는 것을 권장하며, 1년 동안 각 텐센트 클라우드 계정(UIN)에 매월 10,000분의 무료 사용 시간이 제공됩니다.
RTC Engine 월정액 요금제는 체험판(기본), 라이트, 스탠다드, 프로페셔널로 구분되며, 각각 다른 부가 기능 서비스를 이용할 수 있습니다. 자세한 내용은 버전 기능 및 월정액 요금제 설명을 참조하세요.
2. 애플리케이션 생성이 완료되면, 앱 관리 - 앱 개요 섹션에서 해당 애플리케이션의 기본 정보를 확인할 수 있습니다. 향후 사용을 위해 SDKAppID와 SDKSecretKey를 안전하게 보관해야 하며, 키 유출로 인한 트래픽 도용을 방지해야 합니다.


1. 뷰티 AR 콘솔 > 모바일 라이선스에 로그인한 후 을 클릭하여 테스트 라이선스 을 생성하세요(테스트비전 라이선스는 무료로 14일간 유효하며, 1회 연장 가능하여 총 28일 사용할 수 있습니다). 모바일을 선택하고 실제 필요에 따라 앱 이름, 패키지 이름, 번들 ID를 입력하세요. 사용해 보고 싶은 기능을 선택하세요: 모든 뷰티 기능, 가상 배경, 얼굴 인식, 제스처 인식, 선물 애니메이션 효과, 그런 다음에 확인을 클릭하세요.

2. 활성화 후 현재 페이지에서 본인의 정보를 확인하고 상단의 통합 가이드를 참조하여 통합시킬 수 있습니다. 통합 가이드에서 License Key와 License URL 사용 방법을 확인할 수 있습니다.

단계2: SDK 임포트하기
RTC Engine SDK와 뷰티 AR SDK가 mavenCentral 라이브러리에 송부되었으며, gradle을 구성하여 자동으로 다운로드 및 업데이트할 수 있습니다.
1. dependencies에 적합한 버전의 SDK 종속성을 추가합니다.
dependencies {// RTC Engine 경량판 SDK에 RTC 엔진과 라이브 방송 재생 두 가지 기능을 포함하며, 크기가 작습니다.implementation 'com.tencent.liteav:LiteAVSDK_TRTC:latest.release'// RTC Engine 전체 기능판 SDK에 라이브 방송, 숏 비디오, 주문형 비디오 등 다양한 기능을 추가로 포함하며, 크기가 약간 큽니다.// implementation 'com.tencent.liteav:LiteAVSDK_Professional:latest.release'// 뷰티 AR SDK, 예: S1-07 패키지는 다음과 같음implementation 'com.tencent.mediacloud:TencentEffect_S1-07:latest.release’}
설명:
추천하는 자동 로드 방식 외에도 SDK를 다운로드하여 수동으로 도입할 수도 있습니다. 자세한 내용은 RTC Engine SDK 수동 통합 및 뷰티 AR SDK 수동 통합을 참조하세요.
2. defaultConfig에서 앱이 사용하는 CPU 아키텍처를 지정합니다.
defaultConfig {ndk {abiFilters "armeabi-v7a", "arm64-v8a"}}
설명:
RTC Engine SDK는 armeabi-v7a/arm64-v8a 아키텍처를 지원하며, 시뮬레이터 전용 x86/x86_64 아키텍처도 추가로 지원합니다.
뷰티AR SDK는 현재 armeabi-v7a/arm64-v8a 아키텍처만 지원합니다.
3. Sync Now를 클릭하면 SDK가 자동으로 다운로드되어 프로젝트에 통합됩니다. 뷰티 AR 패키지에 동적 효과와 필터 기능이 포함된 경우 SDK 다운로드 페이지에서 해당 패키지를 다운로드하고 무료 필터 소재(./assets/lut)와 스티커 동적 효과(./MotionRes)를 압축 해제한 후 프로젝트의 다음 디렉터리에 배치해야 합니다
모션 효과:
../assets/MotionRes필터 효과:
../assets/lut단계 3: 엔지니어링 구성
1. 권한의 설정.
AndroidManifest.xml에서 앱 권한을 구성하고, 쇼 라이브방송 시나리오에서 RTC Engine SDK 및 뷰티 AR SDK에는 다음 권한이 필요합니다
<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.CAMERA" /><uses-feature android:name="android.hardware.camera.autofocus" />
주의:
android:hardwareAccelerated="false"를 설정하지 마십시오. 하드웨어 가속을 끄면 상대방의 비디오 스트림이 렌더링되지 않습니다.RTC Engine SDK에는 내장된 권한 요청 로직이 없으므로 해당 권한과 기능을 직접 선언해야 합니다. 일부 권한(예: 저장, 녹음, 카메라 등)은 런타임에 동적으로 요청해야 합니다.
Android 프로젝트의
targetSdkVersion이 31이거나 대상 기기가 Android 12및 그 이상 시스템 버전과 관련된 경우, 블루투스 기능을 정상적으로 사용하기 위해 코드에서 android.permission.BLUETOOTH_CONNECT 권한을 동적으로 신청해야 합니다. 자세한 내용은 블루투스 권한를 참조하십시오.2. 혼동 구성.
SDK 내부에서 Java의 리플렉션 기능을 사용하기 때문에 proguard-rules.pro 파일에서 SDK 관련 클래스를 혼동 제외 목록에 추가해야 합니다.
-keep class com.tencent.** { *; }-keep class org.light.** { *;}-keep class org.libpag.** { *;}-keep class org.extra.** { *;}-keep class com.gyailib.**{ *;}-keep class androidx.exifinterface.** { *;}
단계4: 인증 및 허가
UserSig는 텐센트 클라우드에서 설계한 보안 서명으로, 악의적인 공격자가 클라우드 서비스 사용 권한을 도용하는 것을 방지하기 위한 것입니다. RTC Engine은 방 입장 시 인증에 사용됩니다.
디버깅 및 테스트 단계: 클라이언트 예시 코드와 콘솔에서 가져오기 두 가지 방법으로 UserSig를 계산 및 생성할 수 있으며, 디버깅 및 테스트 용도로만 사용됩니다.
정식 운영 단계: 클라이언트가 역공학으로 키가 유출되는 것을 방지하기 위해 보안 등급이 더 높은 서버 UserSig 계산 방식의 사용을 권장합니다.
구체적인 구현 프로세스는 다음과 같습니다.
1. 손님의 App은 SDK 초기화 함수를 호출하기 전에 먼저 서버에 UserSig를 요청해야 합니다.
2. 손님의 서버는 SDKAppID와 UserID에 따라 UserSig를 계산합니다.
3. 서버는 계산된 UserSig를 손님의 App에 반환합니다.
4. 손님의 App은 획득한 UserSig를 특정 API를 통해 SDK에 전달합니다.
5. SDK는 SDKAppID + UserID + UserSig를 텐센트 클라우드 서버에 제출하여 검증합니다.
6. 텐센트 클라우드는 UserSig를 검증하여 합법성을 확인합니다.
7. 검증이 통과되면 RTC Engine SDK에 실시간 음성 및 영상 서비스를 제공합니다.


주의:
디버깅 단계의 로컬 UserSig 계산 방식은 온라인 환경에 적용하는 것을 권장하지 않으며, 역공학으로 인해 키가 유출될 수 있기 때문입니다.
여러 언어 버전(Java/GO/PHP/Node.js/Python/C#/C++)의 UserSig 서버 계산원 코드를 제공하며, 자세한 내용은 서버 계산 UserSig 을 참조하세요.
뷰티 AR 효과를 사용하기 전에 텐센트 클라우드에서 허가 증명에 대한 검증 받아야 합니다. License 에 사용되는 License Key와 License URL를 설정하며, 예시 코드는 다음과 같습니다.
import com.tencent.xmagic.telicense.TELicenseCheck;// 라이선스dml 다운로드 또는 업데이트만을 목적으로 하고 인증 결과에 관심이 없는 경우, 네 번째 매개변수에 null을 전달합니다.TELicenseCheck.getInstance().setTELicense(context, URL, KEY, new TELicenseCheck.TELicenseCheckListener() {@Overridepublic void onLicenseCheckFinish(int errorCode, String msg) {// 주의: 이 콜백은 호출 스레드에서 실행되지 않을 수 있습니다if (errorCode == TELicenseCheck.ERROR_OK) {// 인증 성공} else {// 인증 실패}}});
주의:
관련 업무 모듈의 초기화 코드에서 인증 허가를 트리거하고 사용하기 전에 임시로 라이선스를 다운로드하는 것을 피하며, 인증 시에는 네트워크 권한이 있어야 합니다.
실제 적용된 패키지 이름은 라이선스 생성 시 바인딩된 Package Name과 완전히 일치해야 하며, 그렇지 않으면 라이선스 검증이 실패할 수 있습니다. 자세한 내용은 인증 오류 코드을 참조하세요.
단계5: SDK 초기화
// RTC Engine SDK 인스턴스의 생성(싱글톤 모드)TRTCCloud mTRTCCloud = TRTCCloud.sharedInstance(context);// 이벤트 리스너의 설정mTRTCCloud.addListener(trtcSdkListener);// SDK의 다양한 이벤트 알림(예: 오류 코드, 경고 코드, 오디오/비디오 상태 매개변수 등)private TRTCCloudListener trtcSdkListener = new TRTCCloudListener() {@Overridepublic void onError(int errCode, String errMsg, Bundle extraInfo) {Log.d(TAG, errCode + errMsg);}@Overridepublic void onWarning(int warningCode, String warningMsg, Bundle extraInfo) {Log.d(TAG, warningCode + warningMsg);}};// 이벤트 리스너의 제거mTRTCCloud.removeListener(trtcSdkListener);// RTC Engine SDK 인스턴스(싱글톤 모드)를 파기합니다.TRTCCloud.destroySharedInstance();
설명:
import com.tencent.xmagic.XmagicApi;// 뷰티 SDK 초기화XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());// 개발 및 디버깅 시 로그 등급을 DEBUG로 설정하며 릴리스 패키지는 WARN으로 설정하세요. 그렇지 않으면 성능에 영향을 미칠 수 있습니다.mXmagicApi.setXmagicLogLevel(Log.WARN);// 뷰티 SDK를 릴리스하는 것은 GL 스레드에서 호출해야 합니다mXmagicApi.onDestroy();
설명:
접속 과정
API 시퀀스 다이어그램

단계1: 스트리머가 방에 입장하여 스트리밍을 시작합니다
RTC Engine SDK는 비디오 화면을 표시하는 컨트롤이고
TXCloudVideoView 유형만 전달할 수 있으므로, 먼저 레이아웃 파일에 뷰 렌더링 컨트롤을 정의해야 합니다.<com.tencent.rtmp.ui.TXCloudVideoViewandroid:id="@+id/live_cloud_view_main"android:layout_width="match_parent"android:layout_height="match_parent" />
주의:
1. 스트리머가 방에 들어가기 전에 로컬 비디오 미리보기 및 오디오 수집을 시작합니다.
// 스트리머의 로컬 화면 미리보기를 표시하는 데 사용되는 비디오 렌더링 컨트롤 가져옵니다TXCloudVideoView mTxcvvAnchorPreviewView = findViewById(R.id.live_cloud_view_main);// 비디오 인코딩 매개변수 설정은 원격 사용자가 보는 화면의 화질을 결정합니다TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_960_540;encParam.videoFps = 15;encParam.videoBitrate = 1300;encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;mTRTCCloud.setVideoEncoderParam(encParam);// boolean mIsFrontCamera는 전면/후면 카메라의 사용을 지정하여 비디오를 수집합니다.mTRTCCloud.startLocalPreview(mIsFrontCamera, mTxcvvAnchorPreviewView);// 여기서는 음질을 지정할 수 있으며, 낮음에서 높음 순으로 SPEECH/DEFAULT/MUSIC입니다.mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
주의:
업무 요구에 따라 비디오 인코딩 매개변수 TRTCVideoEncParam를 직접 설정할 수 있으며, 각 등급별 최적 해상도 및 비트레이트 조합은 해상도 비트레이트 참조표에서 확인할 수 있습니다.
enterRoom 전에 위 인터페이스를 호출하면 SDK는 카메라 미리보기와 오디오 수집만 시작하며, enterRoom을 호출한 후에야 스트리밍을 시작합니다.enterRoom 후에 위 인터페이스를 호출하면 SDK는 카메라 미리보기와 오디오 수집을 시작하고 자동으로 스트리밍을 시작합니다.2. 스트리머가 로컬 화면의 렌더링 매개변수 및 인코더 출력 화면 모드(선택 사항)를 설정합니다.
TRTCCloudDef.TRTCRenderParams params = new TRTCCloudDef.TRTCRenderParams();params.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_AUTO; // 화면 미러 모드params.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL; // 화면 채우기 모드params.rotation = TRTCCloudDef.TRTC_VIDEO_ROTATION_0; // 화면 회전 각도// 로컬 화면의 렌더링 매개변수를 설정합니다mTRTCCloud.setLocalRenderParams(params);// 인코더 출력 화면 미러 모드를 설정합니다mTRTCCloud.setVideoEncoderMirror(boolean mirror);// 비디오 인코더 출력 화면의 방향을 설정합니다mTRTCCloud.setVideoEncoderRotation(int rotation);
주의:
로컬 화면 렌더링 파라미터의 설정은 로컬 화면의 렌더링 효과에만 영향을 줍니다.
인코더 출력 모드의 설정은 방의 다른 사용자들이 보는 (및 클라우드 레코딩 파일) 화면 효과에 영향을 줍니다.
3. 스트리머가 정식으로 라이브 방송을 시작하고 방에 입장하여 스트리밍 시작합니다.
public void enterRoomByAnchor(String roomId, String userId) {TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();// 문자열 방 번호를 예로 들면params.strRoomId = roomId;params.userId = userId;// 업무 백엔드에서 가져온 UserSigparams.userSig = getUserSig(userId);// 손님의 SDKAppID로 교체합니다params.sdkAppId = SDKAppID;// 스트리머 역할 지정params.role = TRTCCloudDef.TRTCRoleAnchor;// 인터랙티브 라이브 방송 시나리오로 방 입장하기mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_LIVE);}// 방 입장 결과 이벤트의 콜백@Overridepublic void onEnterRoom(long result) {if (result > 0) {// result는 방에 임장하는 데 소요된 시간(밀리초)을 나타냅니다.Log.d(TAG, "Enter room succeed");} else {// result는 방 입장 실패의 오류 코드를 나타냅니다.Log.d(TAG, "Enter room failed");}}
주의:
RTC Engine 방 번호는 정수형
roomId와 문자열 형식 strRoomId로 나뉘며, 두 유형의 방은 서로 통하지 않으므로 방 번호 유형을 통일하는 것이 좋습니다.RTC Engine 사용자 역할은 스트리머와 청취자로 구분되며, 스트리머만 스트리밍 권한을 가집니다. 방 입장 시 사용자 역할을 지정해야 하며, 지정하지 않으면 기본적으로 스트리머 역할로 설정됩니다.
쇼 라이브방송 시나리오에서는 방 입장 모드를
TRTC_APP_SCENE_LIVE로 선택하는 것이 좋습니다.단계2: 시청자가 방에 들어가서 스트리밍을 시작합니다
1. 시청자가 RTC Engine 방에 입장합니다.
public void enterRoomByAudience(String roomId, String userId) {TRTCCloudDef.TRTCParams params = new TRTCCloudDef.TRTCParams();// 문자열 방 번호를 예로 들면params.strRoomId = roomId;params.userId = userId;// 업무 백엔드에서 가져온 UserSigparams.userSig = getUserSig(userId);// 손님의 SDKAppID로 교체합니다params.sdkAppId = SDKAppID;// 시청자 역할의 지정params.role = TRTCCloudDef.TRTCRoleAudience;// 인터랙티브 라이브 방송 시나리오로 방 입장하기mTRTCCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_LIVE);}// 방 입장 결과 이벤트의 콜백@Overridepublic void onEnterRoom(long result) {if (result > 0) {// result는 방에 임장하는 데 소요된 시간(밀리초)을 나타냅니다.Log.d(TAG, "Enter room succeed");} else {// result는 방 입장 실패의 오류 코드를 나타냅니다.Log.d(TAG, "Enter room failed");}}
2. 시청자가 스트리머의 오디오 및 비디오 스트림을 구독합니다.
@Overridepublic void onUserAudioAvailable(String userId, boolean available) {// 원격 사용자가 자신의 오디오를 게시/취소합니다// 자동 구독 모드에서는 사용자가 아무런 작업을 하지 않아도 SDK가 원격 사용자의 오디오를 자동으로 재생합니다.}@Overridepublic void onUserVideoAvailable(String userId, boolean available) {// 원격 사용자가 메인 비디오 화면을 게시/취소합니다if (available) {// 원격 사용자의 비디오 스트림을 구독하고 비디오 렌더링 컨트롤을 바인딩합니다mTRTCCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, TXCloudVideoView view);} else {// 원격 사용자의 비디오 스트림 구독을 중지하고 렌더링 컨트롤을 릴리스합니다mTRTCCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);}}
3. 시청자가 원격 화면의 렌더링 모드를 설정합니다(선택 사항).
TRTCCloudDef.TRTCRenderParams params = new TRTCCloudDef.TRTCRenderParams();params.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_AUTO; // 화면 미러 모드params.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL; // 화면 채우기 모드params.rotation = TRTCCloudDef.TRTC_VIDEO_ROTATION_0; // 화면 회전 각도// 원격 화면의 렌더링 모드를 설정합니다mTRTCCloud.setRemoteRenderParams(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, params)
단계3: 시청자와의 실시간 인터랙션
1. 시청자가 스트리머 역할로 전환됩니다.
// 스트리머 역할로 전환됩니다.mTRTCCloud.switchRole(TRTCCloudDef.TRTCRoleAnchor);// 역할 전환 이벤트의 콜백@Overridepublic void onSwitchRole(int errCode, String errMsg) {if (errCode == TXLiteAVCode.ERR_NULL) {// 역할 전환 성공}}
2. 시청자가 로컬 오디오/비디오 수집 및 스트리밍을 시작합니다.
// 연결된 시청자의 로컬 화면 미리보기를 표시하기 위한 비디오 렌더링 컨트롤을 가져옵니다.TXCloudVideoView mTxcvvAudiencePreviewView = findViewById(R.id.live_cloud_view_sub);// 비디오 인코딩 매개변수 설정은 원격 사용자가 보는 화면의 화질을 결정합니다TRTCCloudDef.TRTCVideoEncParam encParam = new TRTCCloudDef.TRTCVideoEncParam();encParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_480_270;encParam.videoFps = 15;encParam.videoBitrate = 550;encParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;mTRTCCloud.setVideoEncoderParam(encParam);// boolean mIsFrontCamera는 전면/후면 카메라의 사용을 지정하여 비디오를 수집합니다.mTRTCCloud.startLocalPreview(mIsFrontCamera, mTxcvvAudiencePreviewView);// 여기서는 음질을 지정할 수 있으며, 낮음에서 높음 순으로 SPEECH/DEFAULT/MUSIC입니다.mTRTCCloud.startLocalAudio(TRTCCloudDef.TRTC_AUDIO_QUALITY_DEFAULT);
주의:
업무 요구에 따라 비디오 인코딩 매개변수 TRTCVideoEncParam을 직접 설정할 수 있으며, 각 등급별 최적 해상도 및 비트레이트 조합은 해상도 비트레이트 참조표에서 확인할 수 있습니다.
3. 시청자가 마이크를 끄고 스트리밍을 중지합니다.
// 시청자 역할로 전환됩니다mTRTCCloud.switchRole(TRTCCloudDef.TRTCRoleAudience);// 역할 전환 이벤트의 콜백@Overridepublic void onSwitchRole(int errCode, String errMsg) {if (errCode == TXLiteAVCode.ERR_NULL) {// 카메라 수집 및 스트리밍 중지합니다mTRTCCloud.stopLocalPreview();// 마이크 수집 및 스트리밍 중지합니다mTRTCCloud.stopLocalAudio();}}
단계4: 방 나가기 및 해산하기
1. 방에서 나가기.
public void exitRoom() {mTRTCCloud.stopLocalAudio();mTRTCCloud.stopLocalPreview();mTRTCCloud.exitRoom();}// 방 나가기 이벤트의 콜백@Overridepublic void onExitRoom(int reason) {if (reason == 0) {Log.d(TAG, "exitRoom을 호출하여 방에서 나가기");} else if (reason == 1) {Log.d(TAG, "서버에 의해 현재 방에서 나가게 됩니다");} else if (reason == 2) {Log.d(TAG, "현재 방 전체가 해체됩니다");}}
주의:
SDK가 점유한 모든 리소스가 릴리스된 후, SDK는
onExitRoom 콜백을 통해 알려줍니다.enterRoom을 다시 호출하거나 다른 음성/영상 SDK로 전환하려면 onExitRoom 콜백이 발생한 후 관련 작업을 수행하십시오. 그렇지 않으면 카메라, 마이크등 장치가 강제로 점유된 것과 같은 다양한 이상 현상이 발생할 수 있습니다.2. 방 해산
서버 측 해산: RTC Engine 서버 측 방 해산 API
DismissRoom(숫자 방 ID와 문자열 방 ID 구분)을 제공하며, 이 인터페이스를 호출하여 방의 모든 사용자를 방에서 내보내고 방을 해산할 수 있습니다.클라이언트 측 해산: 각 클라이언트의 방 나가기
exitRoom 인터페이스를 통해 방 내 모든 스트리머와 청취자를 방에서 내보낼 수 있습니다.퇴장 후 RTC Engine 방 생명주기 규칙에 따라 방이 자동으로 해산됩니다. 자세한 내용은 방 나가기를 참조하세요.주의:
라이브방송이 종료된 후 서버 측에서 방 해산 API를 호출하여 방이 해산되도록 하는 것이 좋습니다. 이는 시청자가 의도치 않게 방에 들어와 예상치 못한 비용이 발생하는 것을 방지하기 위함입니다.
고급 기능
스트리머 간 크로스 룸 PK 연결
1. 어느 한쪽이 크로스 룸 PK 연결을 시작합니다.
public void connectOtherRoom(String roomId, String userId) {try {JSONObject jsonObj = new JSONObject();// 숫자 방 번호는 roomId입니다jsonObj.put("strRoomId", roomId);jsonObj.put("userId", userId);mTRTCCloud.ConnectOtherRoom(jsonObj.toString());} catch (JSONException e) {e.printStackTrace();}}// 크로스 룸 연결 결과의 콜백@Overridepublic void onConnectOtherRoom(String userId, int errCode, String errMsg) {// 크로스 룸 연결하려는 다른 방의 스트리머의 사용자 ID// 에러 코드, ERR_NULL은 요청 성공을 나타냅니다// 에러 정보}
주의:
크로스 룸 PK 연결의 로컬 사용자와 상대 사용자는 모두 스트리머 역할이어야 하며, 오디오 또는 비디오 업스트림이 모두 있어야 합니다.
2. 두 방의 모든 사용자는 다른 방의 스크리머로부터 오디오/비디오 스트림 사용 가능 콜백을 받게 됩니다.
@Overridepublic void onUserAudioAvailable(String userId, boolean available) {// 원격 사용자가 자신의 오디오를 게시/취소합니다// 자동 구독 모드에서는 사용자가 아무런 작업을 하지 않아도 SDK가 원격 사용자의 오디오를 자동으로 재생합니다.}@Overridepublic void onUserVideoAvailable(String userId, boolean available) {// 원격 사용자가 메인 비디오 화면을 게시/취소합니다if (available) {// 원격 사용자의 비디오 스트림을 구독하고 비디오 렌더링 컨트롤을 바인딩합니다mTRTCCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, TXCloudVideoView view);} else {// 원격 사용자의 비디오 스트림 구독을 중지하고 렌더링 컨트롤을 릴리스합니다mTRTCCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);}}
3. 어느 한쪽이 크로스 룸 PK 연결을 종료합니다.
// 크로스 룸 채팅 연결 종료mTRTCCloud.DisconnectOtherRoom();// 크로스 룸 연결 종료 결과의 콜백@Overridepublic void onDisConnectOtherRoom(int errCode, String errMsg) {super.onDisConnectOtherRoom(errCode, errMsg);}
주의:
DisconnectOtherRoom()을 호출하면 모든 다른 방의 스트리머와의 크로스 룸 PK 연결이 종료됩니다.크로스 룸 PK 연결의 발신 측 또는 수신 측 중 어느 한쪽에서
DisconnectOtherRoom()을 호출하여 크로스 룸 PK 연결을 종료할 수 있습니다.제3자 뷰티 제품의 사용
RTC Engine은 서드파티 뷰티 효과 제품의 접근을 지원하며, 아래에서는 뷰티 AR을 예로 들어 서드파티 뷰티 접근 절차를 설명합니다.
1. 뷰티 AR SDK 통합 및 라이선스 권한의 신청에 대한 자세한 내용은 접속 준비 단계를 참조하세요.
2. 리소스 복사(있는 경우). 리소스 파일이 assets 디렉터리에 내장된 경우 사용 전에 App의 개인 디렉터리로 복사해야 합니다.
XmagicResParser.setResPath(new File(getFilesDir(), "xmagic").getAbsolutePath());//loading//개인 디렉터리로 리소스 파일을 복사하며, 한 번만 수행하면 됩니다.XmagicResParser.copyRes(getApplicationContext());
XmagicResParser.setResPath(다운로드한 리소스 파일의 로컬 경로);
3. 제3자 뷰티의 비디오 데이터 콜백을 설정하고, 뷰티 SDK가 처리한 프레임별 데이터 결과를 RTC Engine SDK 내부로 전달하여 렌더링 처리를 수행합니다.
mTRTCCloud.setLocalVideoProcessListener(TRTCCloudDef.TRTC_VIDEO_PIXEL_FORMAT_Texture_2D, TRTCCloudDef.TRTC_VIDEO_BUFFER_TYPE_TEXTURE, new TRTCCloudListener.TRTCVideoFrameListener() {@Overridepublic void onGLContextCreated() {// SDK 내부 OpenGL 환경이 생성되었으며, 이때 제3자 뷰티의 초기화 작업을 진행할 수 있습니다.if (mXmagicApi == null) {XmagicApi mXmagicApi = new XmagicApi(context, XmagicResParser.getResPath(), new XmagicApi.OnXmagicPropertyErrorListener());} else {mXmagicApi.onResume();}}@Overridepublic int onProcessVideoFrame(TRTCCloudDef.TRTCVideoFrame srcFrame, TRTCCloudDef.TRTCVideoFrame dstFrame) {// 제3자 뷰티 컴포넌트와 연동하기 위한 비디오 처리의 콜백if (mXmagicApi != null) {dstFrame.texture.textureId = mXmagicApi.process(srcFrame.texture.textureId, srcFrame.width, srcFrame.height);}return 0;}@Overridepublic void onGLContextDestory() {// SDK 내부 OpenGL 환경이 파기되었으며, 이때 제3자 뷰티 리소스 파기 작업을 진행할 수 있습니다.mXmagicApi.onDestroy();}});
주의:
단계1 및 단계2는 제3자 뷰티 제품의 구현 방식에 따라 다르며, 단계3은 RTC Engine이 제3자 뷰티를 통합하는 공통적이고 중요한 단계입니다.
듀얼 인코딩 모드
듀얼 인코딩 모드를 활성화하면 현재 사용자의 인코더가 [고화질 대형 화면]과 [저화질 소형 화면] 두 가지 비디오 스트림을 동시에 출력합니다(단, 오디오 스트림은 하나만 존재함). 이렇게 하면 방의 다른 사용자가 자신의 네트워크 상황이나 화면 크기에 따라 [고화질 대형 화면] 또는 [저화질 소형 화면]을 선택하여 구독할 수 있습니다.
1. 대형및 소형 화면 듀얼 인코딩 모드를 활성화합니다.
public void enableDualStreamMode(boolean enable) {// 소형 스트림의 비디오 인코딩 매개변수(자체 정의 가능)TRTCCloudDef.TRTCVideoEncParam smallVideoEncParam = new TRTCCloudDef.TRTCVideoEncParam();smallVideoEncParam.videoResolution = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_480_270;smallVideoEncParam.videoFps = 15;smallVideoEncParam.videoBitrate = 550;smallVideoEncParam.videoResolutionMode = TRTCCloudDef.TRTC_VIDEO_RESOLUTION_MODE_PORTRAIT;mTRTCCloud.enableEncSmallVideoStream(enable, smallVideoEncParam);}
주의:
듀얼 인코딩을 활성화하면 더 많은 CPU 및 네트워크 대역폭이 소모되므로 Mac, Windows 또는 고성능 Pad에서는 활성화를 고려할 수 있지만 모바일에서는 활성화하지 않는 것이 좋습니다.
2. 원격 사용자 비디오 스트림의 유형을 선택합니다.
// 원격 사용자 비디오 스트림을 구독할 때 선택 가능한 비디오 스트림의 유형mTRTCCloud.startRemoteView(userId, streamType, videoView);// 원격 사용자의 대/소 화면을 언제든지 전환할 수 있습니다mTRTCCloud.setRemoteVideoStreamType(userId, streamType);
주의:
듀얼 스트림 인코딩 활성화 후,
streamType 비디오 스트림 유형을 TRTC_VIDEO_STREAM_TYPE_SMALL으로 지정하여 저화질 소형 화면을 가져올 수 있습니다.뷰 렌더링 컨트롤
RTC Engine에는 비디오 화면을 관리하는 인터페이스가 많으며, 이러한 인터페이스는 모두 비디오 렌더링 컨트롤을 지정해야 합니다. Android 플랫폼에서는
TXCloudVideoView를 비디오 렌더링 컨트롤로 사용하며, SurfaceView와 TextureView 두 가지 렌더링 방식을 지원합니다. 아래에서는 렌더링 컨트롤 유형을 지정하는 방법과 비디오 렌더링 컨트롤을 업데이트하는 방법을 소개합니다.1. 특정 방식을 강제로 사용하거나 로컬 비디오 렌더링 컨트롤을
TXCloudVideoView으로 변환하려면 다음과 같이 코딩할 수 있습니다.//TextureView를 강제로 사용합니다TextureView textureView = findViewById(R.id.texture_view);TXCloudVideoView cloudVideoView = new TXCloudVideoView(context);cloudVideoView.addVideoView(textureView);//SurfaceView를 강제로 사용합니다SurfaceView surfaceView = findViewById(R.id.surface_view);TXCloudVideoView cloudVideoView = new TXCloudVideoView(surfaceView);
2. 업무에 표시 영역 전환과 관련된 인터랙티브 시나리오가 포함된 경우 RTC Engine SDK를 사용하여 로컬 미리보기 화면을 업데이트하고 원격 사용자 비디오 렌더링 컨트롤 기능을 구현할 수 있습니다.
// 로컬 미리보기 화면 렌더링 컨트롤의 업데이트mTRTCCloud.updateLocalView(videoView);// 원격 사용자 비디오 렌더링 컨트롤의 업데이트mTRTCCloud.updateRemoteView(userId, streamType, videoView);
주의:
매개변수
videoView를 대상 비디오 렌더링 컨트롤로 전달하고, streamType은 TRTC_VIDEO_STREAM_TYPE_BIG 및 TRTC_VIDEO_STREAM_TYPE_SUB만 지원됩니다.라이브 방송의 인터랙티브 메시지
라이브 방송의 인터랙티브는 라이브 방송 시나리오에서 특히 중요하며, 사용자는 좋아요 메시지, 선물 메시지, 탄막 메시지 등을 통해 스트리머와 인터랙티브 할 수 있습니다 . 라이브방송 인터랙티브 기능을 구현하기 위해서는 Chat 서비스를 활성화하고 Chat SDK를 임포트해야 합니다. 자세한 안내는 음성 채팅방 접속 가이드-접속 준비를 참조하십시오.
좋아요 메시지
1. 좋아요를 누른 사용자는 클라이언트에서 좋아요 관련 그룹 커스텀 메시지를 전송하며, 전송 성공 후 업무 측에서 로컬에 좋아요 효과를 렌더링합니다.
// 좋아요 메시지 본문 구성JSONObject jsonObject = new JSONObject();try {jsonObject.put("cmd", "like_msg");JSONObject msgJsonObject = new JSONObject();msgJsonObject.put("type", 1); // 좋아요 유형msgJsonObject.put("likeCount", 10); // 좋아요 수량jsonObject.put("msg", msgJsonObject);} catch (JSONException e) {e.printStackTrace();}String data = jsonObject.toString();// 그룹 커스텀 메시지 전송 (좋아요 메시지는 낮은 우선순위로 설정 권장드립니다)V2TIMManager.getInstance().sendGroupCustomMessage(data.getBytes(), mRoomId,V2TIMMessage.V2TIM_PRIORITY_LOW, new V2TIMValueCallback<V2TIMMessage>() {@Overridepublic void onError(int i, String s) {// 좋아요 메시지 전송 실패}@Overridepublic void onSuccess(V2TIMMessage v2TIMMessage) {// 좋아요 메시지 전송 성공// 로컬에서 좋아요 효과 렌더링합니다}});
2. 방 내의 다른 사용자의 클라이언트는 그룹 커스텀 메시지 콜백을 수신한 후 메시지 파싱 및 좋아요 효과 렌더링을 수행합니다.
// 그룹 커스텀 메시지의 수신V2TIMManager.getInstance().addSimpleMsgListener(new V2TIMSimpleMsgListener() {@Overridepublic void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {String customStr = new String(customData);if (!customStr.isEmpty()) {try {JSONObject jsonObject = new JSONObject(customStr);String command = jsonObject.getString("cmd");JSONObject messageJsonObject = jsonObject.getJSONObject("msg");if (command.equals("like_msg")) {int type = messageJsonObject.getInt("type"); // 좋아요 유형int likeCount = messageJsonObject.getInt("likeCount"); // 좋아요 수량// 좋아요 유형과 수량에 따라 좋아요 효과 렌더링합니다}} catch (JSONException e) {e.printStackTrace();}}}});
선물 메시지
1. 선물 보내는 사람이 업무 서버에 요청을 보내면 업무 서버가 결제 정산을 완료한 후 REST API를 호출하여 그룹에 커스텀 메시지를 전송합니다.
1.1 URL 요청의 예시.
https://xxxxxx/v4/group_open_http_svc/send_group_msg?sdkappid=88888888&identifier=admin&usersig=xxx&random=99999999&contenttype=json
1.2 패킷 요청의 예시.
{"GroupId": "@TGS#12DEVUDHQ","Random": 2784275388,"MsgPriority": "High", // 메시지의 우선순위이고 선물 메시지는 높은 우선순위로 설정해야 합니다"MsgBody": [{"MsgType": "TIMCustomElem","MsgContent": {// type: 선물 유형; giftUrl: 선물 리소스 주소; giftName: 선물 이름; giftCount: 선물 수량"Data": "{""cmd"": ""gift_msg", ""msg"": {""type"": 1, ""giftUrl"": ""xxx", ""giftName"": ""xxx", ""giftCount"": 1}}"}}]}
2. 방 내의 다른 사용자 클라이언트는 그룹 커스텀 메시지 콜백을 수신한 후 메시지 파싱 및 선물 효과 렌더링을 수행합니다.
// 그룹 커스텀 메시지의 수신V2TIMManager.getInstance().addSimpleMsgListener(new V2TIMSimpleMsgListener() {@Overridepublic void onRecvGroupCustomMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, byte[] customData) {String customStr = new String(customData);if (!customStr.isEmpty()) {try {JSONObject jsonObject = new JSONObject(customStr);String command = jsonObject.getString("cmd");JSONObject messageJsonObject = jsonObject.getJSONObject("msg");if (command.equals("gift_msg")) {int type = messageJsonObject.getInt("type"); // 선물 유형int giftCount = messageJsonObject.getInt("giftCount"); // 선물 수량String giftUrl = messageJsonObject.getString("giftUrl"); // 선물 리소스 주소String giftName = messageJsonObject.getString("giftName"); // 선물 이름// 선물 유형, 선물 수량, 선물 리소스 주소, 선물 이름에 따라 선물 효과를 렌더링합니다.}} catch (JSONException e) {e.printStackTrace();}}}});
탄막 메시지
쇼 라이브 방송에는 일반적으로 텍스트 형식의 탄막 메시지가 나오며, 여기서는 Chat의 전송 및 그룹 채팅 일반 텍스트 메시지 수신을 통해 구현할 수 있습니다.
// 공개 탄막 메시지의 전송V2TIMManager.getInstance().sendGroupTextMessage(text, groupID, V2TIMMessage.V2TIM_PRIORITY_NORMAL, new V2TIMValueCallback<V2TIMMessage>() {@Overridepublic void onError(int i, String s) {// 탄막 메시지의 전송이 실패됩니다}@Overridepublic void onSuccess(V2TIMMessage v2TIMMessage) {// 탄막 메시지의 전송이 성공됩니다// 로컬에서 메시지 텍스트가 표시됨}});// 공개 탄막 메시지의 수신V2TIMManager.getInstance().addSimpleMsgListener(new V2TIMSimpleMsgListener() {@Overridepublic void onRecvGroupTextMessage(String msgID, String groupID, V2TIMGroupMemberInfo sender, String text) {// 발신자 정보 sender와 메시지 텍스트 text에 따라 탄막 메시지 렌더링합니다}});
주의:
선물 메시지는 높은 우선순위로 설정하는 것을 권장합니다. 탄막 메시지는 일반 우선순위로 설정하며, 좋아요 메시지는 낮은 우선순위로 설정하는 것을 권장합니다.
본인이 클라이언트에서 그룹 채팅 메시지를 보내면 메시지 수신 콜백이 트리거되지 않으며 그룹 내의 다른 사용자만 수신할 수 있습니다.
이상 처리
고장및 오류 처리
1. UserSig 관련. UserSig 검증 실패로 인해 방 입장에 실패할 수 있으며 UserSig 도구를 사용하여 검증할 수 있습니다.
열거형 | 값 | 설명 |
ERR_TRTC_INVALID_USER_SIG | -3320 | 입장 매개변수 UserSig가 올바르지 않습니다. TRTCParams.userSig이 비어 있는지 확인하세요. |
ERR_TRTC_USER_SIG_CHECK_FAILED | -100018 | UserSig 검증에 실패했습니다. 매개변수 TRTCParams.userSig이 올바르게 입력되었거나 만료되지 않았는지 확인하세요. |
2. 방 입장 실패 시 먼저 입장 매개변수가 올바른지 확인하고 입장 및 퇴장 인터페이스는 반드시 쌍으로 호출해야 합니다. 입장에 실패한 경우에도 퇴장 인터페이스를 호출해야 합니다.
열거형 | 값 | 설명 |
ERR_TRTC_CONNECT_SERVER_TIMEOUT | -3308 | 입장 요청이 시간 초과했습니다, 네트워크 연결이 끊겼는지 또는 VPN이 켜져 있는지 확인하세요. 4G로 전환하여 테스트할 수도 있습니다. |
ERR_TRTC_INVALID_SDK_APPID | -3317 | 입장 매개변수 sdkAppId가 잘못되었습니다. TRTCParams.sdkAppId이 비어 있는지 확인하세요. |
ERR_TRTC_INVALID_ROOM_ID | -3318 | 입장 매개변수 roomId가 올바르지 않습니다. TRTCParams.roomId 또는 TRTCParams.strRoomId이 비어 있는지 확인하세요. roomId와 strRoomId는 혼용할 수 없습니다. |
ERR_TRTC_INVALID_USER_ID | -3319 | 입장 매개변수 userId가 올바르지 않습니다. TRTCParams.userId이 비어 있는지 확인하세요. |
ERR_TRTC_ENTER_ROOM_REFUSED | -3340 | 입장 요청이 거부되었습니다. enterRoom을 연속적으로 호출하여 동일한 ID의 방에 입장했는지 확인하세요. |
3. 장치 관련. 장치 관련 오류를 감지할 수 있으며, 관련 오류 발생 시 사용자에게 UI로 알립니다.
열거형 | 값 | 설명 |
ERR_CAMERA_START_FAIL | -1301 | Windows 또는 Mac 장치에서 카메라 구성 프로그램(드라이버)이 비정상일 경우, 카메라 열 수가 없습니다. 장치를 비활성화한 후 다시 활성화하거나, 기기를 재시작하거나, 구성 프로그램을 업데이트하세요. |
ERR_MIC_START_FAIL | -1302 | Windows 또는 Mac 장치에서 마이크 구성 프로그램(드라이버)에 오류가 발생하여 마이크를 열지 못한 경우, 장치를 비활성화한 후 다시 활성화하거나 기기를 재시작하거나 구성 프로그램을 업데이트하세요. |
ERR_CAMERA_NOT_AUTHORIZED | -1314 | 카메라 장치에 권한이 없습니다. 일반적으로 모바일 장치에서 발생하며, 사용자가 권한을 거부했을 수 있습니다. |
ERR_MIC_NOT_AUTHORIZED | -1317 | 마이크 장치에 권한이 없습니다. 일반적으로 모바일 장치에서 발생하며, 사용자가 권한을 거부했을 수 있습니다. |
ERR_CAMERA_OCCUPY | -1316 | 카메라가 사용 중입니다. 다른 카메라를 열어 볼 수 있습니다. |
ERR_MIC_OCCUPY | -1319 | 마이크가 사용 중입니다. 예를 들어 모바일 장치에서 통화 중일 때 마이크를 열 수가 없습니다. |
원격 미러 모드의 무효 문제
RTC Engine 설정 화면 미러는 로컬 미리보기 미러
setLocalRenderParams과 비디오 인코더 미러 setVideoEncoderMirror으로 나뉘며, 각각 로컬 미리보기 화면의 미러 효과와 비디오 인코딩 출력 화면의 미러 효과(원격 시청자 및 클라우드 레코딩의 미러링 모드)에 영향을 줍니다. 로컬 미리보기의 미러 효과가 원격 시청자 측에도 동시에 적용되도록 하려면 다음과 같이 코딩하십시오.// 로컬 화면의 렌더링 매개변수를 설정합니다TRTCCloudDef.TRTCRenderParams params = new TRTCCloudDef.TRTCRenderParams();params.mirrorType = TRTCCloudDef.TRTC_VIDEO_MIRROR_TYPE_ENABLE; // 화면 미러 모드params.fillMode = TRTCCloudDef.TRTC_VIDEO_RENDER_MODE_FILL; // 화면 채우기 모드params.rotation = TRTCCloudDef.TRTC_VIDEO_ROTATION_0; // 화면 회전 각도mTRTCCloud.setLocalRenderParams(params);// 인코더 출력 화면 미러 모드를 설정합니다mTRTCCloud.setVideoEncoderMirror(true);
카메라 줌/초점/전환 문제
쇼 라이브 방송 시나리오에서 스트리머는 카메라에 대한 사용자 커스텀 필요할 수 있으며, RTC Engine SDK 장치 관리 클래스에는 이러한 요구 사항을 해결하기 위한 관련 인터페이스가 있습니다.
1. 카메라 줌 배율의 조회 및 설정.
// 카메라 최대 줌 배율 가져오기(모바일 전용)float zoomRatio = mTRTCCloud.getDeviceManager().getCameraZoomMaxRatio();// 카메라 줌 배율의 설정(모바일 전용)// 범위는 1-5이며, 1은 가장 먼 시야(일반 렌즈)이고 5는 가장 가까운 시야(확대 렌즈)를 나타냅니다. 최대값은 5를 권장하며 5를 초과하면 비디오 데이터가 흐릿해질 수 있습니다mTRTCCloud.getDeviceManager().setCameraZoomRatio(zoomRatio);
2. 카메라 초점 기능 및 위치의 설정.
// 카메라 자동 초점 기능 켜기 또는 끄기(모바일 전용)mTRTCCloud.getDeviceManager().enableCameraAutoFocus(false);// 카메라 초점 위치의 설정(모바일 전용)// 해당 인터페이스를 사용하려면 먼저 enableCameraAutoFocus를 통해 자동 초점 기능을 꺼야 합니다mTRTCCloud.getDeviceManager().setCameraFocusPosition(int x, int y);
3. 전면 또는 후면 카메라의 판단 및 전환.
// 현재 전면 카메라인지 판단하세요(모바일만 적용)boolean isFrontCamera = mTRTCCloud.getDeviceManager().isFrontCamera();// 전면 또는 후면 카메라의 전환(모바일 전용)// true 전달: 전면으로 전환; false 전달: 후면으로 전환mTRTCCloud.getDeviceManager().switchCamera(!isFrontCamera);