tencent cloud

iOS

PDF
フォーカスモード
フォントサイズ
最終更新日: 2025-11-27 20:42:39

業務フロー

このセクションでは、1V1オーディオ・ビデオ通話におけるいくつかの一般的な業務フローをまとめて、全体のシナリオの実装をよりよく理解するのに役立ちます。
ボイス通話の流れ
ビデオ通話の流れ
下の図は1V1ボイス通話のシーケンス図を示しており、発信、応答、通話、切断などの流れが含まれています。



下図は、1V1ビデオ通話のシーケンス図を示しており、発信、応答、通話、切断などの流れが含まれています。




アクセスの準備

ステップ1:サービスを利用する

1V1オーディオ・ビデオ通話シナリオは通常、Tencent CloudのChatReal-Time Communicationの2つの有料PaaSサービスに依存して構築する必要があります。
1. まず、TRTCコントロールパネルにログインしてアプリケーションを作成する必要があります。この時、IMコントロールパネルでは、現在のTRTCアプリケーションと同じSDKAppIDのIM体験版アプリケーションが自動的に同期して作成され、両方のアカウントと認証システムを共通して利用できます。その後、必要に応じてTRTCまたはIMアプリケーションのバージョンをアップグレードすることができます。たとえば、プレミアム版では、より多くの付加価値機能サービスが使えます。



説明:
テスト環境と本番環境に使用するアプリケーションをそれぞれ作成することをお勧めします。1年間に各Tencent Cloudアカウント(UIN)に毎月10,000分間の無料時間が提供されます。
TRTC月額プランは体験版(デフォルト)、ベーシック版、プロフェッショナル版に分かれており、異なる付加価値機能サービスが使えます。詳細はバージョン機能と月額プランの説明を参照してください。
2. アプリケーションが作成された後、「アプリケーション管理アプリケーション概要セクション」を選択してそのアプリケーションの基本情報を確認できます。この一連の操作において、これからの便宜上、SDKAppIDSDKSecretKeyを大切に保管してください。また、キーの漏洩によるトラフィックの不正利用にご注意ください。




ステップ2:SDKをインポートする

TRTC SDKとIM SDKは既にCocoaPodsレポジトリーにパブリッシュされており、CocoaPodsを通じてSDKを統合することをお勧めします。
1. CocoaPodsのインストール
ターミナルウィンドウで以下のコマンドを入力してください(Macで事前にRuby環境をインストールする必要があります)。
sudo gem install cocoapods
2. Podfileを作成
プロジェクトのパスに移動し、以下のコマンドラインを入力すると、プロジェクトのパスにPodfileが表示されます。
pod init
3. Podfileを編集
プロジェクトのニーズに応じて適切なバージョンを選択し、Podfileファイルを編集してください。
platform :ios, '8.0'
target 'App' do
# TRTC Lite版
# インストールパッケージのサイズ増加は最小限だが、Real-Time Communication(TRTC)とライブプレーヤー(TXLivePlayer)の2つの機能のみをサポートします。
pod 'TXLiteAVSDK_TRTC', :podspec => 'https://liteav.sdk.qcloud.com/pod/liteavsdkspec/TXLiteAVSDK_TRTC.podspec'
# Add the IM SDK
pod 'TXIMSDK_Plus_iOS'
# pod 'TXIMSDK_Plus_iOS_XCFramework'
# pod 'TXIMSDK_Plus_Swift_iOS_XCFramework'
# If you need to add the Quic plugin, please uncomment the next line.
# Note: This plugin must be used with the Objective-C edition or XCFramework edition of the IM SDK, and the plugin version number must match the IM SDK version number.
# pod 'TXIMSDK_Plus_QuicPlugin'
end
4. SDKを更新してインストール
ターミナルウィンドウで以下のコマンドを入力して、ローカルライブラリファイルを更新し、SDKをインストールします。
pod install
あるいは以下のコマンドを使用して、ローカルライブラリのバージョンを更新してください。
pod update
pod命令を実行した後、SDKが統合された.xcworkspaceの拡張子を持つプロジェクトファイルが生成され、ダブルクリックで開けます。
説明:
podの検索に失敗した場合、podのローカルrepoキャッシュを更新することをお勧めします。更新コマンドは以下の通りです。
pod setup
pod repo update
rm ~/Library/Caches/CocoaPods/search_index.json
CocoaPodsの統合方法以外に、SDKをダウンロードして手動でインポートすることもできます。詳細はTRTC SDKの手動統合IM SDKの手動統合を参照してください。

ステップ3:プロジェクトの設定

1. 1V1オーディオ・ビデオ通話シナリオでAppはTRTC SDKおよびIM SDKにマイクとカメラへのアクセス権限を許可する必要があります。AppのInfo.plistに以下の内容を追加してください。マイクとカメラがシステムの承認ダイアログをポップアップする際のプロンプト情報に対応しています。
Privacy - Microphone Usage Description、そしてマイク使用目的も入力してください
Privacy - Camera Usage Description、そしてカメラ使用目的も入力してください。



2. バックグラウンドでApp関連機能を継続して実行する必要がある場合は、XCodeで現在のプロジェクトを選択し、Capabilitiesで設定項目Background ModesをONに設定し、AudioとAirPlay and Picture in Pictureにチェックを入れてください。以下の図に示されたように。




