本文为您介绍如何实现 HarmonyOS NEXT 播放器 SDK 的基础功能。
/** * 订阅播放回调,每次调用 SDK 内部会创建新的 IPlayEventObserver 并返回, * 同一次播放可订阅多次,使用完需要解除订阅。 * @param dataSource, 设置的播放源 * @param observerName, Observer命名标识,标记所在业务场景,方便后续异常定位 * @returns */ subscribeObserverByPlayRequest(dataSource: DataSource, observerName: string): IPlayEventObserver /** * 取消订阅,确保与订阅方法逻辑对称。 * @param vid,对应播放源的 vid * @param playEventObserver,需要解除订阅的 IPlayEventObserver */ unsubscribeObserver(vid:string, playEventObserver: IPlayEventObserver)
export interface IPlayEventObserver { /** * 首帧回调 */ onRenderFirstFrame(callback: Callback<string | undefined>): IPlayEventObserver /** * prepare 完成回调 */ onPrepared(callback: Callback<string | undefined>): IPlayEventObserver /** * 开始播放回调 */ onPlaying(callback: Callback<string | undefined>): IPlayEventObserver /** * 调用暂停后回调 */ onPaused(callback: Callback<string | undefined>): IPlayEventObserver /** * 调用 stop 后回调 */ onStopped(callback: Callback<string | undefined>): IPlayEventObserver /** * 播放至结尾回调,不论用户是否开启loop,播放至结尾均触发回调 */ onPlayEnd(callback: Callback<string | undefined>): IPlayEventObserver /** * 出现卡顿回调 * @param start 为 true 开始卡顿;start 为 false 卡顿结束。 */ onBuffering(callback: (sourceID: string | undefined, start: boolean) => void): IPlayEventObserver /** * 播放器已经缓存的可播放进度 * @param percent 百分比 */ onBufferingPercent(callback: (sourceID: string | undefined, percent: number) => void): IPlayEventObserver /** * 播放进度变化回调,默认间隔 1s 上报,因用户操作(seek)产生的时间变化会立刻上报 * @param currentDuration 当前播放进度,单位 ms */ onTimeChange(callback: (sourceID: string | undefined, currentDuration: number) => void): IPlayEventObserver /** * seek 完成回调 * @param seekDoneTime seek 到的位置,单位 ms。 * 精准位置需要通过 onTimeChange 获取,seek 回调的 time 仅代表完成用户某一次请求。 */ onSeekDone(callback: (sourceID: string | undefined, seekDoneTime: number) => void): IPlayEventObserver /** * 播放错误回调 * @param error 错误信息,error.code 为错误码 */ onError(callback: (sourceID: string | undefined, error: BusinessError) => void): IPlayEventObserver /** * 获取到 VideoModel 回调 * @param videoModel,播放使用的 VideoModel */ onFetchVideoModel(callback: (sourceID: string | undefined, videoModel: VideoModel) => void): IPlayEventObserver /** * 视频宽高变化回调,仅系统播放器回调 * @param width 视频宽 * @param height 视频高 */ onVideoSizeChange(callback: (sourceID: string | undefined, width: number, height: number) => void): IPlayEventObserver }
// 订阅回调 this.playEventObserver = this.simPlayer .subscribeObserverByPlayRequest(this.dataSource, 'FeedItemView') .onPrepared((sourceID) => { }) .onPaused((sourceID) => { }) .onPlaying((sourceID) => { }) .onBuffering((sourceID, start) => { }) .onTimeChange((sourceID, currentDuration) => { }) .onBufferingPercent((sourceID, percent) => { }) .onError((sourceID, error) => { }) // 结束播放时,取消订阅 this.simPlayer.unsubscribeObserver(this.dataSource.getVid(), this.playEventObserver)
// 暂停播放 this.simPlayer.pause(this.dataSource.getVid()) // 恢复播放 this.simPlayer.resume(this.dataSource.getVid())
// 演示 seek 到 1 秒的位置 this.simPlayer.seek(1000);
this.simPlayer.play(playRequest, PlayOptions.create() // 单位为毫秒,以下示例表示从 1 秒处起播 .setInitialStartTimeMs(1000);
// 默认值为 1。支持取值:0.5, 1, 1.5, 2, 2.5, 3 this.simPlayer.setSpeed(2)
// 循环播放默认关闭 this.simPlayer.play(playRequest, PlayOptions.create() .setLoop(true));
// 静音 this.simPlayer.setVolume(0); // 取消静音 this.simPlayer.setVolume(1);
// 单位为毫秒 let duration = this.simPlayer.getDuration()
this.simPlayer.play(dataSource, PlayOptions.create() .setEnableHardwareDecode(true));
在 Vid 模式下播放视频时,视频点播服务会根据配置下发一个或多个清晰度的播放地址。播放器触发 onFetchVideoModel
回调后,您可调用 getVideoList
方法获取包含所有清晰度信息的数组,基于该数组实现清晰度列表的展示和清晰度切换逻辑。
构造 Vid 播放源时,若指定起播分辨率,则采用该分辨率;否则,使用清晰度列表的首个分辨率。若指定分辨率不存在,则采用最接近的分辨率。
let dataSource = new VidSource(videoDetail.vid, videoDetail.playAuthToken, Resolution.resolution_360p) this.simPlayer.play(dataSource);
播放器触发 onFetchVideoModel
回调后,调用 getVideoList
方法获取包含所有清晰度信息的数组。
.onFetchVideoModel((sourceID, videoModel) => { let videoList = this.simPlayer.getVideoList(); for (let videoInfo of videoList) { // 清晰度字段,见下面清晰度枚举 console.info("definition is" + videoInfo.definition) } })
获取清晰度列表后,传入要切换清晰度在列表中的 index。
this.simPlayer.switchVideo(index);
Resolution 枚举如下表所示:
key | 视频清晰度 |
---|---|
resolution_360p | 360p |
resolution_480p | 480p |
resolution_540p | 540p |
resolution_720p | 720p |
resolution_1080p | 1080p |
resolution_2k | 2k |
resolution_4k | 4k |
当 License 过期或其他错误发生时,播放器会报错 -30001
,无法正常使用。此时建议切换至鸿蒙系统播放器进行播放。系统播放器效果较差,因此建议及时更新 License,避免过期。
this.playEventObserver = this.simPlayer.subscribeObserverByPlayRequest(this.dataSource, 'FeedItemView') .onError((sourceID, error) => { // license 校验失败 if (error.codec == TTPlayerErrorCode.LICENSE_FAIL) { } })
VodEnv.addLicenseFile(this.license) ..... // addLicenseFile 后,检查 license,如不可用设置使用系统播放器播放。 if (!VodEnv.isLicenseAvailable()) { VodEnv.setUseOwnPlayer(false) }
使用系统播放器时,视频拉伸变形铺满视图。您需根据视频宽高比自行调整 SimVideoView
宽高。
build() { Stack() { // 构造视图控件并传入播放器和播放源 SimVideoView({ playRequest: this.dataSource, simPlayer: this.simPlayer, }) .width(this.playerWidth + 'px') .height(this.playerHeight + 'px') } .width('100%') .height('100%') } this.playEventObserver = this.simPlayer.subscribeObserverByPlayRequest(this.dataSource, 'FeedItemView') .onVideoSizeChange((sourceID, width, height) => { // 获取屏幕宽高比 let displaySc = display.getDefaultDisplaySync().width / display.getDefaultDisplaySync().height // 获取视频宽高比 let videoSc = width / height; if (videoSc > displaySc) { // 视图宽填满屏幕,高等比例适配留黑边 this.playerWidth = display.getDefaultDisplaySync().width; this.playerHeight = this.playerWidth * height / width; } else { // 视图高填满屏幕,宽等比例适配留黑边 this.playerHeight = display.getDefaultDisplaySync().height; this.playerWidth = this.playerHeight * width / height; } })
VodEnv.addLicenseFile(this.license) ..... // addLicenseFile 后,检查 license,如不可用,使用自己封装的系统播放器。 if (!VodEnv.isLicenseAvailable()) { // 接入方自行封装鸿蒙系统播放器 }
详见以下鸿蒙官方文档: