RedPlayer 视频播放器在 HarmonyOS 应用中的实践

前言

在现代移动应用中,视频播放功能已经成为核心功能之一。尤其在教育类应用中,优质的视频播放体验直接影响用户学习效率和应用的用户留存率。在开发《鸿蒙轻松学》这款 HarmonyOS 教育应用时,我们选择了 RedPlayer 作为核心视频播放解决方案。RedPlayer 是小红书开源的跨平台视频播放器,基于 FFmpeg 构建,支持丰富的视频格式,并提供了稳定的播放性能。

RedPlayer 的核心优势在于跨平台支持、高性能播放、低延迟缓冲以及丰富的 API 接口。通过将 RedPlayer 集成到《鸿蒙轻松学》中,我们不仅能够实现高质量的视频播放,还能提供丰富的用户交互功能,例如进度控制、音量调节、播放速度设置和断点续播等功能,从而提升整体用户体验。本文将从环境配置、组件实现到性能优化,详细介绍 RedPlayer 在 HarmonyOS 应用中的实践经验。

REDPlayer 三方库地址:https://ohpm.openharmony.cn/#/cn/detail/@rte-xhs%2Fredplayer

鸿蒙轻松学 App 项目地址:https://gitcode.com/nutpi/Learn-HarmonyOS-Easily


RedPlayer简介

RedPlayer 是一款开源、跨平台的视频播放器,最初由小红书开发,专为移动端优化设计。它基于 FFmpeg 构建,能够支持主流的视频格式,同时提供了硬件加速能力,从而保证了播放的高性能和低延迟。RedPlayer 的 API 设计简洁,易于在 HarmonyOS 应用中集成,并支持自定义播放控制、状态监听以及进度管理等功能。对于教育类应用来说,稳定性和性能是核心考量,而 RedPlayer 在这方面表现出色,可以满足从入门到高级的视频播放需求。

在功能上,RedPlayer 支持自动播放、循环播放、音量调节、倍速播放、进度条控制和视频预加载等多种功能。同时,它提供了事件回调接口,开发者可以监听播放状态变化、播放完成、播放错误等事件,从而实现对播放器的精细化控制。通过这些功能,教育类应用能够为用户提供流畅、稳定且可交互的学习视频体验。


环境准备与依赖配置

安装 RedPlayer OHPM 包

在 HarmonyOS 项目中,RedPlayer 以 OHPM 包形式提供。首先在项目根目录下通过 OHPM 命令安装依赖包:

bash 复制代码
ohpm install @rte-xhs/redplayer

这条命令会将 RedPlayer 包下载并集成到项目中,使我们可以在应用中直接使用 RedPlayer 的 API。安装完成后,可以在项目的 entry/oh-package.json5 文件中添加依赖配置,以确保项目构建时正确引入 RedPlayer:

bash 复制代码
{
  "dependencies": {
    "@rte-xhs/redplayer": "^1.0.0"
  }
}

完成依赖安装后,还需要配置网络权限,因为播放器需要访问在线视频资源。在 module.json5 文件中添加如下权限配置:

bash 复制代码
{
  "requestPermissions": [
    {
      "name": "ohos.permission.INTERNET",
      "reason": "$string:internet_permission_reason",
      "usedScene": {
        "abilities": ["EntryAbility"],
        "when": "inuse"
      }
    }
  ]
}

这一步确保播放器在加载远程视频时不会因权限问题而出错。

完成上述配置后,RedPlayer 的环境依赖准备工作就算完成。


基础播放器组件实现

在 HarmonyOS 中,我们通常将视频播放器封装成一个组件,以便在不同页面中复用。下面是一个基础 RedPlayer 组件实现示例:

TypeScript 复制代码
import { RedPlayerController, RedPlayerXComponentController } from '@rte-xhs/redplayer'

