HarmonyOS的AVPlayer提供了强大的多媒体播放能力,支持多种视频格式和网络协议。以下是利用AVPlayer开发视频播放功能的完整实现方案。
![图片[1]_HarmonyOS系统AVPlayer视频播放功能开发指南_知途无界](https://zhituwujie.com/wp-content/uploads/2025/04/d2b5ca33bd20250420104209.png)
一、基础环境配置
1. 添加权限
在config.json
中添加必要权限:
{"module": {"reqPermissions": [{"name": "ohos.permission.INTERNET" // 网络视频需要},{"name": "ohos.permission.READ_MEDIA" // 本地视频需要}]}}{ "module": { "reqPermissions": [ { "name": "ohos.permission.INTERNET" // 网络视频需要 }, { "name": "ohos.permission.READ_MEDIA" // 本地视频需要 } ] } }{ "module": { "reqPermissions": [ { "name": "ohos.permission.INTERNET" // 网络视频需要 }, { "name": "ohos.permission.READ_MEDIA" // 本地视频需要 } ] } }
2. 导入AVPlayer模块
import media from '@ohos.multimedia.media';import fs from '@ohos.file.fs';import media from '@ohos.multimedia.media'; import fs from '@ohos.file.fs';import media from '@ohos.multimedia.media'; import fs from '@ohos.file.fs';
二、创建AVPlayer实例
1. 初始化AVPlayer
let avPlayer: media.AVPlayer;let surfaceId: string; // 用于视频渲染的surface IDasync function initAVPlayer() {// 创建AVPlayer实例avPlayer = await media.createAVPlayer();// 设置监听器avPlayer.on('stateChange', (state: string) => {console.log(`Current state: ${state}`);// 可处理的状态:idle, initialized, prepared, playing, paused, completed, stopped, released, error});avPlayer.on('error', (error: BusinessError) => {console.error(`Error occurred: ${error.code}, ${error.message}`);});}let avPlayer: media.AVPlayer; let surfaceId: string; // 用于视频渲染的surface ID async function initAVPlayer() { // 创建AVPlayer实例 avPlayer = await media.createAVPlayer(); // 设置监听器 avPlayer.on('stateChange', (state: string) => { console.log(`Current state: ${state}`); // 可处理的状态:idle, initialized, prepared, playing, paused, completed, stopped, released, error }); avPlayer.on('error', (error: BusinessError) => { console.error(`Error occurred: ${error.code}, ${error.message}`); }); }let avPlayer: media.AVPlayer; let surfaceId: string; // 用于视频渲染的surface ID async function initAVPlayer() { // 创建AVPlayer实例 avPlayer = await media.createAVPlayer(); // 设置监听器 avPlayer.on('stateChange', (state: string) => { console.log(`Current state: ${state}`); // 可处理的状态:idle, initialized, prepared, playing, paused, completed, stopped, released, error }); avPlayer.on('error', (error: BusinessError) => { console.error(`Error occurred: ${error.code}, ${error.message}`); }); }
三、视频播放实现
1. 播放网络视频
async function playNetworkVideo(url: string) {// 设置播放源await avPlayer.reset();await avPlayer.setSource({uri: url // 支持http/https/rtmp等协议});// 准备播放await avPlayer.prepare();// 获取surface并绑定到UI组件surfaceId = await avPlayer.getSurfaceId();// 将surfaceId传递给XComponent组件// 开始播放await avPlayer.play();}async function playNetworkVideo(url: string) { // 设置播放源 await avPlayer.reset(); await avPlayer.setSource({ uri: url // 支持http/https/rtmp等协议 }); // 准备播放 await avPlayer.prepare(); // 获取surface并绑定到UI组件 surfaceId = await avPlayer.getSurfaceId(); // 将surfaceId传递给XComponent组件 // 开始播放 await avPlayer.play(); }async function playNetworkVideo(url: string) { // 设置播放源 await avPlayer.reset(); await avPlayer.setSource({ uri: url // 支持http/https/rtmp等协议 }); // 准备播放 await avPlayer.prepare(); // 获取surface并绑定到UI组件 surfaceId = await avPlayer.getSurfaceId(); // 将surfaceId传递给XComponent组件 // 开始播放 await avPlayer.play(); }
2. 播放本地视频
async function playLocalVideo(filePath: string) {// 检查文件是否存在try {await fs.access(filePath);} catch (error) {console.error('File not found');return;}// 设置播放源await avPlayer.reset();await avPlayer.setSource({fdSrc: {fd: await fs.open(filePath).fd,offset: 0,length: (await fs.stat(filePath)).size}});await avPlayer.prepare();surfaceId = await avPlayer.getSurfaceId();await avPlayer.play();}async function playLocalVideo(filePath: string) { // 检查文件是否存在 try { await fs.access(filePath); } catch (error) { console.error('File not found'); return; } // 设置播放源 await avPlayer.reset(); await avPlayer.setSource({ fdSrc: { fd: await fs.open(filePath).fd, offset: 0, length: (await fs.stat(filePath)).size } }); await avPlayer.prepare(); surfaceId = await avPlayer.getSurfaceId(); await avPlayer.play(); }async function playLocalVideo(filePath: string) { // 检查文件是否存在 try { await fs.access(filePath); } catch (error) { console.error('File not found'); return; } // 设置播放源 await avPlayer.reset(); await avPlayer.setSource({ fdSrc: { fd: await fs.open(filePath).fd, offset: 0, length: (await fs.stat(filePath)).size } }); await avPlayer.prepare(); surfaceId = await avPlayer.getSurfaceId(); await avPlayer.play(); }
四、播放控制功能
1. 基础控制方法
// 暂停播放function pause() {avPlayer.pause();}// 继续播放function resume() {avPlayer.play();}// 停止播放function stop() {avPlayer.stop();}// 跳转到指定位置(毫秒)function seekTo(position: number) {avPlayer.seek(position, media.SeekMode.SEEK_NEXT_SYNC);}// 调整播放速度function setSpeed(speed: media.PlaybackSpeed) {avPlayer.setSpeed(speed); // 如PlaybackSpeed.SPEED_FORWARD_1_00_X}// 暂停播放 function pause() { avPlayer.pause(); } // 继续播放 function resume() { avPlayer.play(); } // 停止播放 function stop() { avPlayer.stop(); } // 跳转到指定位置(毫秒) function seekTo(position: number) { avPlayer.seek(position, media.SeekMode.SEEK_NEXT_SYNC); } // 调整播放速度 function setSpeed(speed: media.PlaybackSpeed) { avPlayer.setSpeed(speed); // 如PlaybackSpeed.SPEED_FORWARD_1_00_X }// 暂停播放 function pause() { avPlayer.pause(); } // 继续播放 function resume() { avPlayer.play(); } // 停止播放 function stop() { avPlayer.stop(); } // 跳转到指定位置(毫秒) function seekTo(position: number) { avPlayer.seek(position, media.SeekMode.SEEK_NEXT_SYNC); } // 调整播放速度 function setSpeed(speed: media.PlaybackSpeed) { avPlayer.setSpeed(speed); // 如PlaybackSpeed.SPEED_FORWARD_1_00_X }
2. 获取播放信息
async function getPlayerInfo() {const currentPos = await avPlayer.getCurrentTime(); // 当前播放位置(ms)const duration = await avPlayer.getDuration(); // 总时长(ms)const videoWidth = avPlayer.getVideoWidth(); // 视频宽度const videoHeight = avPlayer.getVideoHeight(); // 视频高度const isPlaying = avPlayer.state === 'playing'; // 是否正在播放return { currentPos, duration, videoWidth, videoHeight, isPlaying };}async function getPlayerInfo() { const currentPos = await avPlayer.getCurrentTime(); // 当前播放位置(ms) const duration = await avPlayer.getDuration(); // 总时长(ms) const videoWidth = avPlayer.getVideoWidth(); // 视频宽度 const videoHeight = avPlayer.getVideoHeight(); // 视频高度 const isPlaying = avPlayer.state === 'playing'; // 是否正在播放 return { currentPos, duration, videoWidth, videoHeight, isPlaying }; }async function getPlayerInfo() { const currentPos = await avPlayer.getCurrentTime(); // 当前播放位置(ms) const duration = await avPlayer.getDuration(); // 总时长(ms) const videoWidth = avPlayer.getVideoWidth(); // 视频宽度 const videoHeight = avPlayer.getVideoHeight(); // 视频高度 const isPlaying = avPlayer.state === 'playing'; // 是否正在播放 return { currentPos, duration, videoWidth, videoHeight, isPlaying }; }
五、UI界面集成
1. 布局文件示例
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:width="match_parent"ohos:height="match_parent"ohos:orientation="vertical"><!-- 视频显示区域 --><XComponentohos:id="$+id:videoComponent"ohos:width="match_parent"ohos:height="300vp"ohos:type="surface"/><!-- 控制按钮区域 --><DirectionalLayoutohos:width="match_parent"ohos:height="wrap_content"ohos:orientation="horizontal"ohos:margin_top="10vp"><Buttonohos:id="$+id:playBtn"ohos:width="100vp"ohos:height="50vp"ohos:text="播放"/><Buttonohos:id="$+id:pauseBtn"ohos:width="100vp"ohos:height="50vp"ohos:text="暂停"/><Sliderohos:id="$+id:progressSlider"ohos:width="200vp"ohos:height="50vp"/></DirectionalLayout></DirectionalLayout><DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:width="match_parent" ohos:height="match_parent" ohos:orientation="vertical"> <!-- 视频显示区域 --> <XComponent ohos:id="$+id:videoComponent" ohos:width="match_parent" ohos:height="300vp" ohos:type="surface"/> <!-- 控制按钮区域 --> <DirectionalLayout ohos:width="match_parent" ohos:height="wrap_content" ohos:orientation="horizontal" ohos:margin_top="10vp"> <Button ohos:id="$+id:playBtn" ohos:width="100vp" ohos:height="50vp" ohos:text="播放"/> <Button ohos:id="$+id:pauseBtn" ohos:width="100vp" ohos:height="50vp" ohos:text="暂停"/> <Slider ohos:id="$+id:progressSlider" ohos:width="200vp" ohos:height="50vp"/> </DirectionalLayout> </DirectionalLayout><DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos" ohos:width="match_parent" ohos:height="match_parent" ohos:orientation="vertical"> <!-- 视频显示区域 --> <XComponent ohos:id="$+id:videoComponent" ohos:width="match_parent" ohos:height="300vp" ohos:type="surface"/> <!-- 控制按钮区域 --> <DirectionalLayout ohos:width="match_parent" ohos:height="wrap_content" ohos:orientation="horizontal" ohos:margin_top="10vp"> <Button ohos:id="$+id:playBtn" ohos:width="100vp" ohos:height="50vp" ohos:text="播放"/> <Button ohos:id="$+id:pauseBtn" ohos:width="100vp" ohos:height="50vp" ohos:text="暂停"/> <Slider ohos:id="$+id:progressSlider" ohos:width="200vp" ohos:height="50vp"/> </DirectionalLayout> </DirectionalLayout>
2. 界面逻辑实现
import { XComponent } from '@ohos.arkui.xcomponent';@Entry@Componentstruct VideoPlayerPage {private avPlayer: media.AVPlayer = null;build() {Column() {// 视频显示区域XComponent({id: 'videoComponent',type: 'surface',controller: this.xComponentController}).onLoad(() => {// 绑定surface到AVPlayerthis.bindSurface();})// 控制区域Row() {Button('播放').onClick(() => this.playVideo())Button('暂停').onClick(() => this.pauseVideo())Slider({value: 0,min: 0,max: 100}).onChange((value: number) => {this.seekTo(value);})}}}async bindSurface() {// 获取XComponent的surfacethis.surfaceId = await this.xComponentController.getXComponentSurfaceId();// 将surface设置给AVPlayerif (this.avPlayer) {this.avPlayer.setDisplaySurface(this.surfaceId);}}async playVideo() {if (!this.avPlayer) {await this.initAVPlayer();}await this.avPlayer.play();}// 其他方法实现...}import { XComponent } from '@ohos.arkui.xcomponent'; @Entry @Component struct VideoPlayerPage { private avPlayer: media.AVPlayer = null; build() { Column() { // 视频显示区域 XComponent({ id: 'videoComponent', type: 'surface', controller: this.xComponentController }) .onLoad(() => { // 绑定surface到AVPlayer this.bindSurface(); }) // 控制区域 Row() { Button('播放') .onClick(() => this.playVideo()) Button('暂停') .onClick(() => this.pauseVideo()) Slider({ value: 0, min: 0, max: 100 }) .onChange((value: number) => { this.seekTo(value); }) } } } async bindSurface() { // 获取XComponent的surface this.surfaceId = await this.xComponentController.getXComponentSurfaceId(); // 将surface设置给AVPlayer if (this.avPlayer) { this.avPlayer.setDisplaySurface(this.surfaceId); } } async playVideo() { if (!this.avPlayer) { await this.initAVPlayer(); } await this.avPlayer.play(); } // 其他方法实现... }import { XComponent } from '@ohos.arkui.xcomponent'; @Entry @Component struct VideoPlayerPage { private avPlayer: media.AVPlayer = null; build() { Column() { // 视频显示区域 XComponent({ id: 'videoComponent', type: 'surface', controller: this.xComponentController }) .onLoad(() => { // 绑定surface到AVPlayer this.bindSurface(); }) // 控制区域 Row() { Button('播放') .onClick(() => this.playVideo()) Button('暂停') .onClick(() => this.pauseVideo()) Slider({ value: 0, min: 0, max: 100 }) .onChange((value: number) => { this.seekTo(value); }) } } } async bindSurface() { // 获取XComponent的surface this.surfaceId = await this.xComponentController.getXComponentSurfaceId(); // 将surface设置给AVPlayer if (this.avPlayer) { this.avPlayer.setDisplaySurface(this.surfaceId); } } async playVideo() { if (!this.avPlayer) { await this.initAVPlayer(); } await this.avPlayer.play(); } // 其他方法实现... }
六、高级功能实现
1. 全屏播放实现
function toggleFullscreen(isFullscreen: boolean) {// 获取窗口能力const windowClass = getContext(this).resourceManager;const window = windowClass.getTopWindow();if (window) {if (isFullscreen) {window.setWindowLayoutFullScreen(true);// 调整XComponent大小this.videoComponent.width = '100%';this.videoComponent.height = '100%';} else {window.setWindowLayoutFullScreen(false);this.videoComponent.width = 'match_parent';this.videoComponent.height = '300vp';}}}function toggleFullscreen(isFullscreen: boolean) { // 获取窗口能力 const windowClass = getContext(this).resourceManager; const window = windowClass.getTopWindow(); if (window) { if (isFullscreen) { window.setWindowLayoutFullScreen(true); // 调整XComponent大小 this.videoComponent.width = '100%'; this.videoComponent.height = '100%'; } else { window.setWindowLayoutFullScreen(false); this.videoComponent.width = 'match_parent'; this.videoComponent.height = '300vp'; } } }function toggleFullscreen(isFullscreen: boolean) { // 获取窗口能力 const windowClass = getContext(this).resourceManager; const window = windowClass.getTopWindow(); if (window) { if (isFullscreen) { window.setWindowLayoutFullScreen(true); // 调整XComponent大小 this.videoComponent.width = '100%'; this.videoComponent.height = '100%'; } else { window.setWindowLayoutFullScreen(false); this.videoComponent.width = 'match_parent'; this.videoComponent.height = '300vp'; } } }
2. 视频缓存设置
async function setCacheConfig() {const cacheConfig: media.AVPlayerCacheConfig = {enable: true, // 启用缓存maxCacheSize: 200, // 最大缓存大小(MB)maxCacheFileSize: 50, // 单个缓存文件最大大小(MB)cachePath: getContext().cacheDir + '/videoCache' // 缓存路径};await avPlayer.setCacheConfig(cacheConfig);}async function setCacheConfig() { const cacheConfig: media.AVPlayerCacheConfig = { enable: true, // 启用缓存 maxCacheSize: 200, // 最大缓存大小(MB) maxCacheFileSize: 50, // 单个缓存文件最大大小(MB) cachePath: getContext().cacheDir + '/videoCache' // 缓存路径 }; await avPlayer.setCacheConfig(cacheConfig); }async function setCacheConfig() { const cacheConfig: media.AVPlayerCacheConfig = { enable: true, // 启用缓存 maxCacheSize: 200, // 最大缓存大小(MB) maxCacheFileSize: 50, // 单个缓存文件最大大小(MB) cachePath: getContext().cacheDir + '/videoCache' // 缓存路径 }; await avPlayer.setCacheConfig(cacheConfig); }
七、资源释放
1. 正确释放资源
function releasePlayer() {if (avPlayer) {avPlayer.stop();avPlayer.release();avPlayer = null;}}// 在页面销毁时调用aboutToDisappear() {this.releasePlayer();}function releasePlayer() { if (avPlayer) { avPlayer.stop(); avPlayer.release(); avPlayer = null; } } // 在页面销毁时调用 aboutToDisappear() { this.releasePlayer(); }function releasePlayer() { if (avPlayer) { avPlayer.stop(); avPlayer.release(); avPlayer = null; } } // 在页面销毁时调用 aboutToDisappear() { this.releasePlayer(); }
八、常见问题解决
- 黑屏无画面
- 检查surface是否正确绑定
- 确认视频源是否有画面
- 检查权限是否申请
- 网络视频无法播放
- 确认网络权限已添加
- 检查URL是否有效
- 尝试设置缓存配置
- 播放卡顿
- 降低视频分辨率
- 启用硬件解码
- 检查网络状况
通过以上实现方案,您可以轻松在HarmonyOS应用中集成功能完善的视频播放器。AVPlayer提供了丰富的API支持各种播放场景,开发者可根据实际需求进行功能扩展和优化。
© 版权声明
文中内容均来源于公开资料,受限于信息的时效性和复杂性,可能存在误差或遗漏。我们已尽力确保内容的准确性,但对于因信息变更或错误导致的任何后果,本站不承担任何责任。如需引用本文内容,请注明出处并尊重原作者的版权。
THE END
暂无评论内容