直播在强网下跑通并不难,真正拉开体验差距的是地铁、电梯、跨小区、拥塞 Wi-Fi 等弱网场景。HarmonyOS 7 的网络增强方向包含弱网信号感知、直播优化以及一进二出编码等能力。工程上不能把它理解为“检测到弱网就把码率调低”,因为码率、分辨率、帧率、GOP、缓冲、编码负载和恢复速度相互影响。

本文设计一套端到端弱网直播控制器:用可解释信号形成网络等级,用双路编码准备高低两套码流,用迟滞状态机切换,再用播放、功耗和画质指标共同验收。

HarmonyOS 7 新特性(四十二)封面

一、弱网不是单个信号值

仅看信号格或瞬时 RTT 都容易误判。需要把吞吐、往返时延、抖动、丢包、发送队列和重传趋势组合起来。

interface NetworkSample {
  uplinkKbps: number
  rttMs: number
  jitterMs: number
  lossRate: number
  queueMs: number
  capturedAt: number
}

type NetworkGrade = 'GOOD' | 'FAIR' | 'POOR' | 'CRITICAL'

系统或 Network Boost Kit 提供的弱信号判断适合作为输入之一,但业务仍要结合实时推流统计;“无线信号弱”和“当前可用上传带宽不足”不是同一件事。

二、滑动窗口抑制瞬时抖动

一次采样不能触发切换。保留最近数秒的窗口,计算分位值和趋势。

class NetworkWindow {
  private values: NetworkSample[] = []

  push(sample: NetworkSample) {
    this.values.push(sample)
    const cutoff = sample.capturedAt - 8_000
    this.values = this.values.filter(v => v.capturedAt >= cutoff)
  }

  p90Rtt(): number { return percentile(this.values.map(v => v.rttMs), 0.9) }
  avgLoss(): number { return average(this.values.map(v => v.lossRate)) }
}

窗口太短会频繁震荡,太长又会反应迟缓。直播上行通常使用“快速降级、谨慎升级”的不对称策略。

三、把网络等级变成可解释规则

规则必须可配置、可回放,而不是把大量魔法数字散在回调里。

interface GradeThreshold {
  minUplinkKbps: number
  maxRttMs: number
  maxLossRate: number
  maxQueueMs: number
}

function classify(s: NetworkSample, t: GradeThreshold): NetworkGrade {
  if (s.uplinkKbps < t.minUplinkKbps * 0.55 || s.lossRate > 0.12) return 'CRITICAL'
  if (s.uplinkKbps < t.minUplinkKbps || s.queueMs > t.maxQueueMs) return 'POOR'
  if (s.rttMs > t.maxRttMs || s.lossRate > t.maxLossRate) return 'FAIR'
  return 'GOOD'
}

阈值应按业务类型、分辨率和设备能力远端配置,并记录触发原因,便于复盘。

四、一进二出解决切换准备时间

传统方案在弱网出现后再重建编码器,可能产生黑帧、关键帧等待和数百毫秒空窗。一进二出让同一原始画面同时产出高、低两路编码结果,切换时选择已准备好的码流。

interface StreamProfile {
  id: 'HIGH' | 'LOW'
  width: number
  height: number
  fps: number
  bitrateKbps: number
  gopSeconds: number
}

const profiles: StreamProfile[] = [
  { id: 'HIGH', width: 1920, height: 1080, fps: 30, bitrateKbps: 4200, gopSeconds: 2 },
  { id: 'LOW', width: 1280, height: 720, fps: 24, bitrateKbps: 1500, gopSeconds: 1 }
]

低路的 GOP 可更短,便于快速切入,但会增加码率开销,需要压测。

HarmonyOS 7 新特性(四十二)核心链路

五、双路编码并非免费

同时编码会增加 GPU/NPU/编解码器占用、功耗和温升。支持性、分辨率上限和并发能力必须按设备查询和验证。

interface EncoderCapability {
  dualOutputSupported: boolean
  maxPixelsPerSecond: number
  thermalBudget: 'LOW' | 'MID' | 'HIGH'
}

function chooseMode(c: EncoderCapability): 'DUAL' | 'SINGLE_ABR' {
  return c.dualOutputSupported && c.thermalBudget !== 'LOW'
    ? 'DUAL' : 'SINGLE_ABR'
}

不支持设备回退为单路动态调参,不能让“新特性”成为直播入口门槛。

六、设计带迟滞的状态机

网络稍有恢复就立刻升码率,会形成高低档反复横跳。降级阈值与升级阈值必须不同。

type StreamState = 'HIGH' | 'LOW' | 'AUDIO_SAFE'

class AbrStateMachine {
  state: StreamState = 'HIGH'
  private goodSince = 0