ステップ4:認証クレデンシャル

UserSigはTencent Cloudが設計したセキュリティ保護署名で、悪意のある攻撃者がクラウドサービスの使用権を盗用するのを防ぐためのものです。Tencent CloudのReal-Time Communication(TRTC)とChat(IM)サービスは、このセキュリティ保護メカニズムを採用しており、TRTCは入室時に認証を行い、IMはログイン時に認証を行います。
デバッグフェーズクライアントサンプルコードコントロールパネル取得の2つの方法でUserSigを計算生成でき、デバッグテストのみに使用します。
本番フェーズ:クライアントのリバースエンジニアリングによるキーの漏洩を防ぐため、より高いセキュリティレベルのサーバー側UserSig計算を推奨します。
具体的な実装の流れは以下の通りです。
1. AppがSDKの初期化関数を呼び出す前に、最初にサーバーにUserSigをリクエストします。
2. サーバーはSDKAppIDとUserIDに基づいてUserSigを計算します。
3. サーバーは計算されたUserSigをAppに返します。
4. Appは、特定のAPIを通じてSDKにUserSigを伝達します。
5. SDKがSDKAppID + UserID + UserSigをTencent Cloudのクラウドサーバーに提出して検証します。
6. Tencent CloudはUserSigを検証し、合法性を確認します。
7. 検証を通過した後、IM SDKにChatサービスを提供し、TRTC SDKにReal-Time Communicationサービスを提供します。



