【鸿蒙开发实战篇】基于AVPlayer播放网络视频案例

大家好,我是 V 哥。今天我们来详细讲解在 HarmonyOS 6.0(API 21)中,如何使用 AVPlayer 实现网络视频播放功能。AVPlayer 是鸿蒙系统提供的一个功能完善的音视频播放 ArkTS API,它集成了流媒体和本地资源解析、媒体资源解封装、视频解码和渲染功能,能够直接播放 MP4、MKV 等格式的网络视频文件。

联系V哥获取 鸿蒙学习资料

一、功能概述与开发准备

AVPlayer 核心能力

  • 端到端播放:支持网络流媒体(如 HLS、MP4)和本地文件的完整播放流程。
  • 播放控制:提供播放、暂停、跳转、停止、倍速播放等控制能力。
  • 状态监听 :通过 stateChangetimeUpdate 等事件监听播放器状态和进度变化。

开发环境配置module.json5 文件中添加必要的依赖和权限:

json 复制代码
{
  "module": {
    "dependencies": {
      "@ohos.multimedia.media": "^1.0"  // 媒体服务核心库
    },
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET",
        "reason": "用于播放网络视频"
      }
    ]
  }
}

二、实现步骤详解

步骤 1:创建 AVPlayer 实例

首先导入媒体模块并创建 AVPlayer 实例:

typescript 复制代码
import { media } from '@ohos.multimedia.media';

// 创建 AVPlayer 实例
let avPlayer: media.AVPlayer | undefined = undefined;

async function createAVPlayer(): Promise<void> {
  try {
    avPlayer = await media.createAVPlayer();
    console.info('AVPlayer 创建成功');
  } catch (error) {
    console.error(`AVPlayer 创建失败: ${error.code}, ${error.message}`);
  }
}

步骤 2:设置播放窗口(Surface)

AVPlayer 需要通过 XComponent 获取 SurfaceID 来设置视频渲染窗口:

typescript 复制代码
import { XComponent } from '@ohos.arkui.node';

@Entry
@Component
struct VideoPage {
  @State surfaceId: string = '';
  xComponentController: XComponentController = new XComponentController();

  build() {
    Column() {
      // XComponent 用于显示视频画面
      XComponent({
        id: 'video_surface',
        type: XComponentType.SURFACE,
        controller: this.xComponentController
      })
        .onLoad(() => {
          // 获取 SurfaceID 并设置给 AVPlayer
          this.surfaceId = this.xComponentController.getXComponentSurfaceId();
          this.setSurface();
        })
        .width('100%')
        .height(300)
    }
  }

  async setSurface() {
    if (avPlayer && this.surfaceId) {
      await avPlayer.surfaceId = this.surfaceId;
    }
  }
}

步骤 3:设置网络视频资源并准备播放

配置网络视频 URL 并初始化播放器:

typescript 复制代码
async function setupVideoSource(): Promise<void> {
  if (!avPlayer) return;

  try {
    // 设置网络视频 URL
    let url = 'https://example.com/sample.mp4'; //改成自己的哈
    avPlayer.url = url;
    
    // 监听状态变化
    avPlayer.on('stateChange', (state: media.AVPlayerState) => {
      switch (state) {
        case media.AVPlayerState.IDLE:
          console.info('播放器处于闲置状态');
          break;
        case media.AVPlayerState.INITIALIZED:
          console.info('资源初始化完成');
          break;
        case media.AVPlayerState.PREPARED:
          console.info('播放器已准备就绪');
          this.startPlayback(); // 自动开始播放
          break;
        case media.AVPlayerState.PLAYING:
          console.info('视频播放中');
          break;
        case media.AVPlayerState.PAUSED:
          console.info('视频已暂停');
          break;
        case media.AVPlayerState.COMPLETED:
          console.info('播放完成');
          break;
      }
    });

    // 准备播放
    await avPlayer.prepare();
    console.info('播放器准备完成');
  } catch (error) {
    console.error(`设置视频源失败: ${error.code}, ${error.message}`);
  }
}

步骤 4:实现播放控制功能

实现基本的播放控制方法:

typescript 复制代码
// 开始播放
async function startPlayback(): Promise<void> {
  if (avPlayer && avPlayer.state === media.AVPlayerState.PREPARED) {
    await avPlayer.play();
  }
}

// 暂停播放
async function pausePlayback(): Promise<void> {
  if (avPlayer && avPlayer.state === media.AVPlayerState.PLAYING) {
    await avPlayer.pause();
  }
}

// 跳转到指定位置(单位:毫秒)
async function seekTo(position: number): Promise<void> {
  if (avPlayer) {
    await avPlayer.seek(position);
  }
}

// 停止播放并重置
async function stopPlayback(): Promise<void> {
  if (avPlayer) {
    await avPlayer.stop();
    await avPlayer.reset(); // 重置到 idle 状态
  }
}

步骤 5:实现进度监听与显示

通过 timeUpdate 事件监听播放进度:

typescript 复制代码
@State currentPosition: number = 0;
@State duration: number = 0;

function setupProgressListener(): void {
  if (!avPlayer) return;

  // 监听时间更新
  avPlayer.on('timeUpdate', (time: number) => {
    this.currentPosition = time;
  });

  // 监听视频时长
  avPlayer.on('durationUpdate', (duration: number) => {
    this.duration = duration;
  });
}

三、完整案例:网络视频播放器