@Component
export struct RedPlayerComponent {
  @Prop videoUrl: string = ''
  @Prop playerWidth: string | number = '100%'
  @Prop playerHeight: number = 200
  @Prop autoplay: boolean = false

  private redPlayerController: RedPlayerController = new RedPlayerController()
  private xComponentController: RedPlayerXComponentController = new RedPlayerXComponentController()

  aboutToAppear() {
    this.initializePlayer()
  }

  private initializePlayer() {
    const config = {
      url: this.videoUrl,
      autoPlay: this.autoplay,
      loop: false,
      muted: false,
      volume: 1.0
    }

    this.redPlayerController.init(config)

    this.redPlayerController.setOnPreparedListener(() => {
      console.info('RedPlayer: 播放器准备完成')
    })

    this.redPlayerController.setOnErrorListener((error) => {
      console.error('RedPlayer: 播放错误', error)
    })

    this.redPlayerController.setOnCompletionListener(() => {
      console.info('RedPlayer: 播放完成')
    })
  }

  build() {
    Column() {
      XComponent({
        id: 'redplayer_xcomponent',
        type: 'surface',
        controller: this.xComponentController
      })
      .width(this.playerWidth)
      .height(this.playerHeight)
      .onLoad(() => {
        this.redPlayerController.attachToXComponent(this.xComponentController)
      })

      this.buildControlButtons()
    }
  }

  @Builder
  buildControlButtons() {
    Row() {
      Button('播放')
        .onClick(() => {
          this.redPlayerController.start()
        })

      Button('暂停')
        .onClick(() => {
          this.redPlayerController.pause()
        })

      Button('停止')
        .onClick(() => {
          this.redPlayerController.stop()
        })
    }
    .justifyContent(FlexAlign.SpaceEvenly)
    .width('100%')
    .margin({ top: 10 })
  }
}

上述代码通过 RedPlayerController 初始化播放器,并提供播放、暂停、停止按钮以便用户控制视频播放。aboutToAppear 生命周期中调用 initializePlayer 方法配置播放器参数,并设置播放状态、错误和完成监听器。XComponent 用于渲染播放器画面,并与 RedPlayer 绑定。

通过这种组件化封装,我们可以在不同页面中复用 RedPlayer 播放器,同时保证代码结构清晰。


高级播放器功能实现

在基础播放器之上,我们实现了更高级的播放器功能,包括播放进度控制、音量调节、倍速播放等。组件通过 State 管理播放状态,包括当前播放时间、视频总时长、是否播放、音量和播放速度。组件生命周期方法 aboutToAppear 中初始化播放器并启动进度定时器,aboutToDisappear 中释放资源和停止定时器,避免内存泄漏。

TypeScript 复制代码
@Component
export struct AdvancedRedPlayerComponent {
  @State currentTime: number = 0
  @State duration: number = 0
  @State isPlaying: boolean = false
  @State volume: number = 1.0
  @State playbackSpeed: number = 1.0

  private redPlayerController: RedPlayerController = new RedPlayerController()
  private progressTimer: number = -1

  aboutToAppear() {
    this.initializeAdvancedPlayer()
    this.startProgressTimer()
  }

  aboutToDisappear() {
    this.stopProgressTimer()
    this.redPlayerController.release()
  }

  private initializeAdvancedPlayer() {
    this.redPlayerController.setOnProgressUpdateListener((current, total) => {
      this.currentTime = current
      this.duration = total
    })

    this.redPlayerController.setOnPlaybackStateChangeListener((isPlaying) => {
      this.isPlaying = isPlaying
    })
  }

  private startProgressTimer() {
    this.progressTimer = setInterval(() => {
      if (this.isPlaying) {
        this.currentTime = this.redPlayerController.getCurrentPosition()
      }
    }, 1000)
  }

  private stopProgressTimer() {
    if (this.progressTimer !== -1) {
      clearInterval(this.progressTimer)
      this.progressTimer = -1
    }
  }