注意:
デバッグフェーズのローカルUserSig計算方式をオンライン環境に適用することは推奨しません。逆コンパイルによって容易に解読され、キーが漏洩する可能性があります。
複数の言語(Java/GO/PHP/Nodejs/Python/C#/C++)のUserSigサーバーサイド計算のソースコードを提供しています。詳細はサーバーサイドUserSig計算を参照してください。

ステップ5:SDKの初期化

1. IM SDK初期化とイベントモニターの追加
// ChatIMコントロールパネルからアプリケーションのSDKAppIDを取得します。
// V2TIMSDKListenerのイベントリスナーを追加、selfはid<V2TIMSDKListener>の実装クラス。IM SDKのイベントをリスニングする必要がない場合、このステップは無視できます。
[[V2TIMManager sharedInstance] addIMSDKListener:self];
// IM SDKを初期化、このインターフェースを呼び出した後、すぐにログインインターフェースを呼び出すことができます。
[[V2TIMManager sharedInstance] initSDK:sdkAppID config:config];
// SDK初期化後にはいくつかのイベントが発生します。例えば、接続状態、ログインチケットの有効期限切れなど。
- (void)onConnecting {
NSLog(@"IM SDKがTencent Cloudクラウドサーバーに接続中");
}
- (void)onConnectSuccess {
NSLog(@"IM SDKはすでにTencent Cloudクラウドサーバーに接続しました");
}
// イベントリスナーを削除
// selfはid<V2TIMSDKListener>の実装クラス
[[V2TIMManager sharedInstance] removeIMSDKListener:self];
// SDKの初期化解除
[[V2TIMManager sharedInstance] unInitSDK];
説明:
アプリケーションのライフサイクルがSDKのライフサイクルと一致している場合、アプリケーションを終了する前に初期化解除を行う必要はありません。特定の画面に入った後にのみSDKを初期化し、その画面を離れた後は使用しない場合は、SDKを初期化解除することができます。
2. TRTC SDKインスタンスの作成とイベントリスナーの設定
// TRTC SDKのインスタンスを作成する(シングルトンパターン)
self.trtcCloud = [TRTCCloud sharedInstance];
// イベントリスナーを設定する
self.trtcCloud.delegate = self;
// SDKからの各種イベント通知(例:エラーコード、警告コード、オーディオ・ビデオの状態パラメータなど)
- (void)onError:(TXLiteAVError)errCode errMsg:(nullable NSString *)errMsg extInfo:(nullable NSDictionary *)extInfo {
NSLog(@"%d: %@", errCode, errMsg);
}
- (void)onWarning:(TXLiteAVWarning)warningCode warningMsg:(nullable NSString *)warningMsg extInfo:(nullable NSDictionary *)extInfo {
NSLog(@"%d: %@", warningCode, warningMsg);
}
// イベントリスナーを削除
self.trtcCloud.delegate = nil;
// TRTC SDKインスタンスを破棄する(シングルトンパターン)
[TRTCCloud destroySharedIntance];
説明:
SDKイベント通知のモニタリングを推奨します。一般的なエラーに関するログ出力と処理についてはエラーコード表を参照してください。

アクセスの流れ

ステップ1:ログイン

IM SDK初期化後、SDKログインインターフェースを呼び出してアカウントの身元を検証し、アカウントの機能使用権限を取得する必要があります。そのため、他の機能を使用する前に、必ずログインしたことを確認してください。ログインされない場合、機能が異常になったり利用できなくなったりする可能性があります。TRTCのオーディオ・ビデオサービスのみをご利用の場合、このステップを無視しても構いません。

タイムライン図





ログイン操作

// ログイン:userIDはカスタマイズ可能、userSigはステップ1を参照して取得します。
[[V2TIMManager sharedInstance] login:userID userSig:userSig succ:^{
NSLog(@"success");
} fail:^(int code, NSString *desc) {
// 以下のエラーコードが返された場合、UserSigの使用期限が切れている。新しく発行されたUserSigを使用して再ログインします。
// 1. ERR_USER_SIG_EXPIRED(6206)
// 2. ERR_SVR_ACCOUNT_USERSIG_EXPIRED(70001)
// 注意:他のエラーコードの場合、IM SDKのログインが無限ループになる恐れがありますので、ログインインターフェースをここで呼び出さないでください。
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];

ログアウト操作

// ログアウト
[[V2TIMManager sharedInstance] logout:^{
NSLog(@"success");
} fail:^(int code, NSString *desc) {
NSLog(@"failure, code:%d, desc:%@", code, desc);
}];
説明:
アプリケーションのライフサイクルがIM SDKのライフサイクルと一致している場合、アプリケーションを終了する前にログアウトする必要はありません。特定の画面に入った後にのみIM SDKを使用し、その画面を離れた後は使用しない場合は、ログアウトおよびIM SDKをデイニシャライゼーションすることができます。

ステップ2:発信

タイムライン図





発信を開始する

1. 発信側ローカル画面プレビュー(ビデオ通話の場合のみが必要、ボイス通話の場合このステップをスキップ)
- (void)setupTRTC {
// ビデオエンコードのパラメータを設定し、リモートのユーザーが見る画面の品質を決定
TRTCVideoEncParam *encParam = [[TRTCVideoEncParam alloc] init];
encParam.videoResolution = TRTCVideoResolution_960_540;
encParam.videoFps = 15;
encParam.videoBitrate = 850;
encParam.resMode = TRTCVideoResolutionModePortrait;
[self.trtcCloud setVideoEncoderParam:encParam];
// ローカルのカメラプレビューを開始(イン/アウトカメラを指定してビデオキャプチャーが可能)
[self.trtcCloud startLocalPreview:self.isFrontCamera view:self.previewView];
}
注意:
業務のニーズに応じて、ビデオエンコーディングのパラメータTRTCVideoEncParamを自由に設定できます。各グレードの最適な解像度とビットレートの組み合わせの詳細は、解像度ビットレート参照表を参照してください。
enterRoomの前に、上記のインターフェースを呼び出すと、SDKはカメラのプレビューのみを開始し、enterRoomを呼び出すまでローカルビデオのプッシュストリームを開始しません。
2. 発信側が通話招待のシグナルを送信
// カスタムデータの構築
NSDictionary *dic = @{
@"cmd": @"av_call",
@"msg": @{
// 通話タイプ(ビデオ通話、ボイス通話)を指定
@"callType": @"videoCall",
// TRTCルーム番号を指定(発信側でランダム生成)
@"roomId": @"xxxRoomId",
},
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
options:NSJSONWritingPrettyPrinted
error:nil];
if (jsonData) {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// 通話招待シグナルを送信
[[V2TIMManager sharedInstance] invite:self.receiverId data:jsonString onlineUserOnly:false offlinePushInfo:self.offlinePushInfo timeout:self.timeout succ:^{
// 通話招待シグナルの送信に成功
// 発信ページをレンダリングし、呼出音を再生
} fail:^(int code, NSString *desc) {
// 通話招待シグナルの送信に失敗
// 発信失敗、再試行可能
}];
}
注意:
オーディオ・ビデオ通話シナリオでは、通常、招待シグナルにオフラインプッシュ情報offlinePushInfoを設定する必要があります。詳細はオフラインプッシュメッセージを参照してください。
招待シグナル内で合理的なタイムアウトパラメータtimeoutを設定することをお勧めします。単位は秒です。SDKはタイムアウトしたかを検知し、発信がタイムアウトした時の自動切断を実現します。
3. 着信側に通話招待通知が届く
[[V2TIMManager sharedInstance] addSignalingListener:self];
#pragma mark - V2TIMSignalingListener
// 着信ユーザーが発信リクエストを受信し、inviteIDはそのリクエストのためのID、inviterは発信ユーザーのIDです。
- (void)onReceiveNewInvitation:(NSString *)inviteID inviter:(NSString *)inviter groupID:(NSString *)groupID inviteeList:(NSArray<NSString *> *)inviteeList data:(NSString *)data {
if (data && ![data isEqualToString:@""]) {
NSData *jsonData = [data dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:nil];
if (dictionary) {
NSString *command = dictionary[@"cmd"];
NSDictionary *msg = dictionary[@"msg"];
if ([command isEqualToString:@"av_call"]) {
NSString *callType = msg[@"callType"];
NSString *roomId = msg[@"roomId"];
// 発信ページをレンダリングし、呼出音を再生
}
}
}
}
注意:
発信側が発信リクエストを開始し、着信音が発信リクエストを受け取った時、開発者は発信/着信ページのレンダリングと呼出音の再生を自身で実装する必要があります。
4. 着信側ローカル画面プレビュー(ビデオ通話の場合のみが必要、ボイス通話の場合このステップをスキップ)
if ([callType isEqualToString:@"videoCall"]) {
// ビデオエンコードのパラメータを設定し、リモートのユーザーが見る画面の品質を決定
TRTCVideoEncParam *encParam = [[TRTCVideoEncParam alloc] init];
encParam.videoResolution = TRTCVideoResolution_960_540;
encParam.videoFps = 15;
encParam.videoBitrate = 850;
encParam.resMode = TRTCVideoResolutionModePortrait;
[self.trtcCloud setVideoEncoderParam:encParam];
// ローカルのカメラプレビューを開始(イン/アウトカメラを指定してビデオキャプチャーが可能)
[self.trtcCloud startLocalPreview:self.isFrontCamera view:self.previewView];
}

発信取消

1. 発信側が呼び出しをキャンセル
[[V2TIMManager sharedInstance] cancel:inviteId data:data succ:^{
// 呼び出しをキャンセルしました
// 発信ページが破棄され、呼び出し音の再生が停止します
} fail:^(int code, NSString *desc) {
// 呼び出しのキャンセルに失敗しました
// 提示のキャンセルに失敗しました。再試行してみてください。
}];
2. 着信側にキャンセルの通知が届く
#pragma mark - V2TIMSignalingListener
- (void)onInvitationCancelled:(NSString *)inviteID inviter:(NSString *)inviter data:(NSString *)data {
// 発信ページが破棄され、呼び出し音の再生が停止します
}

発信タイムアウト

発信側と着信側の両方にタイムアウトの通知が届き、同時に発信/着信ページが破棄され、呼出音/着信音の再生が停止します。
#pragma mark - V2TIMSignalingListener
- (void)onInvitationTimeout:(NSString *)inviteID inviteeList:(NSArray<NSString *> *)inviteeList {
// タイムアウトの通知、ページの破棄、呼出着信音の再生停止
}

ステップ3:応答

シグナルを受信

1. 着信側が受取のシグナルを送信
[[V2TIMManager sharedInstance] accept:inviteId data:data succ:^{
// 応答に成功、通話ページをレンダリング、呼出音の再生が停止します。
if ([callType isEqualToString:@"videoCall"]) {
// ビデオ通話を開始
[self startVideoCall];
} else {
// ボイス通話を開始
[self startAudioCall];
}
} fail:^(int code, NSString *desc) {
// 応答に失敗、「例外が発生しました」、「再試行してください」が表示されます。
}];
2. 発信側が応答通知を受信
#pragma mark - V2TIMSignalingListener
- (void)onInviteeAccepted:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString *)data {
if ([self.callType isEqualToString:@"videoCall"]) {
// ビデオ通話を開始
[self startVideoCall];
} else {
// ボイス通話を開始
[self startAudioCall];
}
}

ボイス通話

1. 発信側と着信側は共に同じTRTCルームに入り、ボイス通話を開始します。
- (void)startAudioCall {
TRTCParams *params = [[TRTCParams alloc] init];
// TRTC認証クレデンシャル、サーバー側で生成
params.sdkAppId = SDKAPPID;
// TRTCアプリケーションID、コントロールパネルで取得
params.userSig = USERSIG;
// 文字列のルーム番号を例に
params.strRoomId = self.roomId;
// ユーザー名はIMに同期することをお勧めします
params.userId = self.userId;
[self.trtcCloud startLocalAudio:TRTCAudioQualitySpeech];
[self.trtcCloud enterRoom:params appScene:TRTCAppSceneAudioCall];
}
注意:
オーディオ通話モードで、TRTC入室シナリオはTRTCAppSceneAudioCallを選択する必要があり、入室ロールTRTCRoleTypeを指定する必要がありません。
音声キャプチャーstartLocalAudioを開始する時、音質パラメータを設定できます。オーディオ通話モードではTRTCAudioQualitySpeechの使用をお勧めします。
SDKデフォルトの自動購読モードでは、ユーザーがルームに入ると、そのルームのオーディオストリームをすぐに受信し、オーディオは自動的にデコードされ再生されます。手動でプルストリームする必要はありません。
2. 入室結果で通話状態をラベリングします。
// 通話の状態をラベリングする
@property (nonatomic, assign) BOOL isOnCalling;
#pragma mark - TRTCCloudDelegate
// 入室結果イベントコールバック
- (void)onEnterRoom:(NSInteger)result {
if (result > 0) {
// 入室成功、通話中であることをラベリングする
self.isOnCalling = YES;
} else {
// 入室失敗、通話異常を表示
self.isOnCalling = NO;
}
}

ビデオ通話

1. 発信側と着信側が同じTRTCルームに入り、ビデオ通話を開始します。
- (void)startVideoCall {
TRTCParams *params = [[TRTCParams alloc] init];
// TRTC認証クレデンシャル、サーバー側で生成
params.sdkAppId = SDKAPPID;
// TRTCアプリケーションID、コントロールパネルで取得
params.userSig = USERSIG;
// 文字列のルーム番号を例に
params.strRoomId = self.roomId;
// ユーザー名はIMに同期することをお勧めします
params.userId = self.userId;
[self.trtcCloud startLocalAudio:TRTCAudioQualitySpeech];
[self.trtcCloud enterRoom:params appScene:TRTCAppSceneVideoCall];
}
注意:
ビデオ通話モードで、TRTC入室シナリオはTRTCAppSceneVideoCallを選択する必要があり、入室ロールTRTCRoleTypeを指定する必要がありません。
音声キャプチャーstartLocalAudioを開始する時、音質パラメータを設定できます。ビデオ通話モードではTRTCAudioQualitySpeechの使用をお勧めします。
SDKデフォルトの自動購読モードでは、音声は自動的にデコードされて再生されますが、ビデオは手動でstartRemoteViewを呼び出してリモートビデオストリームをプルしてレンダリングし再生する必要があります。
2. 入室結果で通話状態をラベリングし、リモートビデオストリームをプルします。
// 通話の状態をラベリングする
@property (nonatomic, assign) BOOL isOnCalling;
#pragma mark - TRTCCloudDelegate
// 入室結果イベントコールバック
- (void)onEnterRoom:(NSInteger)result {
if (result > 0) {
// 入室成功、通話中であることをラベリングする
self.isOnCalling = YES;
} else {
// 入室失敗、通話異常を表示
self.isOnCalling = NO;
}
}
// リモートビデオストリームをプル
- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available {
// リモートユーザーがメインビデオ画面をパブリッシュ/キャンセル
if (available) {
// リモートユーザーのビデオストリームを購読し、ビデオレンダリングコントロールにバインド
[self.trtcCloud startRemoteView:userId streamType:TRTCVideoStreamTypeBig view:self.previewView];
} else {
// リモートユーザーのビデオストリームの購読を停止し、レンダリングコントロールをリリース
[self.trtcCloud stopRemoteView:userId streamType:TRTCVideoStreamTypeBig];
}
}

ステップ4:拒否

タイムライン図





アクティブ拒否

1. 着信側が通話拒否シグナルを送信
NSDictionary *dic = @{
@"cmd": @"av_call",
@"msg": @{
// 通話タイプ(ビデオ通話、ボイス通話)を指定
@"callType": @"videoCall",
// 拒否タイプを指定(アクティブ拒否、ビジー拒否)
@"reason": @"active",
},
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
options:NSJSONWritingPrettyPrinted
error:nil];
if (jsonData) {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
[[V2TIMManager sharedInstance] reject:self.inviteId data:jsonString succ:^{
// 拒否に成功、発信ページが破棄され、着信音の再生をが停止します。
} fail:^(int code, NSString *desc) {
// 拒否に失敗、「例外が発生しました」、「再試行してください」が表示されます。
}];
}
2. 発信側が拒否通知を受け取る
#pragma mark - V2TIMSignalingListener
- (void)onInviteeRejected:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString *)data {
if (data && ![data isEqualToString:@""]) {
NSData *jsonData = [data dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:nil];
if (dictionary) {
NSString *command = dictionary[@"cmd"];
NSDictionary *msg = dictionary[@"msg"];
if ([command isEqualToString:@"av_call"]) {
NSString *reason = msg[@"reason"];
if ([reason isEqualToString:@"active"]) {
// 相手が拒否したと表示
} else if ([reason isEqualToString:@"busy"]) {
// 相手がビジー状態であると表示
}
// 発信ページが破棄され、呼び出し音の再生が停止します
}
}
}
}

