Monitore a qualidade da rede, do áudio e do vídeo durante uma chamada para solucionar problemas e otimizar a experiência do usuário.
Introdução ao Recurso
Durante uma chamada, o RTC SDK aciona callbacks relacionados à qualidade da chamada e da transmissão ao vivo. Use esses callbacks para avaliar a qualidade da interação, solucionar problemas e otimizar a experiência do usuário. O SDK também relata alterações no status da rede por meio de callbacks dedicados.
Código de Exemplo
Monitoramento de qualidade durante a chamada para Android: Android/ARTCExample/BasicUsage/src/main/java/com/aliyun/artc/api/basicusage/StreamMonitoring/StreamMonitoringActivity.java.
Monitoramento de qualidade durante a chamada para iOS: iOS/ARTCExample/BasicUsage/StreamMonitoring/StreamMonitoringVC.swift.
Pré-requisitos
Antes de começar, verifique se os seguintes requisitos foram atendidos:
Você possui uma conta Alibaba Cloud válida e crie um aplicativo ApsaraVideo Real-time Communication. Para mais informações, consulte Criar Aplicativo. Obtenha seu App ID e App Key no Console de Gerenciamento de Aplicativos.
Você integrou o ARTC SDK ao seu projeto e implementou recursos básicos de áudio e vídeo em tempo real. Para integração do SDK, consulte Baixe e Integração do SDK. Para implementação de áudio e vídeo, consulte Implementar Chamadas de Áudio e Vídeo.
Implementação
Os exemplos a seguir usam Android. Os nomes das interfaces podem variar entre plataformas. Para detalhes, consulte o código de exemplo.
Relatórios de Qualidade de Rede de Uplink e Downlink
Quando a qualidade da rede muda, o callback onNetworkQualityChanged relata a qualidade da rede de uplink e downlink.
Este recurso não tem suporte no Linux.
uid: ID do usuário. Se estiver vazio, representa o status da rede de uplink e downlink do usuário local.
upQuality: Status da rede de uplink.
downQuality: Status da rede de downlink.
O tipo de qualidade de rede AliRtcNetworkQuality é definido da seguinte forma:
|
Valor da Enumeração |
Descrição |
|
AliRtcNetworkExcellent (0) |
Qualidade de rede excelente. |
|
AliRtcNetworkGood (1) |
Boa qualidade de rede. |
|
AliRtcNetworkPoor (2) |
Qualidade de rede ruim. |
|
AliRtcNetworkBad (3) |
Má qualidade de rede. |
|
AliRtcNetworkVeryBad (4) |
Qualidade de rede muito ruim. |
|
AliRtcNetworkDisconnected (5) |
Rede desconectada. |
|
AliRtcNetworkUnknow (6) |
Qualidade de rede desconhecida. |
Relatórios de Estatísticas
O callback onAliRtcStats é acionado a cada 2 segundos e fornece estatísticas em tempo real sobre transmissão de dados, uso de CPU, duração da chamada e taxa de perda de pacotes. Para mais informações sobre métricas, consulte AliRtcStats.
Relatórios de Qualidade de Áudio
Estatísticas do Stream de Áudio Local
O callback onRtcLocalAudioStats é acionado a cada 2 segundos e fornece estatísticas em tempo real para o remetente de áudio local, incluindo qualidade de áudio, condições de rede e status de ingestão de stream. As principais métricas incluem:
sentSamplerate: Taxa de amostragem (Hz), como 44100 ou 48000. Indica a frequência de amostragem do quadro de áudio atual e afeta a clareza do áudio.
numChannel: Número de canais de som, como 1 (mono) ou 2 (estéreo). Afeta a percepção espacial e a sobrecarga de transmissão.
sentBitrate: Bitrate enviado (kbps). Indica a quantidade de dados de áudio codificados enviados por segundo. Bitrates mais altos melhoram a qualidade do áudio, mas aumentam o uso de largura de banda.
Para mais métricas e descrições, consulte AliRtcLocalAudioStats.
Estatísticas de Dados de Assinatura de Áudio
O callback onRtcRemoteAudioStats é acionado a cada 2 segundos e fornece estatísticas em tempo real para streams de áudio remotos, incluindo qualidade de áudio, condições de rede e desempenho de reprodução. As principais métricas incluem:
-
quality:
0: Unknown — Qualidade desconhecida.
1: Excellent — Qualidade excelente.
2: Good — Boa qualidade com bitrate ligeiramente inferior.
3: Poor: A experiência do usuário é degradada, mas a comunicação não é afetada.
4: Bad — Qualidade ruim; a comunicação é interrompida.
5: Very Bad — Qualidade muito ruim; a comunicação é quase impossível.
6: NetworkDisconnected — Rede desconectada; nenhuma comunicação possível.
audioTotalFrozenRate: Taxa de travamento da reprodução de áudio desde a entrada no canal.
network_transport_delay: Latência de rede do remetente ao receptor (ms).
Para mais métricas e descrições, consulte AliRtcRemoteAudioStats.
Relatórios de Qualidade de Vídeo
Estatísticas do Stream de Vídeo Local
O callback onRtcLocalVideoStats é acionado a cada 2 segundos e fornece estatísticas em tempo real para o remetente de vídeo local, incluindo qualidade de codificação, condições de rede e status de ingestão de stream. As principais métricas incluem:
actualEncodeBitrate: Bitrate de codificação real usado durante a codificação.
sentBitrate: Bitrate enviado (kbps). Indica o bitrate de vídeo real enviado pela rede.
captureFps, encodeFps, sentFps: Taxas de quadros para captura, codificação e envio de vídeo.
avgQp: Parâmetro de Quantização (QP) médio por segundo. Reflete a qualidade da codificação de vídeo. Valores de QP mais baixos indicam menor compressão.
Para mais métricas e descrições, consulte AliRtcLocalVideoStats.
Estatísticas de Dados de Assinaturas de Vídeo
O callback onRtcRemoteVideoStats é acionado a cada 2 segundos e fornece estatísticas em tempo real para streams de vídeo remotos, incluindo qualidade de vídeo, condições de rede e desempenho de reprodução. As principais métricas incluem:
width, height: Resolução do vídeo.
decodeFps, renderFps: Taxas de quadros para decodificação e renderização de vídeo.
videoTotalFrozenRate: Taxa cumulativa de travamento da reprodução de vídeo.
Para mais métricas e descrições, consulte AliRtcRemoteVideoStats.
Android
// Uplink and downlink network quality
private AliRtcEngineEventListener mRtcEngineEventListener = new AliRtcEngineEventListener() {
// Network quality change
@Override
public void onNetworkQualityChanged(String uid, AliRtcEngine.AliRtcNetworkQuality upQuality, AliRtcEngine.AliRtcNetworkQuality downQuality){
super.onNetworkQualityChanged(uid, upQuality, downQuality);
// TODO: Add business logic
}
}
// Statistics callback
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;
// Update display for all statistics
updateStatsDisplay();
}
}
iOS
extension StreamMonitoringMainVC: AliRtcEngineDelegate {
// MARK: Network Quality
func onNetworkQualityChanged(_ uid: String, up upQuality: AliRtcNetworkQuality, downNetworkQuality downQuality: AliRtcNetworkQuality) {
}
// MARK: Stream Monitoring Callback
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
/* Local video status */
void CTutorialDlg::OnLocalVideoStats(const AliEngineLocalVideoStats& localVideoStats)
{
if (m_pRtcStatsDlg != nullptr) {
m_pRtcStatsDlg->setLocalVideoStats(localVideoStats);
}
}
/* Local audio status */
void CTutorialDlg::OnLocalAudioStats(const AliEngineLocalAudioStats& localVideoStats)
{
if (nullptr != m_pRtcStatsDlg)
{
m_pRtcStatsDlg->setLocalAudioStats(localVideoStats);
}
}
/* Network status */
void CTutorialDlg::OnNetworkQualityChanged(const char *uid,
AliEngineNetworkQuality upQuality,
AliEngineNetworkQuality downQuality)
{
// Handle network quality change
}
/* Remote audio status */
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);
/* Write to status map. UI reads and displays it via timer. */
m_MuteUserAudioStats.Lock();
m_UserAudioStatsMap[strid] = strText;
m_MuteUserAudioStats.Unlock();
}
/* Remote video status */
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;
/* Write to status map. UI reads and displays it via timer. */
m_MutexUserVideoStats.Lock();
m_UserVideoStatsMap[strid] = strStats;
m_MutexUserVideoStats.Unlock();
}
/* Engine global status */
void CTutorialDlg::OnStats(const AliEngineStats& stats)
{
AliEngineStats* pStats = new AliEngineStats;
if (pStats == nullptr)
{
return;
}
/* Global status can also be sent to the UI module for display. */
*pStats = stats;
PostMessage(MM_UPDATE_STATS, (WPARAM)pStats, 0);
}
Linux
Implemente as interfaces de callback na classe EngineEventHandlerInterface.
/**
* @brief Session statistics callback
* @param stats Session statistics
* @note SDK triggers this callback every two seconds.
*/
virtual void OnStats(const AliRTCSdk::Linux::AliEngineStats& stats) {}
/**
* @brief Local video statistics
* @param localVideoStats Local video statistics
* @note SDK triggers this callback every two seconds.
*/
virtual void OnLocalVideoStats(const AliRTCSdk::Linux::AliEngineLocalVideoStats& localVideoStats) {}
/**
* @brief Remote video statistics
* @param remoteVideoStats Remote video statistics
* @note SDK triggers this callback every two seconds.
*/
virtual void OnRemoteVideoStats(const AliRTCSdk::Linux::AliEngineRemoteVideoStats& remoteVideoStats) {}
/**
* @brief Local audio statistics
* @param localAudioStats Local audio statistics
* @note SDK triggers this callback every two seconds.
*/
virtual void OnLocalAudioStats(const AliRTCSdk::Linux::AliEngineLocalAudioStats& localAudioStats) {}
/**
* @brief Remote audio statistics
* @param remoteAudioStats Remote audio statistics
* @note SDK triggers this callback every two seconds.
*/
virtual void OnRemoteAudioStats(const AliRTCSdk::Linux::AliEngineRemoteAudioStats& remoteAudioStats) {}