You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过客观方法估算VoIP通话MOS值:RTCP数据转换疑问

问题:RTCP数据转换为MOS值的标准参考与代码解析

我需要估算VoIP通话的语音流质量,在ITU G.107标准中找到核心公式:

R = R₀ - Iₛ - I_d - I_eff + A

但不清楚如何从RTP/UDP/IP/Ethernet栈中填充公式的变量值。我在MicroSIP代码库的global.cpp第404行找到相关实现(代码如下),但网络资料和代码注释中均无该公式到代码的转换说明,希望找到可靠的学术或标准参考,明确RTCP数据转换为MOS值的方法。

代码实现

bool msip_call_statistics(call_user_data *user_data, float *MOS)
{
    if (pjsua_var.state != PJSUA_STATE_RUNNING) {
        return false;
    }
    if (!pjsua_call_has_media(user_data->call_id)) {
        return false;
    }
    pjsua_stream_stat stat;
    pj_status_t status = pjsua_call_get_stream_stat(user_data->call_id, 0, &stat);
    if (status != PJ_SUCCESS) {
        return false;
    }

    int LOCAL_DELAY = 30;
    float R;
    float a = 0.0f;
    float b = 19.8f;
    float c = 29.7f;
    float rx_loss = 0.0;
    float rx_jit = 0.0;
    float avg_latency = 0.0;

    int pkt_last = stat.rtcp.rx.pkt - user_data->rx_pkt_prev;
    int loss_last = stat.rtcp.rx.loss - user_data->rx_loss_prev;
    rx_loss = (pkt_last == 0) ? 1.0f : ((float)loss_last / (float)(pkt_last + loss_last));
    user_data->rx_pkt_prev = stat.rtcp.rx.pkt;
    user_data->rx_loss_prev = stat.rtcp.rx.loss;

    rx_jit = (float)stat.rtcp.rx.jitter.last / 1000;

    avg_latency = (stat.rtcp.rtt.last / 2000.0f) + LOCAL_DELAY + PJMEDIA_SND_DEFAULT_PLAY_LATENCY +
        PJMEDIA_SND_DEFAULT_REC_LATENCY + rx_jit;

    {
        float d = avg_latency;
        float d2 = d - 177.3f;
        float Id = 0.024f * d + 0.11f * (d - 177.3f) * (d2 < 0 ? 0 : 1);
        float P = rx_loss;
        float Ie = a + b * (float)log(1 + c * P);
        R = 94.2f - Id - Ie;
    }
    if (R < 0) {
        *MOS = 1;
    }
    else if (R > 100) {
        *MOS = 4.5;
    }
    else {
        *MOS = 1 + 0.035f * R + 7.10f / 1000000 * R * (R - 60) * (100 - R);
    }
    return true;
}

代码与ITU G.107(E-Model)的对应关系

这段代码是E-Model的简化实现,针对VoIP场景做了参数默认取值,对应关系如下:

  • R₀(基准质量分):代码中直接使用94.2f,这是G.711等高质量语音编码的默认基准值,代表无损耗、无延迟的理想语音质量。
  • Iₛ(编码损耗):代码未单独计算,因为默认使用高质量编码,Iₛ已合并到R₀的取值中。
  • I_d(延迟损耗):通过avg_latency计算,完全符合G.107的分段公式:
    • avg_latency由单向网络延迟(RTT/2)、本地处理延迟(30ms)、设备播放/录音延迟、抖动缓冲延迟(rx_jit)组成,这些数据全部来自RTCP统计。
    • 当延迟d ≤ 177.3ms时,I_d = 0.024*d;当d > 177.3ms时,额外叠加0.11*(d-177.3)的惩罚项。
  • I_eff(有效丢包损耗):代码中Ie = a + b*log(1 + c*P),其中P是从RTCP计算出的丢包率(rx_loss),a=0、b=19.8、c=29.7是VoIP场景下的标准经验参数,对应G.107中丢包对语音质量的影响模型。
  • A(用户满意度调整因子):代码未体现,默认取0,该因子仅在特定场景(如降噪、回声消除优化)下添加。

MOS值转换

代码中R值到MOS的映射是标准的E-Model转换公式:

  • 当R < 0时,MOS取最小值1;
  • 当R > 100时,MOS取最大值4.5;
  • 中间范围用多项式MOS = 1 + 0.035R + 7.1e-6*R*(R-60)*(100-R)计算,完全符合ITU标准。

可靠参考资料

  • ITU-T G.107:即E-Model标准,详细定义了R值的计算逻辑、各参数含义及取值范围,是VoIP质量评估的核心依据。
  • ITU-T G.114:定义了VoIP延迟的指标要求,帮助理解I_d参数的计算依据。
  • PJMEDIA官方文档:代码基于PJSUA/PJMEDIA框架,其统计模块的设计完全对齐ITU标准,可参考框架内的语音质量计算逻辑说明。

内容的提问来源于stack exchange,提问作者exception

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 16:11:09