HarmonyOS 鸿蒙Next中AVPlayer播放HLS流媒体视频时,设置seek后实际播放位置和seek位置有很大偏差

HarmonyOS 鸿蒙Next中AVPlayer播放HLS流媒体视频时,设置seek后实际播放位置和seek位置有很大偏差

组件功能操作流程如下:组件加载自动播放视频,然后我拖动Slider调用seek方法,此时日志记录seek设置的time,通过avplayer的Events.TIME_UPDATE事件监控输出time,发现seek的time和播放的time差了好多,大部分时候time直接变0了,有的时候差了很多很多

播放的是hls类型,m3u8格式的流媒体,媒体是服务器转码的。我知道可能是媒体的原因,但能否有人帮忙解惑下对流媒体有什么要求?

代码部分如下,进度条:

Slider({
  value: this.progressVal,
  min: 0,
  max: 100,
  step: 1,
})
.onChange((value: number, mode: SliderChangeMode) => {
  this.mediaController?.setSeekTime(value, mode)
  // ...
})

mediaController的setSeekTime代码:

setSeekTime(value: number, mode: SliderChangeMode) {
  if (mode === Number(SliderMode.MOVING)) {
    // 拖动进度条回显处理
  }
  this.seekTime = Math.round(value * this.duration / ONE_HUNDRED)
  if (mode == Number(SliderChangeMode.Begin)) {
    return
  }
  if (mode === Number(SliderChangeMode.End) || mode === Number(SliderChangeMode.Click)) {
    if (this.avPlayer !== null) {
      logger.debug(`time set: percent: ${value}, time: ${this.seekTime}`)
      this.avPlayer.seek(this.seekTime, media.SeekMode.SEEK_CLOSEST)
      this.avPlayer.play()
    }
  }
}

avPlayer事件监听:

this.avPlayer.on(Events.STATE_CHANGE, async (state: media.AVPlayerState) => {
  // ...
  switch (avplayerStatus) {
    case AvplayerStatus.IDLE:
      // 初始化进度URL等
      break
    case AvplayerStatus.INITIALIZED:
      // 初始化surfaceId等
      this.avPlayer.prepare()
      break
    case AvplayerStatus.PREPARED:
      this.duration = this.avPlayer.duration
      // 其他初始化行为以及父级事件回调
      break
    case AvplayerStatus.PLAYING:
      // 设置声音和播放状态等
      break
    case AvplayerStatus.PAUSED:
      // 暂停播放处理
      break
    case AvplayerStatus.COMPLETED:
      // 播放完成处理
      this.avPlayer.reset()
      break
    case AvplayerStatus.RELEASED:
      this.avPlayer.release()
      // 其他释放资源行为
      break
    default:
      break
  }
})
this.avPlayer.on(Events.TIME_UPDATE, (time: number) => {
  this.loadProgress(time)
})

loadProgress代码:

loadProgress(time: number) {
  let nowSeconds = Math.floor(time / A_THOUSAND)
  let totalSeconds = Math.floor(this.duration / A_THOUSAND)
  const dateTimeNow = date.secondToTime(nowSeconds)
  if (this.mediaPlayerInfo.currentTime == dateTimeNow) {
    return
  }
  this.mediaPlayerInfo.currentTime = dateTimeNow
  this.mediaPlayerInfo.totalTime = date.secondToTime(totalSeconds)
  this.mediaPlayerInfo.progressVal = Math.floor(nowSeconds * ONE_HUNDRED / totalSeconds)
  logger.debug(`time get: percent: ${this.mediaPlayerInfo.progressVal}, time: ${time}`)
  this.triggerTimeUpdate()
}

play方法代码:

play() {
  if (this.avPlayer && (this.avPlayer.state === AvplayerStatus.PAUSED || this.avPlayer.state === AvplayerStatus.PREPARED
    || this.avPlayer.state === AvplayerStatus.COMPLETED || this.avPlayer.state === AvplayerStatus.STOPPED)) {
    this.avPlayer.play()
  }
}

服务器转码,码率设置很低,然后进入页面开始播放,拖动Slider松开,然后等视频正常播放再次拖动松开重复,从日志可以看到,每次拖动设置的是正确的seek,以及第一次get是正确的,但是马上time就变为0了

06-05 01:53:47.260   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: initialized
06-05 01:53:48.820   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: prepared
06-05 01:53:48.820   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: prepared
06-05 01:53:48.838   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: playing
06-05 01:53:49.937   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1034
06-05 01:53:50.646   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1745
06-05 01:53:50.747   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1840
06-05 01:53:50.850   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1942
06-05 01:53:50.950   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2043
06-05 01:53:50.972   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time set: percent: 36, time: 2664745
06-05 01:53:57.905   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 35, time: 2664745
06-05 01:53:57.905   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 170
06-05 01:53:58.811   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1066
06-05 01:53:59.824   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2090
06-05 01:54:00.750   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3007
06-05 01:54:00.935   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3199
06-05 01:54:00.953   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3199
06-05 01:54:01.037   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3285
06-05 01:54:01.053   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3306
06-05 01:54:01.137   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3391
06-05 01:54:01.240   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3498
06-05 01:54:01.360   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time set: percent: 51, time: 3775055
06-05 01:54:08.578   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 50, time: 3775055
06-05 01:54:08.579   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 170
06-05 01:54:09.433   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1002
06-05 01:54:10.434   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2005
06-05 01:54:10.859   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2453
06-05 01:54:10.902   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2495
06-05 01:54:10.941   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2538
06-05 01:54:10.961   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2559
06-05 01:54:11.042   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2623
06-05 01:54:11.061   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2645
06-05 01:54:11.106   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2687
06-05 01:54:11.143   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2730
06-05 01:54:11.163   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2751
06-05 01:54:11.206   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2794
06-05 01:54:11.245   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2837
06-05 01:54:11.308   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2879
06-05 01:54:11.346   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2922
06-05 01:54:11.447   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3029
06-05 01:54:11.966   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time set: percent: 94, time: 6957945
06-05 01:54:19.127   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 93, time: 6957945
06-05 01:54:19.128   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 42
06-05 01:54:20.000   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1023
06-05 01:54:21.010   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2047
06-05 01:54:21.589   12217-12217   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: released