ビジー拒否

着信側に新しい通話招待が届いた場合、ローカルの通話状態が通話中であると判断したら、自動的にビジー拒否が実行されます。
- (void)onReceiveNewInvitation:(NSString *)inviteID inviter:(NSString *)inviter groupID:(NSString *)groupID inviteeList:(NSArray<NSString *> *)inviteeList data:(NSString *)data {
if (data && ![data isEqualToString:@""]) {
NSData *jsonData = [data dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:nil];
if (dictionary) {
NSString *command = dictionary[@"cmd"];
NSDictionary *msg = dictionary[@"msg"];
if ([command isEqualToString:@"av_call"] && self.isOnCalling) {
NSDictionary *dic = @{
@"cmd": @"av_call",
@"msg": @{
// 通話タイプ(ビデオ通話、ボイス通話)を指定
@"callType": @"videoCall",
// 拒否タイプを指定(アクティブ拒否、ビジー拒否)
@"reason": @"busy",
},
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
options:NSJSONWritingPrettyPrinted
error:nil];
if (jsonData) {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
// ローカル通話中、ビジー拒否シグナルを送信
[[V2TIMManager sharedInstance] reject:inviteID data:jsonString succ:^{
// ビジー拒否に成功
} fail:^(int code, NSString *desc) {
// ビジー拒否に失敗
}];
}
}
}
}
}
注意:
アクティブ拒否とビジー拒否は両方ともrejectシグナリングで実現されていますが、シグナリングのカスタムデータであるdatareasonフィールドを通じて区別する必要があります。

