本文为您介绍如何使用 HarmonyOS NEXT 播放器 SDK 实现短视频场景预渲染。
注意
本文适用于播放器 SDK 3.1.2-tob 及之后的版本。若您使用更早版本,请见HarmonyOS NEXT 播放器 SDK 使用文档(历史版本)。
@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 }) } }
@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) } }) } } }