本文为您介绍如何实现 HarmonyOS NEXT 播放器 SDK 的进阶功能。
预加载是指在开始播放之前提前下载即将播放视频的头部数据,实现快速起播,提升播放体验。预加载实现成本低,效果显著,适用于各种播放场景。更多介绍,请见预加载规则说明。
注意
该功能仅高级版支持。请确保您已购买高级版的 License,详见播放器 License。
添加预加载任务:预加载与播放使用相同的数据源结构。为保证播放能命中预加载缓存,需确保构造预加载数据源与构造播放数据源时使用的 vid
、url
和 cacheKey
一致。示例代码如下:
// 构造播放源 let videoInfo = new VideoInfo(); videoInfo.urls = [url] videoInfo.fileHash = fileHash let dataSource = new VideoModel(); dataSource.videoInfos = [videoInfo]; dataSource.vid = vid; let preloadSize = 800 * 1024; // 预加载大小 800K let startPreloadOffset = 0; // 预加载的起始位置 // 构造预加载实例 let preloadModel = new PreloadVideoModel(dataSource, startPreloadOffset, preloadSize, (type: PreloadTaskEventType, info: string, extraInfo: string) => { switch (type) { case PreloadTaskEventType.Success: // 预加载成功 case PreloadTaskEventType.Failed: // 预加载失败 case PreloadTaskEventType.Cancel: // 预加载取消 break; } }) // 开始预加载 preloadModel.create();
取消预加载任务:取消未执行和正在下载的任务,已完成的任务不受影响。
// 取消预加载任务 preloadModel.cancel();
添加预加载任务:预加载与播放使用相同的播放源结构。为保证播放能命中预加载缓存,需确保预加载与播放构造的播放源 vid
、playAuthToken
和 resolution
一致。
let vid = "your vid"; // appServer 下发 let playAuthToken = "your video id's play auth token"; // appServer 下发 let source = new VidSource(vid, playAuthToken) // 设置分辨率,如不设置起播分辨率,则使用清晰度列表里的第一个起播 // let source = new VidSource(vid, playAuthToken, Resolution.resolution_360p) let preloadSize = 800 * 1024; // 预加载大小 800K let startPreloadOffset = 0; // 预加载的起始位置 let preloadVid = new PreloadVid(source, startPreloadOffset, preloadSize, (type: PreloadTaskEventType, info: string, extraInfo: string) => { switch (type) { case PreloadTaskEventType.Success: // 预加载成功 case PreloadTaskEventType.Failed: // 预加载失败 case PreloadTaskEventType.Cancel: // 预加载取消 break; } }) preloadVid.create();
取消预加载任务:取消未执行和正在下载的任务,已完成的任务不受影响。
// 取消预加载任务 preloadVid.cancel();
视频点播私有加密方案采用火山引擎自研加密算法,安全级别高,能够便捷、高效、安全地保护您的音视频版权。更多介绍,请见火山引擎私有加密方案。播放器 SDK 支持通过 DirectUrl 模式播放私有加密视频。应用服务端从视频点播服务获取用于解密的密钥 playAuth
并下发给播放器 SDK,即可播放火山引擎私有加密视频。
// 视频源与 vid 必须一一对应 let vid = "your vid"; // 视频 url let url = "http://www.example.com/h264.mp4"; // 播放源唯一标识,与视频源一一对应,如 url 的 MD5 let fileHash = getMd5(url); // 使用服务端签发的临时播放 Token let playAuth = "l7wZ9Em+A/xxxxxxx"; // 构造播放源 let videoInfo = new VideoInfo(); videoInfo.urls = [url] videoInfo.fileHash = fileHash videoInfo.decryptionKey = playAuth let dataSource = new VideoModel(); dataSource.videoInfos = [videoInfo]; dataSource.vid = vid; // 播放 this.simPlayer.play(dataSource, PlayOptions.create() .setEnableMdl(true));
@Entry @Component export struct SmallVideoFeed { // 2. Feed 流数据 private data: FeedDataSource = new FeedDataSource(); // 3. 记录当前显示页面的 index @State currentIndex: number = 0 aboutToAppear(): void { } build() { // 1. 使用 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) => { TTPlayerItemView({ dataSource: dataSource, index: index, currentIndex: this.currentIndex }) .width('100%') .height("100%") }, (dataSource: DataSource) => dataSource.getVid()) } .vertical(true) .loop(false) // 4. cachedCount 可根据业务需求设置 .cachedCount(1) .displayCount(1) .width('100%') .height('100%') .indicator(false) .onChange((index) => { // 5. 页面上下滑动结束,触发此事件,更新 currentIndex。 this.currentIndex = index }) } }
@Component export struct TTPlayerItemView { // 1. 当前 View 在 feed 数组里的 index index: number = 0 // 2. Feed 流页面滑动,currentIndex 更新,执行 onIndexChange @Watch('onIndexChange') @Prop currentIndex: number = 0 @State dataSource: DataSource = new DataSource(); private simPlayer?: ISimPlayer; aboutToAppear() { this.simPlayer = SimKitService.instance().createSimPlayer(); if (this.index == 0 && this.currentIndex == 0) { // 3. 进入 Feed 流页面的第一个视频,直接开始播放 this.simPlayer?.play(this.dataSource, PlayOptions.create()); } else { // 4. 滑动到其他页面先进行预渲染,onIndexChange 页面切换完成时再播放 this.simPlayer?.preRender(this.dataSource, PlayOptions.create()); } } onIndexChange() { // 5. 页面切换完成 if (this.index === this.currentIndex) { // 此 View 是要显示的页面,开始播放 this.simPlayer?.play(this.dataSource, PlayOptions.create()); } else { // 此 View 不是要显示的页面,停止播放 this.simPlayer?.stop(this.dataSource?.getVid()) } } aboutToDisappear() { // 6. 画面退出,释放播放器 this.simPlayer?.release(this.dataSource?.getVid()) } build() { Stack() { SimVideoView({ playRequest: this.dataSource, simPlayer: this.simPlayer, }) } } }