ステップ5:切断

タイムライン図





通話を切断

1. 任意側が部屋から退出すると、ローカル通話状態がリセットされます。
- (void)hangup {
[self.trtcCloud stopLocalAudio];
[self.trtcCloud stopLocalPreview];
[self.trtcCloud exitRoom];
}
#pragma mark - TRTCCloudDelegate
- (void)onExitRoom:(NSInteger)reason {
// 部屋から正常に退出し、通話を切断しました
self.isOnCalling = NO;
}
2. もう一方にリモート退室の通知が届いた場合、ローカルで退室を実行し、通話状態がリセットされます。
#pragma mark - TRTCCloudDelegate
- (void)onRemoteUserLeaveRoom:(NSString *)userId reason:(NSInteger)reason {
[self hangup];
}
- (void)onExitRoom:(NSInteger)reason {
// 部屋から正常に退出し、通話を切断しました
self.isOnCalling = NO;
}

ステップ6:機能制御

マイクのオン・オフ

// マイクをオンにする
[self.trtcCloud muteLocalAudio:NO];
// マイクをオフにする
[self.trtcCloud muteLocalAudio:YES];

スピーカーのオン・オフ

// スピーカーをオンにする
[self.trtcCloud muteAllRemoteAudio:NO];
// スピーカーをオフにする
[self.trtcCloud muteAllRemoteAudio:YES];