当我把码率设置高一点,然后再播放,同样的代码操作日志如下:可以看出来进度不会回到0了,稍微正常一点,但是仍有偏差,可以确认是源的原因了,是因为不兼容?有没有官方或者大佬解答下,快崩溃了…

06-05 02:03:17.383   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: initialized
06-05 02:03:18.281   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: prepared
06-05 02:03:18.282   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: prepared
06-05 02:03:18.305   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: playing
06-05 02:03:19.398   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1032
06-05 02:03:20.205   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1828
06-05 02:03:20.307   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1930
06-05 02:03:20.407   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2027
06-05 02:03:20.510   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2127
06-05 02:03:20.624   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time set: percent: 27, time: 1998559
06-05 02:03:21.087   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 26, time: 1998559
06-05 02:03:21.087   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2447701
06-05 02:03:21.593   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2448063
06-05 02:03:22.601   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2449069
06-05 02:03:22.827   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2449296
06-05 02:03:22.904   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2449367
06-05 02:03:22.930   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2449391
06-05 02:03:23.006   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2449467
06-05 02:03:23.028   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 33, time: 2449491
06-05 02:03:23.104   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time set: percent: 61, time: 4515262
06-05 02:03:23.566   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5498368
06-05 02:03:24.270   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5499025
06-05 02:03:25.125   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5499870
06-05 02:03:25.139   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5499885
06-05 02:03:25.176   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5499922
06-05 02:03:25.225   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5499971
06-05 02:03:25.280   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5500033
06-05 02:03:25.325   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5500078
06-05 02:03:25.383   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5500134
06-05 02:03:25.426   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5500178
06-05 02:03:25.483   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5500234
06-05 02:03:25.525   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 74, time: 5500278
06-05 02:03:25.619   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time set: percent: 88, time: 6513821
06-05 02:03:31.271   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 87, time: 6513821
06-05 02:03:31.280   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 170
06-05 02:03:32.117   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 1002
06-05 02:03:33.121   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 2005
06-05 02:03:34.132   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     time get: percent: 0, time: 3029
06-05 02:03:34.481   16424-16424   A0ff09/MINFY_LOGGER             com.rdminfo.minfy     D     onStatusChange: released

更多关于HarmonyOS 鸿蒙Next中AVPlayer播放HLS流媒体视频时,设置seek后实际播放位置和seek位置有很大偏差的实战教程也可以访问 https://www.itying.com/category-93-b0.html

8 回复

请问你这个流媒体是哪种形式?直播、点播?官方文档示例中提到直播是不支持seek的,另外还是需要这边提供下完整一些的demo。

更多关于HarmonyOS 鸿蒙Next中AVPlayer播放HLS流媒体视频时,设置seek后实际播放位置和seek位置有很大偏差的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


您好,我是搭建了一个开源的影视平台,该平台提供的api可将视频转码后以hls流媒体形式返回。

demo我建好了:https://gitee.com/Minfo/hls-player_-demo

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:BV1S4411E7LY/?p=17

我用你上面的url测试是正常的。有问题的这个视频流是服务器转过来的,想问下怎么操作的?

你那边是正常的?进入页面点击播放,播放后拖动进度条,然后播放是正常的,但是进度条会异常,也就是time_update事件输出的time会异常,我能看下你那边输出的time的set,get日志吗?

添加了seekDone监听输出time,日志如下:seek_done和第一次get结束,time是正确的,而后又是0了

在HarmonyOS鸿蒙Next中,AVPlayer播放HLS流媒体时出现seek偏差,主要原因是HLS流媒体的时间戳不连续和关键帧间隔问题。HLS协议以TS片段为单位分割视频,AVPlayer只能定位到最近的关键帧位置。开发者可使用以下API优化:1)通过AVPlayer的currentPosition获取实际播放位置;2)使用seekToMode参数选择PRECISE模式(若支持);3)检查HLS切片时长是否过大,建议2-10秒。偏差程度取决于HLS分片策略和关键帧密度。

这个问题确实与HLS流媒体的特性有关。在HarmonyOS AVPlayer中处理HLS流媒体seek操作时,需要注意以下几点:

  1. HLS流媒体seek精度问题:
  • HLS是基于分片的流媒体协议,seek操作会定位到最近的关键帧(I帧)
  • 低码率视频通常关键帧间隔较大,导致seek后实际位置偏差明显
  • 高码率视频关键帧间隔较小,seek精度会有所改善
  1. 建议的解决方案:
  • 检查服务器端HLS分片设置,确保关键帧间隔合理(建议2-4秒)
  • 在AVPlayer.seek()时使用SEEK_PREVIOUS_SYNC模式而非SEEK_CLOSEST
  • 增加缓冲时间,给播放器足够时间定位准确位置
  1. 代码优化建议:
  • 在seek后添加缓冲状态检测,等待PLAYING状态再更新UI
  • 增加seek完成回调处理,避免立即查询播放位置
  1. 流媒体服务器要求:
  • 确保m3u8索引文件包含准确的EXT-X-TARGETDURATION
  • 视频分片时长建议2-10秒,不宜过长
  • 关键帧间隔应与分片时长对齐

这个问题主要是HLS协议特性导致的,通过优化服务器端编码参数和客户端处理逻辑可以改善体验。

回到顶部