// 实时速率指数平滑(与后端 `Rainbow.Data/Services/RateSmoother.cs` 算法对齐)。
// 上升(有流量)用快时间常数快速跟踪;下降(无流量/降速)用慢时间常数指数衰减,
// 避免"这一帧没统计到流量速度就瞬间归零",近似视频播放器断网后网速缓缓对半下降。
/** 上升时间常数(秒)。有流量时快速跟踪新速率 */
export const RISE_TIME_CONSTANT = 2
/** 下降时间常数(秒)。无流量/降速时按指数衰减,半衰期 ≈ 6×ln2 ≈ 4.2 秒 */
export const FALL_TIME_CONSTANT = 6
/**
* 计算平滑后的速率(B/s)
* @param prev 上一帧平滑速率(B/s);无历史或已衰减到 0 时直接采用瞬时值,保证断流恢复后快速起量
* @param instant 本帧瞬时速率(B/s)
* @param elapsedSec 距上一帧的秒数
* @returns 平滑后速率(B/s),恒非负
*/
export function smoothSpeed(prev: number, instant: number, elapsedSec: number): number {
if (prev <= 0) return Math.max(0, instant)
// 防除零;极短间隔按 0.1s 计,避免瞬时速率被放得过大
const dt = Math.max(elapsedSec, 0.1)
// 上升走快时间常数快速跟踪;下降(含无流量归零)走慢时间常数指数衰减
const tau = instant > prev ? RISE_TIME_CONSTANT : FALL_TIME_CONSTANT
const alpha = 1 - Math.exp(-dt / tau)
return Math.max(0, prev + (instant - prev) * alpha)
}
|