カメラのオン・オフ

// カメラを開き、イン・アウトカメラとレンダリングコントロールを指定
[self.trtcCloud startLocalPreview:self.isFrontCamera view:self.previewView];
// カメラをオフにする
[self.trtcCloud stopLocalPreview];

スピーカーとハンズフリーの切り替え

// スピーカーに切り替える
[[self.trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece];
// ハンズフリーに切り替える
[[self.trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone];

カメラの切り替え

// 現在がインカメラかどうかを判断
BOOL isFrontCamera = [[self.trtcCloud getDeviceManager] isFrontCamera];
// 前後カメラの切り替え、true: :インカメラに切り替える、; false: :アウトカメラに切り替える
[[self.trtcCloud getDeviceManager] switchCamera:!isFrontCamera];

詳細設定

ネットワーク状態の提示

オーディオ・ビデオ通話において、通話がカクカクする心の準備をするために、相手の通信状況に関する通知を送る必要があります。
#pragma mark - TRTCCloudDelegate
- (void)onNetworkQuality:(TRTCQualityInfo *)localQuality remoteQuality:(NSArray<TRTCQualityInfo *> *)remoteQuality {
if (remoteQuality.count > 0) {
switch(remoteQuality[0].quality) {
case TRTCQuality_Excellent:
NSLog(@"相手のネットワーク状態がとてもいい");
break;
case TRTCQuality_Good:
NSLog(@"相手のネットワーク状態が比較的良い");
break;
case TRTCQuality_Poor:
NSLog(@"相手のネットワーク状態が普通");
break;
case TRTCQuality_Bad:
NSLog(@"相手のネットワーク状態が不安定");
break;
case TRTCQuality_Vbad:
NSLog(@"相手のネットワーク状態がかなり悪い");
break;
case TRTCQuality_Down:
NSLog(@"相手のネットワーク状態が極めて悪い");
break;
default:
NSLog(@"未定義");
break;
}
}
}
注意:
localQualityはローカルユーザーのネットワーク品質評価結果で、そのuserIdフィールドは空です。
remoteQualityはリモートユーザーのネットワーク品質評価結果を表し、その結果はリモートとローカルの両方の影響を受けます。

通話時間の統計

TRTCリモートユーザーの入室時間を通話時間の統計の開始時間、ローカルユーザーの退室時間を通話時間の統計の終了時間にすることをお勧めします。
// 通話開始時間
@property (nonatomic, assign) NSTimeInterval callStartTime;
// 通話終了時間
@property (nonatomic, assign) NSTimeInterval callFinishTime;
// 通話の持続時間(秒)
@property (nonatomic, assign) NSInteger callDuration;
// リモートユーザー入室コールバック
- (void)onRemoteUserEnterRoom:(NSString *)userId {
self.callStartTime = [[NSDate date] timeIntervalSince1970];
}
// ローカルユーザー退室コールバック
- (void)onExitRoom:(NSInteger)reason {
self.callFinishTime = [[NSDate date] timeIntervalSince1970];
self.callDuration = (NSInteger)(self.callFinishTime - self.callStartTime);
}
注意:
強制終了やネットワークの切断などの異常終了が発生した場合、クライアントでは関連する時間を統計できない可能性があります。これにより、サーバー側イベントコールバックで入退室イベントを監視し、この通話の時間を統計することができます。

ビデオ顔加工エフェクト

TRTCはサードパーティーの顔加工エフェクト製品をサポートし、以下にTencent Effectを例にして、サードパーティー顔加工のアクセスプロセスを示します。
1. Tencent Effect SDKを統合し、License認可を申請します。詳細はライブショー→アクセスの準備の手順を参照してください。
2. SDK素材リソースパスを設定します(存在する場合)。
NSString *beautyConfigPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
beautyConfigPath = [beautyConfigPath stringByAppendingPathComponent:@"beauty_config.json"];
NSFileManager *localFileManager=[[NSFileManager alloc] init];
BOOL isDir = YES;
NSDictionary * beautyConfigJson = @{};
if ([localFileManager fileExistsAtPath:beautyConfigPath isDirectory:&isDir] && !isDir) {
NSString *beautyConfigJsonStr = [NSString stringWithContentsOfFile:beautyConfigPath encoding:NSUTF8StringEncoding error:nil];
NSError *jsonError;
NSData *objectData = [beautyConfigJsonStr dataUsingEncoding:NSUTF8StringEncoding];
beautyConfigJson = [NSJSONSerialization JSONObjectWithData:objectData
options:NSJSONReadingMutableContainers
error:&jsonError];
}
NSDictionary *assetsDict = @{@"core_name":@"LightCore.bundle",
@"root_path":[[NSBundle mainBundle] bundlePath],
@"tnn_"
@"beauty_config":beautyConfigJson
};
// SDKの初期化:widthとheightはそれぞれtextureの幅と高さ
self.xMagicKit = [[XMagic alloc] initWithRenderSize:CGSizeMake(width,height) assetsDict:assetsDict];
3. サードパーティー顔加工のビデオデータコールバックを設定し、顔加工SDKに処理された各フレームの結果データをTRTC SDK内部でレンダリング処理に渡します。
// TRTC SDKサードパーティー顔加工のビデオデータコールバックを設定
[self.trtcCloud setLocalVideoProcessDelegete:self pixelFormat:TRTCVideoPixelFormat_Texture_2D bufferType:TRTCVideoBufferType_Texture];
#pragma mark - TRTCVideoFrameDelegate
// YTProcessInputを作成しSDKに渡してレンダリング処理を実行
- (uint32_t)onProcessVideoFrame:(TRTCVideoFrame *_Nonnull)srcFrame dstFrame:(TRTCVideoFrame *_Nonnull)dstFrame {
if (!self.xMagicKit) {
[self buildBeautySDK:srcFrame.width and:srcFrame.height texture:srcFrame.textureId];// XMagic SDKを初期化
self.heightF = srcFrame.height;
self.widthF = srcFrame.width;
}
if(self.xMagicKit!=nil && (self.heightF!=srcFrame.height || self.widthF!=srcFrame.width)){
self.heightF = srcFrame.height;
self.widthF = srcFrame.width;
[self.xMagicKit setRenderSize:CGSizeMake(srcFrame.width, srcFrame.height)];
}
YTProcessInput *input = [[YTProcessInput alloc] init];
input.textureData = [[YTTextureData alloc] init];
input.textureData.texture = srcFrame.textureId;
input.textureData.textureWidth = srcFrame.width;
input.textureData.textureHeight = srcFrame.height;
input.dataType = kYTTextureData;
YTProcessOutput *output = [self.xMagicKit process:input withOrigin:YtLightImageOriginTopLeft withOrientation:YtLightCameraRotation0];
dstFrame.textureId = output.textureData.texture;
return 0;
}
注意:
ステップ1、ステップ2は、異なるサードパーティ顔加工製品の実装方法によって異なりますが、ステップ3はTRTCにおいて、サードパーティー顔加工製品を統合するための共通で重要なステップです。
シナリオプランTencent Effect統合ガイドはTRTC SDKへのTencent Effectの統合を参照してください。Tencent Effectを単独で統合するガイドはTencent Effectの単独統合を参照してください。

ウィンドウサイズの切り替え

TRTCには、ビデオ画面を操作するための多くのインターフェースがあり、これらのインターフェースにビデオレンダリングコントロールを指定する必要があります。
1. もし業務が表示エリアの切り替えるインタラクションがあるシナリオに関連している場合、TRTC SDKのローカルプレビュー画面更新、リモートユーザーのビデオレンダリングコントロール更新機能で実装できます。
// ローカルプレビュー画面のレンダリングコントロールを更新
[self.trtcCloud updateLocalView:self.previewView];
// リモートユーザーのビデオレンダリングコントロールを更新
[self.trtcCloud updateRemoteView:self.previewView streamType:TRTCVideoStreamTypeBig forUser:self.userId];
注意:
streamTypeTRTCVideoStreamTypeBigTRTCVideoStreamTypeSubのみをサポートしています。

オフラインプッシュメッセージ

オーディオ・ビデオ通話シナリオでは通常、着信ユーザーがオフラインの場合でも着信メッセージを受け取ることができるように、オフラインプッシュメッセージを使用する必要があります。オフラインプッシュの統合ガイドについては、オフラインメッセージプッシュを参照してください。以下では、特にステップ5:オフラインプッシュメッセージを送信、ステップ6:オフラインプッシュメッセージを解析の実装方法について詳しく説明します。

オフラインプッシュメッセージの送信

inviteで通話招待を送る際、V2TIMOfflinePushInfoを通じてオフラインプッシュのパラメータを設定できます。V2TIMOfflinePushInfoのextでカスタムextデータを設定し、ユーザーがオフラインプッシュを受け取ってアプリを起動した時、システムコールバックでextフィールドを取得できます。そして、extフィールドの内容に基づいて指定されたUIページにジャンプします。
NSDictionary *dic = @{
@"cmd": @"av_call",
@"msg": @{
// 通話タイプ(ビデオ通話、ボイス通話)を指定
@"callType": @"videoCall",
// TRTCルーム番号を指定(発信側でランダム生成)
@"roomId": @"xxxRoomId",
},
};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
V2TIMOfflinePushInfo *pushInfo = [[V2TIMOfflinePushInfo alloc] init];
pushInfo.title = self.nickName;
pushInfo.desc = @"You have a new call invitation";
NSDictionary *ext = @{
@"entity" : @{
@"action" : @1,
@"content" : jsonString,
@"sender" : self.senderId,
@"nickname" : self.nickName,
@"faceUrl" : faceUrl,
}
};
NSData *data = [NSJSONSerialization dataWithJSONObject:ext options:NSJSONWritingPrettyPrinted error:nil];
pushInfo.ext = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
pushInfo.iOSSound = @"phone_ringing.mp3";
// 以下はAndroid互換のフィールド、記入が必要
pushInfo.AndroidOPPOChannelID = @"tuikit";
pushInfo.AndroidSound = @"phone_ringing";
pushInfo.AndroidHuaWeiCategory = @"IM";
pushInfo.AndroidVIVOCategory = @"IM";
[[V2TIMManager sharedInstance] invite:@"receiverId" data:jsonString onlineUserOnly:false offlinePushInfo:pushInfo timeout:self.timeout succ:^{
// 通話招待シグナルの送信に成功
} fail:^(int code, NSString *desc) {
// 通話招待シグナルの送信に失敗
}];

オフラインプッシュメッセージの解析

ユーザーがオフラインプッシュを受け取ってアプリを起動した時、AppDelegate -> didReceiveRemoteNotificationシステムコールバックでextフィールドを取得できます。そして、extフィールドの内容に基づいて指定されたUIページにジャンプします。
// アプリ起動後、以下のコールバックを受け取る
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
// プッシュ拡張フィールドを解析
if ([userInfo[@"ext"]) {
// 指定されたUIページにジャンプ
}
}

例外処理

TRTCエラー処理

TRTC SDKは回復不可能なエラーが発生した場合、onErrorコールバックでスローされます。詳細はエラーコード表を参照してください。

UserSig関係

UserSig検証に失敗すると入室に失敗します。UserSigツールを使用して検証できます。
列挙値
取得値
説明
ERR_TRTC_INVALID_USER_SIG
-3320
入室パラメータuserSigが正しくありません。TRTCParams.userSigが空であるかどうかを確認してください。
ERR_TRTC_USER_SIG_CHECK_FAILED
-100018
UserSig検証失敗、パラメータTRTCParams.userSigが正しく入力されているか、または期限切れでないかを確認してください。

入退室関係

入室に失敗した場合は、まず入室パラメータが正しいかどうかを確認してください。また、入退室インターフェースは必ずペアで呼び出す必要があります。入室に失敗した場合でも、退室インターフェースを呼び出す必要があります。
列挙値
取得値
説明
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のルームに連続して入室しようとしていないか確認してください。

デバイス関係

デバイス関連のエラーをリスニングし、関連するエラーが発生した場合に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
マイクが使用中です。たとえば、モバイルデバイスが通話中の場合、マイクを開くと失敗します。

通常メッセージのオフラインプッシュを受信できない

まず、アプリの実行環境と証明書の環境が一致しているかどうかを確認してください。一致していない場合、オフラインプッシュは受信できません。
次に、アプリと証明書の環境が本番環境であるかどうかを確認してください。開発環境であれば、AppleにdeviceTokenの申請を行うと失敗する可能性がありますが、本番環境ではこの問題は発生していません。本番環境に切り替えてテストしてください。

カスタムメッセージのオフラインプッシュを受信できない

カスタムメッセージのオフラインプッシュは通常のメッセージとは少し異なり、カスタムメッセージの内容は解析できず、プッシュする内容を確認できないため、デフォルトではプッシュしません。プッシュする必要がある場合、sendMessageの時にofflinePushInfoのdescフィールドを設定する必要があります。プッシュ時にはデフォルトでdesc情報が表示されます。

オフラインプッシュメッセージの受信を停止

オフラインプッシュメッセージの受信を停止したい場合は、setAPNSインターフェースのconfigパラメータをnilに設定すればOKです。この機能は5.6.1200バージョンから利用可能になります。

プッシュを受信できず、バックグラウンドでbad devicetokenエラーが発生

AppleのdeviceTokenは現在のコンパイル環境に関連しています。もしIMSDKにログインし、deviceTokenをTencent Cloudにアップロードする際に使用される証明書のIDとtokenが一致しない場合、エラーが発生します。
もしRelease環境でコンパイルしている場合、- application:didRegisterForRemoteNotificationsWithDeviceToken:コールバックが返すのは本番環境のtokenで、この時businessIDは本番環境の証明書IDを設定する必要があります。
もしDebug環境でコンパイルしている場合、- application:didRegisterForRemoteNotificationsWithDeviceToken:コールバックが返すのは開発環境のtokenで、この時businessIDは開発環境の証明書IDを設定する必要があります。
V2TIMAPNSConfig *confg = [[V2TIMAPNSConfig alloc] init];
/* ユーザー自身でAppleに開発者証明書を登録し、開発者アカウントから証明書(p12ファイル)をダウンロードして生成し、生成されたp12ファイルをTencentの証明書管理コントロールパネルにアップロードすると、コントロールパネルは自動的に証明書IDを生成し、その証明書IDを以下のbusiIdパラメータに入力します。*/
//証明書IDをプッシュ
confg.businessID = sdkBusiId;
confg.token = self.deviceToken;
[[V2TIMManager sharedInstance] setAPNS:confg succ:^{
NSLog(@"%s, succ, %@", __func__, supportTPNS ? @"TPNS": @"APNS");
} fail:^(int code, NSString *msg) {
NSLog(@"%s, fail, %d, %@", __func__, code, msg);
}];

iOSの開発環境下で、登録時たまにdeviceTokenを返さないか、「APNsのtokenリクエストに失敗しました」と表示されます。

この現象は、APNsサービスが不安定の時に発生します。解決策は以下の方法があります。
1. 携帯電話にSIMカードを挿入した後、4Gネットワークでテストしてください。
2. アンインストールして再インストール、アプリを再起動、端末をシャットダウンして再起動してテストしてください。
3. 本番環境のパッケージでテストしてください。
4. 他のiOSスマホでテストしてください。

ヘルプとサポート

この記事はお役に立ちましたか?

フィードバック