HarmonyOS系统AVPlayer视频播放功能开发指南

HarmonyOS的AVPlayer提供了强大的多媒体播放能力,支持多种视频格式和网络协议。以下是利用AVPlayer开发视频播放功能的完整实现方案。

图片[1]_HarmonyOS系统AVPlayer视频播放功能开发指南_知途无界

一、基础环境配置

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 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}`);
  });
}
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. 布局文件示例

<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>
<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
@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();
  }

  // 其他方法实现...
}
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(); }

八、常见问题解决

  1. 黑屏无画面
  • 检查surface是否正确绑定
  • 确认视频源是否有画面
  • 检查权限是否申请
  1. 网络视频无法播放
  • 确认网络权限已添加
  • 检查URL是否有效
  • 尝试设置缓存配置
  1. 播放卡顿
  • 降低视频分辨率
  • 启用硬件解码
  • 检查网络状况

通过以上实现方案,您可以轻松在HarmonyOS应用中集成功能完善的视频播放器。AVPlayer提供了丰富的API支持各种播放场景,开发者可根据实际需求进行功能扩展和优化。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞35 分享
I am ordinary yet unique.
我很平凡,但我独一无二
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容