You need to enable JavaScript to run this app.
文档中心
视频点播

视频点播

复制全文
下载 pdf
进阶功能
短视频场景预渲染
复制全文
下载 pdf
短视频场景预渲染

本文为您介绍如何使用 HarmonyOS NEXT 播放器 SDK 实现短视频场景预渲染。

注意

本文适用于播放器 SDK 3.1.2-tob 及之后的版本。若您使用更早版本,请见HarmonyOS NEXT 播放器 SDK 使用文档(历史版本)。


Feed 流页面

@Entry
@ComponentV2
export struct ShortVideoFeed {
  // 1. Feed 流数据
  private data: FeedDataSource = new FeedDataSource();
  // 2. 记录当前显示页面的 index
  @Local currentIndex: number = 0
  // 3. 记录已出首帧页面的 index
  @Local renderStartIndex: number = -1

  aboutToAppear(): void {
  }

  build() {
    // 4. 使用 Swiper 实现短视频 Feed 流
    // Swiper 官网使用说明 https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/ts-container-swiper-V5
    Swiper() {
      LazyForEach(this.data, (dataSource: DataSource, index: number) => {
        ShortVideoView({
          dataSource: dataSource,
          index: index,
          currentIndex: this.currentIndex,
          renderStartIndex:this.renderStartIndex,
          onRenderStartIndexChange: (val: number) => {
              // 5. 页面出首帧后更新
              this.renderStartIndex = val;
          }
        })
          .width('100%')
          .height("100%")
      }, (dataSource: DataSource) => dataSource.getVid())
    }
    .vertical(true)
    .loop(false)
    // 6. 设置预加载子组件个数,以当前页面为基准,加载当前显示页面的前后个数,根据业务需求设置
    .cachedCount(1)
    .displayCount(1)
    .width('100%')
    .height('100%')
    .indicator(false)
    .onChange((index) => {
      // 7. 页面上下滑动结束,触发此事件,更新 currentIndex。
      this.currentIndex = index
    })
  }
}

Item 播放页面

@ComponentV2
export struct ShortVideoView {
  // 1. 当前页面在 feed 数组里的 index
  @Param @Require index: number
  @Param @Require dataSource: DataSource
  // 2. 记录当前显示页面的 index
  @Param currentIndex: number = 0
  // 3. 记录已出首帧页面的 index
  @Param renderStartIndex: number = -1;
  // 4. 页面出首帧后回调
  @Event onRenderStartIndexChange: (val: number) => void;

  private player?: VePlayer;

  aboutToAppear() {
    this.player = new VePlayer(this.dataSource)
    this.subscribeObserver()
    if (this.index == 0 && this.currentIndex == 0) {
      // 5. 进入 Feed 流页面的第一个视频,直接开始播放
      this.player.play()
    }
  }

  subscribeObserver() {
      this.playEventObserver = this.player?.subscribeObserver('')
          .onRenderFirstFrame((vid) => {
              this.onRenderStartIndexChange(this.currentIndex)
          })
  }

  // 6. Feed 流页面滑动,页面切换完成,currentIndex 更新,执行 onIndexChange
  @Monitor("currentIndex")
  onIndexChange() {
    if (this.index === this.currentIndex) {
      // 此 View 是要显示的页面,开始播放
      this.player?.play();
    } else {
       // 此 View 不是要显示的页面,停止播放
      this.player?.stop()
    }
  }

  @Monitor("renderStartIndex")
  onRenderStartIndex() {
    // 7. 收到某播放器出首帧消息,是当前显示页面出了首帧,预渲染下一个视频,onIndexChange 页面切换完成时再播放
    if (this.currentIndex == this.renderStartIndex
      && this.index == this.currentIndex + 1) {
      this.player?.prepare()
    }
  }

  aboutToDisappear() {
    // 8. 画面退出,释放播放器
    this.player?.release()
  }

  build() {
      Stack() {
          TTAVPlayerView2({
            scaleType: TTAVScaleType.AspectFit,
            onLoad: (window) => {
              this.player?.bindWindow(window)
            }
          })
      }
    }
}
最近更新时间:2026.10.14 17:48:18
这个页面对您有帮助吗?
有用
有用
无用
无用