  private seekTo(position: number) {
    this.redPlayerController.seekTo(position)
    this.currentTime = position
  }

  private setVolume(volume: number) {
    this.volume = volume
    this.redPlayerController.setVolume(volume)
  }

  private setPlaybackSpeed(speed: number) {
    this.playbackSpeed = speed
    this.redPlayerController.setPlaybackSpeed(speed)
  }

  @Builder
  buildAdvancedControls() {
    Column() {
      Row() {
        Text(this.formatTime(this.currentTime))
          .fontSize(12)
          .fontColor('#666')

        Slider({
          value: this.currentTime,
          min: 0,
          max: this.duration,
          step: 1
        })
        .layoutWeight(1)
        .margin({ left: 10, right: 10 })
        .onChange((value: number) => {
          this.seekTo(value)
        })

        Text(this.formatTime(this.duration))
          .fontSize(12)
          .fontColor('#666')
      }
      .width('100%')
      .margin({ top: 10 })

      Row() {
        Text('音量:')
        Slider({
          value: this.volume,
          min: 0,
          max: 1,
          step: 0.1
        })
        .width(100)
        .onChange((value: number) => {
          this.setVolume(value)
        })

        Text('倍速:')
        Button(`${this.playbackSpeed}x`)
          .onClick(() => {
            const speeds = [0.5, 0.75, 1.0, 1.25, 1.5, 2.0]
            const currentIndex = speeds.indexOf(this.playbackSpeed)
            const nextIndex = (currentIndex + 1) % speeds.length
            this.setPlaybackSpeed(speeds[nextIndex])
          })
      }
      .justifyContent(FlexAlign.SpaceEvenly)
      .width('100%')
      .margin({ top: 10 })
    }
  }

  private formatTime(seconds: number): string {
    const minutes = Math.floor(seconds / 60)
    const remainingSeconds = Math.floor(seconds % 60)
    return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
  }
}

该组件实现了高级控制功能。Slider 用于控制播放进度和音量,Button 用于切换播放速度。组件通过定时器每秒更新播放进度,使 UI 与播放器状态同步。通过这种方式,用户可以灵活控制播放,提升学习体验。


真机效果演示

视频列表页面,展示了从入门到高级的完整学习路径:

当用户点击视频卡片时,应用会切换到视频播放页面,展示完整的播放界面:

相关推荐
盐焗西兰花9 小时前
鸿蒙学习实战之路-Reader Kit修改翻页方式字体大小及行间距最佳实践
学习·华为·harmonyos
lbb 小魔仙13 小时前
【HarmonyOS实战】React Native 表单实战:在 OpenHarmony 上构建高性能表单
react native·华为·harmonyos
上海合宙LuatOS15 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
一只大侠的侠15 小时前
React Native开源鸿蒙跨平台训练营 Day16自定义 useForm 高性能验证
flutter·开源·harmonyos
早點睡39016 小时前
高级进阶 React Native 鸿蒙跨平台开发:@react-native-community-slider 滑块组件
react native·react.js·harmonyos
Android系统攻城狮16 小时前
Android16进阶之音频播放定位MediaPlayer.seekTo调用流程与实战(二百二十七)
音视频·mediaplayer·android16·音频进阶·音频性能实战
一只大侠的侠16 小时前
Flutter开源鸿蒙跨平台训练营 Day11从零开发商品详情页面
flutter·开源·harmonyos
一只大侠的侠17 小时前
React Native开源鸿蒙跨平台训练营 Day18自定义useForm表单管理实战实现
flutter·开源·harmonyos
一只大侠的侠17 小时前
React Native开源鸿蒙跨平台训练营 Day20自定义 useValidator 实现高性能表单验证
flutter·开源·harmonyos
晚霞的不甘17 小时前
Flutter for OpenHarmony 可视化教学:A* 寻路算法的交互式演示
人工智能·算法·flutter·架构·开源·音视频