  next(grade: NetworkGrade, now: number): StreamState {
    if (grade === 'CRITICAL') return this.state = 'AUDIO_SAFE'
    if (grade === 'POOR') return this.state = 'LOW'
    if (grade === 'GOOD') {
      if (!this.goodSince) this.goodSince = now
      if (now - this.goodSince > 12_000) this.state = 'HIGH'
    } else {
      this.goodSince = 0
    }
    return this.state
  }
}

从音频保底恢复时先回低路,确认发送队列下降后再升高路。

七、切换点要对齐关键帧

服务端或播放器在非关键帧切换可能解码失败。切换请求应等待目标路下一关键帧,并携带连续时间戳。

interface EncodedFrame {
  profile: 'HIGH' | 'LOW'
  ptsUs: number
  keyFrame: boolean
  payload: ArrayBuffer
}

function canSwitch(frame: EncodedFrame, target: string): boolean {
  return frame.profile === target && frame.keyFrame
}

两路输出共享统一时间基准。切换期间避免重复或倒退的 PTS,音视频同步也要独立验证。

八、发送队列比编码目标更重要

编码器把码率降下来不代表拥塞立即消失。旧队列仍可能积压数秒,继续发送只会让直播越来越“延迟”。

interface QueuePolicy {
  maxVideoQueueMs: number
  keepLatestKeyFrame: boolean
  dropNonKeyFirst: boolean
}

function shouldDrop(queueMs: number, policy: QueuePolicy): boolean {
  return queueMs > policy.maxVideoQueueMs
}

实时直播应优先保证“新鲜”,超过时延预算后丢弃部分旧视频帧,并保持音频连续与下一关键帧可解码。

九、画质、连续性与时延共同优化

弱网策略不是单目标。过度降码率会产生马赛克;过大缓冲会让互动失去实时性;频繁丢帧又会导致卡顿。

interface LiveQualityMetric {
  freezeRate: number
  glassToGlassMs: number
  droppedFrames: number
  bitrateKbps: number
  switchCount: number
  thermalLevel: number
}

业务应明确优先级:连麦强调时延,赛事直播强调连续,带货强调主播画面清晰。统一算法可通过场景参数调整,而不是复制多套实现。

十、错误与用户感知

短暂降级无需弹窗;持续弱网可以显示轻提示,但不要把技术指标直接暴露给用户。只有音频保底或即将断流时,才提示切换网络或降低画质。

function userHint(state: StreamState, lastedMs: number): string | undefined {
  if (state === 'AUDIO_SAFE' && lastedMs > 3000) return '网络较弱,已优先保障声音'
  if (state === 'LOW' && lastedMs > 15000) return '正在使用流畅画质'
  return undefined
}

提示要可访问、不过度打扰,也不能遮挡直播核心操作。

十一、可回放的弱网测试

人工走进电梯无法稳定复现。使用固定网络脚本模拟带宽下降、突发丢包、高 RTT、抖动和恢复。

[
  { "at": 0, "uplinkKbps": 6000, "loss": 0.00, "rttMs": 40 },
  { "at": 20, "uplinkKbps": 900, "loss": 0.08, "rttMs": 260 },
  { "at": 40, "uplinkKbps": 350, "loss": 0.16, "rttMs": 520 },
  { "at": 60, "uplinkKbps": 5000, "loss": 0.01, "rttMs": 55 }
]

每次构建在同一设备、同一脚本和同一素材下比较,保存编码日志、队列、温度与接收端录制。

十二、上线清单

  • 弱网等级综合多种信号,而非单点判断;
  • 滑动窗口和迟滞避免码率震荡;
  • 双路编码按设备能力与热预算启用;
  • 低档或不支持设备能回退单路 ABR;
  • 切换对齐关键帧并保持时间戳连续;
  • 发送队列超过预算时优先保证实时性;
  • 音频保底和恢复路径经过验证;
  • 固定网络脚本可重复回放;
  • 指标同时覆盖卡顿、时延、画质、切换与温升;
  • 参数具备灰度和远端回滚能力。

HarmonyOS 7 新特性(四十二)检查清单

结语

HarmonyOS 7 弱网直播能力的价值,不是某个孤立接口,而是从网络感知、编码准备、状态切换、发送队列到体验指标形成闭环。一进二出缩短了切换准备时间,Network Boost 类信号帮助提前预判,但最终仍要由可解释状态机与真实设备证据决定是否升级或降级。把快速降级、谨慎恢复和设备回退做好,直播才会在真实移动网络中稳定。

官方参考

  • HarmonyOS 7 新能力一览:https://developer.huawei.com/consumer/cn/features/
  • 弱网信号感知:https://developer.huawei.com/consumer/en/doc/harmonyos-guides-V13/networkboost-weaksignaljudge-V13
  • 一进二出编码与弱网自适应:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/video-encoding-preproc-one-in-dual-out
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