このトピックでは、通話中にネットワーク、音声、および映像の品質をモニタリングする方法について説明します。
機能概要
通話中、RTC SDK は通話およびライブ配信の品質に関連するコールバックをトリガーします。これらのコールバックを使用して、ユーザーのインタラクション体験を評価したり、問題をトラブルシューティングしたり、ユーザー体験を最適化したりできます。また、ユーザーのネットワーク状態が変化した際にも SDK はコールバックをトリガーし、最新の状態を報告します。
サンプルコード
Android 向け通話中の品質モニタリング: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/StreamMonitoring/StreamMonitoringActivity.java。
iOS 向け通話中の品質モニタリング: iOS/ARTCExample/BasicUsage/StreamMonitoring/StreamMonitoringVC.swift。
前提条件
映像設定を構成する前に、以下の要件を満たしている必要があります。
有効な Alibaba Cloud アカウントをお持ちで、ApsaraVideo Real-time Communication アプリケーションを作成済みである必要があります。詳細については、「アプリケーションの作成」をご参照ください。アプリケーション管理コンソールから App ID および App Key を取得してください。
ARTC SDK をプロジェクトに統合済みで、基本的なリアルタイム音声・映像機能を実装済みである必要があります。SDK の統合方法については、「SDK のダウンロードと統合」をご参照ください。音声・映像の実装方法については、「音声・映像通話の実装」をご参照ください。
実装
このドキュメントでは Android を例として使用しています。インターフェイス名はプラットフォームによって異なる場合があります。詳細については、サンプルコードをご参照ください。
アップリンクおよびダウンリンクのネットワーク品質レポート
ネットワーク品質が変化すると、ユーザーは onNetworkQualityChanged コールバックを通じて、アップリンクおよびダウンリンクのネットワーク品質情報を取得できます。
この機能は Linux ではサポートされていません。
uid: ユーザー ID。空の場合は、ローカルユーザーのアップリンクおよびダウンリンクのネットワーク状態を表します。
upQuality: アップリンクのネットワーク状態。
downQuality: ダウンリンクのネットワーク状態。
ネットワーク品質タイプ AliRtcNetworkQuality は次のように定義されています。
列挙値 | 説明 |
AliRtcNetworkExcellent (0) | ネットワーク品質が優れています。 |
AliRtcNetworkGood (1) | ネットワーク品質が良好です。 |
AliRtcNetworkPoor (2) | ネットワーク品質が劣っています。 |
AliRtcNetworkBad (3) | ネットワーク品質が不良です。 |
AliRtcNetworkVeryBad (4) | ネットワーク品質が非常に不良です。 |
AliRtcNetworkDisconnected (5) | ネットワークが切断されています。 |
AliRtcNetworkUnknow (6) | ネットワーク品質が不明です。 |
統計レポート
onAliRtcStats コールバックは 2 秒ごとにトリガーされます。データ転送量、CPU 使用率、通話時間、パケット損失率などのメトリックに関するリアルタイムフィードバックを提供します。メトリックの詳細については、「AliRtcStats」をご参照ください。
音声品質レポート
ローカル音声ストリームの統計情報
onRtcLocalAudioStats コールバックは、ローカル音声送信者のリアルタイム統計情報を提供します。このコールバックは 2 秒ごとにトリガーされます。開発者はこれを使用して、音声品質、ネットワーク状態、アップストリーミング状況をモニターできます。主なメトリックは以下のとおりです。
sentSamplerate: サンプルレート (Hz)。例: 44100 または 48000。現在の音声フレームのサンプリング周波数を示し、音声の明瞭性に影響します。
numChannel: サウンドチャンネル数。例: 1 (モノラル) または 2 (ステレオ)。空間的知覚および伝送オーバーヘッドに影響します。
sentBitrate: 送信ビットレート (kbps)。1 秒間に送信されるエンコード済み音声データ量を示します。ビットレートが高いほど音声品質が向上しますが、帯域幅の使用量も増加します。
その他のメトリックおよび説明については、AliRtcLocalAudioStats をご参照ください。
音声サブスクリプションのデータ統計
onRtcRemoteAudioStats コールバックは、リモートユーザーの音声ストリームに関するリアルタイム統計情報を提供します。このコールバックは 2 秒ごとにトリガーされ、音声品質、ネットワーク状態、再生パフォーマンスに関する詳細なデータを配信します。主なメトリックは以下のとおりです。
quality:
0: Unknown — 品質不明。
1: Excellent — 品質が優れている。
2: Good — 品質が良好(ビットレートがやや低い)。
3: Poor: ユーザー体験が低下しているが、通信には影響がない。
4: Bad — 品質が不良で、通信が中断されている。
5: Very Bad — 品質が非常に不良で、通信がほぼ不可能。
6: NetworkDisconnected — ネットワークが切断されており、通信が不可能。
audioTotalFrozenRate: チャンネル参加時からの音声再生のスタッタリング率。
network_transport_delay: 送信者から受信者へのネットワーク遅延 (ms)。
その他のメトリックおよび説明については、AliRtcRemoteAudioStats をご参照ください。
映像品質レポート
ローカル映像ストリームの統計情報
onRtcLocalVideoStats コールバックは、ローカル映像送信者のリアルタイム統計情報を提供します。このコールバックは 2 秒ごとにトリガーされます。開発者はこれを使用して、ビデオエンコーディング品質、ネットワーク状態、アップストリーミング状況をモニターできます。主なメトリックは以下のとおりです。
actualEncodeBitrate: エンコーディング時に使用された実際のエンコードビットレート。
sentBitrate: 送信ビットレート (kbps)。ネットワーク上で送信された実際の映像ビットレートを示します。
captureFps, encodeFps, sentFps: 映像キャプチャ、エンコーディング、送信のフレームレート。
avgQp: 1 秒あたりの平均量子化パラメーター (QP)。ビデオエンコーディング品質を反映します。QP 値が低いほど圧縮率が低くなります。
その他のメトリックおよび説明については、AliRtcLocalVideoStats をご参照ください。
映像サブスクリプションのデータ統計
onRtcRemoteVideoStats コールバックは、リモートユーザーの映像ストリームに関するリアルタイム統計情報を提供します。このコールバックは 2 秒ごとにトリガーされ、映像品質、ネットワーク状態、再生パフォーマンスに関する詳細なデータを配信します。主なメトリックは以下のとおりです。
width, height: 映像解像度。
decodeFps, renderFps: 映像デコードおよびレンダリングのフレームレート。
videoTotalFrozenRate: 累積的な映像再生スタッタリング率。
その他のメトリックおよび説明については、AliRtcRemoteVideoStats をご参照ください。
Android
// アップリンクおよびダウンリンクのネットワーク品質
private AliRtcEngineEventListener mRtcEngineEventListener = new AliRtcEngineEventListener() {
// ネットワーク品質の変化
@Override
public void onNetworkQualityChanged(String uid, AliRtcEngine.AliRtcNetworkQuality upQuality, AliRtcEngine.AliRtcNetworkQuality downQuality){
super.onNetworkQualityChanged(uid, upQuality, downQuality);
// TODO: ビジネスロジックを追加
}
}
// 統計情報コールバック
private AliRtcEngineNotify mRtcEngineNotify = new AliRtcEngineNotify() {
@Override
public void onAliRtcStats(AliRtcEngine.AliRtcStats stats){
super.onAliRtcStats(stats);
mRtcStats = stats;
updateStatsDisplay();
}
@Override
public void onRtcLocalAudioStats(AliRtcEngine.AliRtcLocalAudioStats aliRtcStats){
super.onRtcLocalAudioStats(aliRtcStats);
mLocalAudioStats = aliRtcStats;
}
@Override
public void onRtcRemoteAudioStats(AliRtcEngine.AliRtcRemoteAudioStats aliRtcStats){
super.onRtcRemoteAudioStats(aliRtcStats);
mRemoteAudioStats = aliRtcStats;
}
@Override
public void onRtcLocalVideoStats(AliRtcEngine.AliRtcLocalVideoStats aliRtcLocalVideoStats){
super.onRtcLocalVideoStats(aliRtcLocalVideoStats);
mLocalVideoStats = aliRtcLocalVideoStats;
}
@Override
public void onRtcRemoteVideoStats(AliRtcEngine.AliRtcRemoteVideoStats aliRtcRemoteVideoStats){
super.onRtcRemoteVideoStats(aliRtcRemoteVideoStats);
mRemoteVideoStats = aliRtcRemoteVideoStats;
// すべての統計情報を表示に更新
updateStatsDisplay();
}
}iOS
extension StreamMonitoringMainVC: AliRtcEngineDelegate {
// MARK: ネットワーク品質
func onNetworkQualityChanged(_ uid: String, up upQuality: AliRtcNetworkQuality, downNetworkQuality downQuality: AliRtcNetworkQuality) {
}
// MARK: ストリームモニタリングコールバック
func onRtcStats(_ stats: AliRtcStats) {
}
func onRtcLocalAudioStats(_ localAudioStats: AliRtcLocalAudioStats) {
}
func onRtcRemoteAudioStats(_ remoteAudioStats: AliRtcRemoteAudioStats) {
}
func onRtcLocalVideoStats(_ localVideoStats: AliRtcLocalVideoStats) {
}
func onRtcRemoteVideoStats(_ remoteVideoStats: AliRtcRemoteVideoStats) {
}
}Mac
- (void)onNetworkQualityChanged:(NSString *)uid upNetworkQuality:(AliRtcNetworkQuality)upQuality downNetworkQuality:(AliRtcNetworkQuality)downQuality{
NSLog(@"onNetworkQualityChanged callback!");
}
- (void)onRtcStats:(AliRtcStats)stats{
/* */
NSLog(@"onRtcStats callback!");
}
- (void)onRtcLocalAudioStats:(AliRtcLocalAudioStats *)localAudioStats {
NSLog(@"onRtcLocalAudioStats callback!");
}
- (void)onRtcRemoteAudioStats:(AliRtcRemoteAudioStats *)remoteAudioStats {
NSLog(@"onRtcRemoteAudioStats callback!");
}
- (void)onRtcLocalVideoStats:(AliRtcLocalVideoStats *)localVideoStats{
NSLog(@"onRtcLocalVideoStats callback!");
}
- (void)onRtcRemoteVideoStats:(AliRtcRemoteVideoStats *)remoteVideoStats{
NSLog(@"onRtcRemoteVideoStats callback!");
}
Windows
/* ローカル映像ステータス */
void CTutorialDlg::OnLocalVideoStats(const AliEngineLocalVideoStats& localVideoStats)
{
if (m_pRtcStatsDlg != nullptr) {
m_pRtcStatsDlg->setLocalVideoStats(localVideoStats);
}
}
/* ローカル音声ステータス */
void CTutorialDlg::OnLocalAudioStats(const AliEngineLocalAudioStats& localVideoStats)
{
if (nullptr != m_pRtcStatsDlg)
{
m_pRtcStatsDlg->setLocalAudioStats(localVideoStats);
}
}
/* ネットワークステータス */
void CTutorialDlg::OnNetworkQualityChanged(const char *uid,
AliEngineNetworkQuality upQuality,
AliEngineNetworkQuality downQuality)
{
// ネットワーク品質の変化を処理
}
/* リモート音声ステータス */
void CTutorialDlg::OnRemoteAudioStats(const AliEngineRemoteAudioStats& remoteAudioStats)
{
CString strText, strTemp;
switch (remoteAudioStats.track)
{
case AliEngineAudioTrackMic:
strText = _T("AudioTrackMic");
break;
default:
strText = _T("AudioTrackNo");
break;
}
strText += _T(": { ");
strTemp.Format(_T("quality: %d,"), remoteAudioStats.quality);
strText += strTemp;
strTemp.Format(_T("audio_loss_rate: %d,"), remoteAudioStats.audioLossRate);
strText += strTemp;
strTemp.Format(_T("rcvd_bitrate: %d,"), remoteAudioStats.rcvdBitrate);
strText += strTemp;
strTemp.Format(_T("total_frozen_times: %d,"), remoteAudioStats.totalFrozenTimes);
strText += strTemp;
strTemp.Format(_T("network_transport_delay: %d,"), remoteAudioStats.networkTransportDelay);
strText += strTemp;
strTemp.Format(_T("jitter_buffer_delay: %d }\n"), remoteAudioStats.jitterBufferDelay);
strText += strTemp;
CString strid = AliStringToCString(remoteAudioStats.userId);
/* ステータスマップに書き込みます。UI はタイマー経由で読み取り、表示します。 */
m_MuteUserAudioStats.Lock();
m_UserAudioStatsMap[strid] = strText;
m_MuteUserAudioStats.Unlock();
}
/* リモート映像ステータス */
void CTutorialDlg::OnRemoteVideoStats(const AliEngineRemoteVideoStats& remoteVideoStats)
{
CString strText, strTemp, strStats;
CString strid = AliStringToCString(remoteVideoStats.userId);
auto iter = m_UserVideoStatsMap.find(strid);
if (iter != m_UserVideoStatsMap.end())
{
strStats = iter->second;
}
switch (remoteVideoStats.track)
{
case AliEngineVideoTrackCamera:
strText = _T("TrackCamera");
break;
case AliEngineVideoTrackScreen:
strText = _T("TrackScreen");
break;
case AliEngineVideoTrackBoth:
strText = _T("TrackBoth");
break;
default:
strText = _T("TrackNo");
break;
}
delRepeatTrackStatic(strStats, strText);
strText += _T(": { ");
strTemp.Format(_T("Width: %d,"), remoteVideoStats.width);
strText += strTemp;
strTemp.Format(_T("Height: %d,"), remoteVideoStats.height);
strText += strTemp;
strTemp.Format(_T("Decode_fps: %d,"), remoteVideoStats.decodeFps);
strText += strTemp;
strTemp.Format(_T("Render_fps: %d,"), remoteVideoStats.renderFps);
strText += strTemp;
strTemp.Format(_T("Frozen_times: %d }\n"), remoteVideoStats.frozenTimes);
strText += strTemp;
strStats += strText;
/* ステータスマップに書き込みます。UI はタイマー経由で読み取り、表示します。 */
m_MutexUserVideoStats.Lock();
m_UserVideoStatsMap[strid] = strStats;
m_MutexUserVideoStats.Unlock();
}
/* エンジングローバルステータス */
void CTutorialDlg::OnStats(const AliEngineStats& stats)
{
AliEngineStats* pStats = new AliEngineStats;
if (pStats == nullptr)
{
return;
}
/* グローバルステータスは UI モジュールに送信し、表示することも可能です。 */
*pStats = stats;
PostMessage(MM_UPDATE_STATS, (WPARAM)pStats, 0);
}Linux
EngineEventHandlerInterface クラス内のコールバックインターフェイスを実装します。
/**
* @brief セッション統計情報コールバック
* @param stats セッション統計情報
* @note SDK はこのコールバックを 2 秒ごとにトリガーします。
*/
virtual void OnStats(const AliRTCSdk::Linux::AliEngineStats& stats) {}
/**
* @brief ローカル映像統計情報
* @param localVideoStats ローカル映像統計情報
* @note SDK はこのコールバックを 2 秒ごとにトリガーします。
*/
virtual void OnLocalVideoStats(const AliRTCSdk::Linux::AliEngineLocalVideoStats& localVideoStats) {}
/**
* @brief リモート映像統計情報
* @param remoteVideoStats リモート映像統計情報
* @note SDK はこのコールバックを 2 秒ごとにトリガーします。
*/
virtual void OnRemoteVideoStats(const AliRTCSdk::Linux::AliEngineRemoteVideoStats& remoteVideoStats) {}
/**
* @brief ローカル音声統計情報
* @param localAudioStats ローカル音声統計情報
* @note SDK はこのコールバックを 2 秒ごとにトリガーします。
*/
virtual void OnLocalAudioStats(const AliRTCSdk::Linux::AliEngineLocalAudioStats& localAudioStats) {}
/**
* @brief リモート音声統計情報
* @param remoteAudioStats リモート音声統計情報
* @note SDK はこのコールバックを 2 秒ごとにトリガーします。
*/
virtual void OnRemoteAudioStats(const AliRTCSdk::Linux::AliEngineRemoteAudioStats& remoteAudioStats) {}