环球军事
avplayer怎么用(【HarmonyOS-媒体技术-AVPlayer】手把手教你用 AVPlayer 实现流媒体播放(ArkTS 详解) – 人人都是产品经理)

一句话总结

本文带你掌握从创建到释放的全链路操作,覆盖 HLS/DASH/FLV 等主流协议,支持码率切换、轨道选择、自动重试、缓冲监控等高阶能力。

在 module.json5 中添加:

“reqPermissions”: [

“name”: “ohos.permission.INTERNET”

]

否则访问任何网络资源都会失败!

import { media } from ‘@kit.MediaKit’;

二、标准播放流程(必看!)

async avSetupStreamingMediaVideo {

// 创建avPlayer实例对象。

// 创建状态机变化回调函数。

this.percent = avPlayer.width / avPlayer.height; // 计算并保存视频的宽高比

this.durationTime = this.getDurationTime; // 获取视频总时长

if (!this.isSwiping) {

this.currentTime = this.getCurrentTime;

}, SET_INTERVAL);

});

this.avPlayer.url = “http://media.iyuns.top:1000/http/720p_1m.mp4”;

avPlay: void {

try {

} catch (e) {

三、核心监听事件详解(缺一不可)

【HarmonyOS-媒体技术-AVPlayer】手把手教你用 AVPlayer 实现流媒体播放(ArkTS 详解) – 人人都是产品经理nerror="javascript:errorimg.call(this);">

// 状态机变化回调函数。

if (this.avPlayer == null) {

return;

// 时间上报监听函数。

this.currentTime = time;

四、主流协议支持一览表

【HarmonyOS-媒体技术-AVPlayer】手把手教你用 AVPlayer 实现流媒体播放(ArkTS 详解) – 人人都是产品经理nerror="javascript:errorimg.call(this);">

五、高阶功能实战(让你的播放器“聪明”起来)

1. 流媒体缓冲状态

import { media } from ‘@kit.MediaKit’;

private avPlayer: media.AVPlayer | null = null;

this.avPlayer.on(‘bufferingUpdate’, (infoType : media.BufferingInfoType, value : number) => {

})

2. HLS 多码率切换(自定义清晰度)

通过on(‘availableBitrates’)监听当前HLS协议流可用的码率。如果监听的码率列表长度为0,则不支持设置指定码率。

this.avPlayer.on(‘availableBitrates’, (bitrates: Array<number>) => {

})

// 监听码率设置是否生效。

console.info(‘bitrateDone called, and bitrate value is: ‘ + bitrate);

// 设置播放码率。

this.avPlayer.setBitrate(this.bitrate);

3. DASH 起播策略设置(首帧更快加载)

// 自定义起播分辨率:1920×1080 import { media } from ‘@kit.MediaKit’;

let playbackStrategy : media.PlaybackStrategy = {preferredWidth: 1920, preferredHeight: 1080};

弱网环境下优先加载低码率,提升首帧速度。

DASH流媒体资源包含多路不同分辨率、码率、采样率、编码格式的音频、视频及字幕资源。默认情况下,AVPlayer会依据网络状况自动切换不同码率的视频轨道。开发者可根据需求选择指定的音视频轨道播放,此时自适应码率切换策略将失效。

this.avPlayer.on(‘trackChange’, (index: number, isSelect: boolean) => {

调用getTrackDescription获取所有音视频轨道列表。开发者可根据实际需求,基于MediaDescription各字段信息,确定目标轨道索引。

import { media } from ‘@kit.MediaKit’;

public videoTrackIndex: number = 0;

if (arrList != null) {

let propertyIndex: Object = arrList[i][media.MediaDescriptionKey.MD_KEY_TRACK_INDEX];

let propertyWidth: Object = arrList[i][media.MediaDescriptionKey.MD_KEY_WIDTH];

if (propertyType == media.MediaType.MEDIA_TYPE_VID && propertyWidth == 1920 && propertyHeight == 1080) {

} else {

在音视频播放过程中调用selectTrack选择对应的音视频轨道,或者调用deselectTrack取消选择的音视频轨道。

this.avPlayer.selectTrack(this.videoTrackIndex);

// this.avPlayer.deselectTrack(this.videoTrackIndex);

六、常见坑位 & 解决方案(避雷手册)

【HarmonyOS-媒体技术-AVPlayer】手把手教你用 AVPlayer 实现流媒体播放(ArkTS 详解) – 人人都是产品经理nerror="javascript:errorimg.call(this);">

import { media } from ‘@kit.MediaKit’;

import { display } from ‘@kit.ArkUI’;

const TIME_TWO = 1000; // 1秒的毫秒数。

const SPEED_ZERO: number = 0; // 对应1.00x。

const SPEED_TWO: number = 2; // 对应1.75x。

const PROPORTION: number = 0.99;

eventId: 1,

};

eventId: 2,

eventId: 3,

@Component

private avPlayer: media.AVPlayer | null = null;

public videoTrackIndex: number = 0;

@State durationTime: number = 0;

@State percent: number = 0;

@State tag: string = ‘StreamingMedia’;

@State speedSelect: number = -1;

@State windowWidth: number = 300;

@State surfaceW: number | null = null;

@State isPaused: boolean = true;

getDurationTime: number {

return this.durationTime;

getCurrentTime: number {

return this.currentTime;

timeConvert(time: number): string {

let second: string = ((time % TIME_ONE) / TIME_TWO).toFixed(0);

second = second.padStart(2, ‘0’);

return `${min}:${second}`;

async msleepAsync(ms: number): Promise<boolean> {

return new Promise((resolve, reject) => {

resolve(true)

this.percent = avPlayer.width / avPlayer.height;

this.durationTime = this.getDurationTime;

// 情况二:HLS视频播放。 // this.avPlayer.url = “http://media.iyuns.top:1000/720-270-480.m3u8”;

// 情况四:通过setMediaSource设置自定义头域及播放优选参数实现初始播放参数设置,以流媒体HTTP点播为例。

let mediaSource : media.MediaSource = media.createMediaSourceWithUrl(“http://media.iyuns.top:1000/http/720p_1m.mp4”, {“”:””});

let playbackStrategy : media.PlaybackStrategy = {preferredBufferDuration: 20};

// 为avPlayer设置媒体来源和播放策略。

* */

// 情况五:HLS切码率。

this.avPlayer.url = “https://upftimae.dailyworkout.cn/videos/course/c800f81a209b5ee7891f1128ed301db/4/master.m3u8”;

this.bitrate = bitrates[0]; // 保存需要切换的码率。

// 情况六:DASH切换音视频轨道。

this.avPlayer.url = “http://poster-inland.hwcloudtest.cn/AiMaxEngine/ProductionEnvVideo/DASH_SDR_MultiAudio_MultiSubtitle_yinHeHuWeiDui3/DASH_SDR_MultiAudio_MultiSubtitle_yinHeHuWeiDui3.mpd”;

//

// HLS切换码率。

this.avPlayer.setBitrate(bitrate);

console.error(`${this.tag}: setBitrate failed, error message is = ${JSON.stringify(error.message)}`);

changeTrack(track: number) {

this.avPlayer.selectTrack(track);

console.error(`${this.tag}: selectTrack failed, error message is = ${JSON.stringify(error.message)}`);

this.avPlayer.deselectTrack(track);

console.error(`${this.tag}: deselectTrack failed, error message is = ${JSON.stringify(error.message)}`);

this.avPlayer.pause;

} catch (e) {

async avSeek(seekTime: number, mode: SliderChangeMode): Promise<void> {

this.avPlayer.seek(seekTime, 2);

} catch (e) {

avSetSpeed(speed: number): void {

console.info(`${this.tag}: avSetSpeed enum ${speed}`);

console.error(`${this.tag}: avSetSpeed == ${JSON.stringify(e)}`);

async setAVPlayerCallback(callback: (avPlayer: media.AVPlayer) => void, vType?: number): Promise<void> {

if (this.avPlayer == null) {

this.avPlayer.on(‘seekDone’, (seekDoneTime) => {

console.info(`${this.tag}: setAVPlayerCallback AVPlayer seek succeeded, seek time is ${seekDoneTime}`);

this.avPlayer.on(‘speedDone’, (speed) => {

console.info(`${this.tag}: setAVPlayerCallback AVPlayer speedDone, speed is ${speed}`);

// error回调监听函数,当avPlayer在操作过程中出现错误时调用reset接口触发重置流程。

console.error(`${this.tag}: setAVPlayerCallback Invoke avPlayer failed ${JSON.stringify(err)}`);

console.error(`${this.tag}: avPlayer has not init on error`);

switch (state) {

console.info(`${this.tag}: setAVPlayerCallback AVPlayer state idle called.`);

case ‘initialized’: // avplayer 设置播放源后触发该状态上报。

if (this.surfaceId) {

console.info(`${this.tag}: setAVPlayerCallback this.avPlayer.surfaceId = ${this.avPlayer.surfaceId}`);

case ‘prepared’: // prepare调用成功后上报该状态机。

this.avPlayer.on(‘bufferingUpdate’, (infoType: media.BufferingInfoType, value: number) => {

console.info(`${this.tag}: bufferingUpdate called, infoType value: ${infoType}, value:${value}}`);

this.durationTime = this.avPlayer.duration;

this.currentTime = this.avPlayer.currentTime;

console.info(`${this.tag}:

if (this.speedSelect != -1) {

case SPEED_ZERO:

this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_00_X);

case SPEED_ONE:

this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_25_X);

case SPEED_TWO:

this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_1_75_X);

case SPEED_THREE:

this.avSetSpeed(media.PlaybackSpeed.SPEED_FORWARD_2_00_X);

callback(this.avPlayer);

case ‘playing’: // play成功调用后触发该状态机上报。

console.info(`${this.tag}: setAVPlayerCallback AVPlayer state playing called.`);

clearInterval(this.intervalID)

this.intervalID = setInterval( => { // 更新当前时间。

AppStorage.setOrCreate(‘currentTime’, this.currentTime);

let eventDataTrue: emitter.EventData = {

‘flag’: true

emitter.emit(innerEventTrue, eventDataTrue);

case ‘completed’: // 播放结束后触发该状态机上报。

console.info(`${this.tag}: setAVPlayerCallback AVPlayer state completed called.`);

let eventDataFalse: emitter.EventData = {

‘flag’: false

let innerEvent: emitter.InnerEvent = {

this.avPlayer.off(‘bufferingUpdate’)

AppStorage.setOrCreate(‘currentTime’, this.durationTime);

case ‘released’:

console.info(`${this.tag}: setAVPlayerCallback released called.`);

case ‘stopped’:

console.info(`${this.tag}: setAVPlayerCallback AVPlayer state stopped called.`);

case ‘error’:

console.error(`${this.tag}: setAVPlayerCallback AVPlayer state error called.`);

case ‘paused’:

console.info(`${this.tag}: setAVPlayerCallback AVPlayer state paused called.`);

default:

console.info(`${this.tag}: setAVPlayerCallback AVPlayer state unknown called.`);

this.windowWidth = display.getDefaultDisplaySync.width;

if (this.percent >= 1) { // 横向视频。

this.surfaceH = Math.round(this.surfaceW / this.percent);

this.surfaceH = Math.round(this.windowHeight * PROPORTION);

this.surfaceW = Math.round(this.surfaceH * this.percent);

this.isPaused = true;

this.context = this.getUIContext.getHostContext;

aboutToDisappear {

console.info(`${this.tag}: avPlayer has not init aboutToDisappear`);

if (err == null) {

} else {

emitter.off(innerEventFalse.eventId);

onPageHide {

this.isPaused = false;

onPageShow {

if (res.data) {

this.XComponentFlag = res.data.flag;

emitter.on(innerEventWH, (res: emitter.EventData) => {

this.windowWidth = res.data.width;

setVideoWH: void {

CoverXComponent {

// …

build {

八、立即行动,开启你的音视频播放开发之旅!

加入 HarmonyOS 社区,共创未来!

加入开发者社区,获取最新资讯和技术支持

让 AVPlayer 成为你开发路上的得力助手,开启你的音视频播放新纪元!


顶一下()     踩一下()

热门推荐

发表评论
0评