以下是一个完整的网络视频播放器实现:

typescript 复制代码
@Entry
@Component
struct NetworkVideoPlayer {
  @State surfaceId: string = '';
  @State currentPos: number = 0;
  @State totalDuration: number = 0;
  @State isPlaying: boolean = false;
  
  xComponentController: XComponentController = new XComponentController();
  avPlayer: media.AVPlayer | undefined = undefined;

  aboutToAppear() {
    this.initAVPlayer();
  }

  async initAVPlayer() {
    try {
      this.avPlayer = await media.createAVPlayer();
      this.setupEventListeners();
    } catch (error) {
      console.error(`播放器初始化失败: ${error.message}`);
    }
  }

  setupEventListeners() {
    if (!this.avPlayer) return;

    // 状态监听
    this.avPlayer.on('stateChange', (state: media.AVPlayerState) => {
      if (state === media.AVPlayerState.PREPARED) {
        this.avPlayer?.play();
        this.isPlaying = true;
      }
    });

    // 进度监听
    this.avPlayer.on('timeUpdate', (time: number) => {
      this.currentPos = time;
    });

    this.avPlayer.on('durationUpdate', (duration: number) => {
      this.totalDuration = duration;
    });
  }

  async setupVideoSource() {
    if (!this.avPlayer || !this.surfaceId) return;

    try {
      //改成自己的url地址哈
      this.avPlayer.url = 'https://example.com/sample.mp4';
      this.avPlayer.surfaceId = this.surfaceId;
      await this.avPlayer.prepare();
    } catch (error) {
      console.error(`视频源设置失败: ${error.message}`);
    }
  }

  build() {
    Column() {
      // 视频显示区域
      XComponent({
        id: 'video_surface',
        type: XComponentType.SURFACE,
        controller: this.xComponentController
      })
        .onLoad(() => {
          this.surfaceId = this.xComponentController.getXComponentSurfaceId();
          this.setupVideoSource();
        })
        .width('100%')
        .height(300)

      // 控制面板
      Row({ space: 20 }) {
        Button(this.isPlaying ? '暂停' : '播放')
          .onClick(() => {
            if (this.isPlaying) {
              this.avPlayer?.pause();
              this.isPlaying = false;
            } else {
              this.avPlayer?.play();
              this.isPlaying = true;
            }
          })
        
        Text(`${this.formatTime(this.currentPos)}/${this.formatTime(this.totalDuration)}`)
          .fontSize(14)
      }
      .margin(10)
    }
  }

  formatTime(ms: number): string {
    let seconds = Math.floor(ms / 1000);
    let minutes = Math.floor(seconds / 60);
    seconds = seconds % 60;
    return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
  }

  aboutToDisappear() {
    if (this.avPlayer) {
      this.avPlayer.release();
      this.avPlayer = undefined;
    }
  }
}

四、关键注意事项

  1. 网络权限与安全 :确保在 module.json5 中声明 INTERNET 权限,并使用 HTTPS 链接保证网络安全。

  2. 状态机管理:AVPlayer 有严格的状态机(idle → initialized → prepared → playing 等),必须在合适的状态下调用相应方法。

  3. 资源释放 :在页面销毁时务必调用 release() 方法释放资源,防止内存泄漏:

typescript 复制代码
aboutToDisappear() {
  if (this.avPlayer) {
    this.avPlayer.release();
    this.avPlayer = undefined;
  }
}
  1. 错误处理:增加网络状态监听,处理弱网或断网情况:
typescript 复制代码
avPlayer.on('error', (error: BusinessError) => {
  console.error(`播放错误: ${error.code}, ${error.message}`);
  // 可在此添加重试逻辑或用户提示
});

五、总结

通过本文的详细实现步骤,我们掌握了在 HarmonyOS 6.0 中使用 AVPlayer 播放网络视频的完整流程。关键点包括:正确创建 AVPlayer 实例、通过 XComponent 设置播放窗口、配置网络视频源、实现播放控制以及合理的资源管理。AVPlayer 提供了强大的视频播放能力,结合正确的状态管理和错误处理,可以开发出体验良好的网络视频播放应用。

希望这篇文章能帮助你在鸿蒙应用开发中顺利实现视频播放功能!

相关推荐
威哥爱编程1 小时前
【鸿蒙开发实战篇】实现剪切板复制粘贴的功能
harmonyos·arkts·arkui
威哥爱编程2 小时前
【鸿蒙开发实战篇】鸿蒙6 AI智能体集成实战
harmonyos·arkts·arkui
威哥爱编程2 小时前
【鸿蒙开发实战篇】鸿蒙开发中如何利用代码检查工具(codelinter)的技巧和经验
harmonyos·arkts·arkui
威哥爱编程2 小时前
【鸿蒙开发实战篇】鸿蒙6开发中CANN Kit十大常见问题与解决方案
harmonyos·arkts·arkui
9***Y487 小时前
HarmonyOS在智能车载中的导航系统
华为·harmonyos
马剑威(威哥爱编程)13 小时前
鸿蒙6开发视频播放器的屏幕方向适配问题
java·音视频·harmonyos
1***Q78413 小时前
HarmonyOS在智能汽车中的V2X通信
华为·汽车·harmonyos
p***c94913 小时前
HarmonyOS应用分发
华为·harmonyos
4***149015 小时前
HarmonyOS在智能电视中的语音交互
华为·harmonyos·智能电视