鸿蒙 ArkTS语言封装一个完整的视频播放器

441 阅读6分钟

用ArkTS语言封装一个完整的视频播放器,支持自定义初始播放URL和推流地址。视频播放通常涉及媒体组件和控制功能。

文件结构:

VideoPlayerApp/
├── videoPlayer.ts                # 播放器核心逻辑
├── controls.ts                   # 主控制面板
├── volumeControl.ts              # 音量控制子系统
├── brightnessControl.ts          # 屏幕亮度控制
├── playbackSpeedControl.ts       # 播放速率控制
├── loadingAnimation.ts           # 加载状态指示器
└── types/
    └── videoTypes.d.ts           # 类型定义文件

一、文件结构实现

1. videoPlayer.ts

import { Controls } from './controls'
import { LoadingAnimation } from './loadingAnimation'

@Observed
export class VideoPlayer {
  private videoController: VideoController = new VideoController()
  private currentSource: VideoResource = new VideoResource()

  // 初始化播放器
  initPlayer(url: string | VideoResource) {
    this.currentSource = this.validateSource(url)
    LoadingAnimation.show()
  }

  private validateSource(source: string | VideoResource): VideoResource {
    if (typeof source === 'string') {
      return new VideoResource().parse(source)
    }
    return source
  }

  build() {
    Column() {
      Video({
        controller: this.videoController,
        src: this.currentSource
      })
      .onPrepared(() => LoadingAnimation.hide())
      
      Controls({ controller: this.videoController })
    }
  }
}

2. controls.ts

import { VolumeControl } from './volumeControl'
import { BrightnessControl } from './brightnessControl'
import { PlaybackSpeedControl } from './playbackSpeedControl'

export class Controls {
  @Link controller: VideoController

  build() {
    Row() {
      ButtonGroup() {
        // 播放控制
        Button(this.controller.isPlaying ? '⏸' : '▶')
          .onClick(() => this.togglePlayback())
        
        // 音量控制
        VolumeControl({ controller: this.controller })
        
        // 亮度控制
        BrightnessControl({ controller: this.controller })
        
        // 倍速控制
        PlaybackSpeedControl({ controller: this.controller })
      }
    }
  }

  private togglePlayback() {
    this.controller.isPlaying ? 
      this.controller.pause() : 
      this.controller.start()
  }
}

3. volumeControl.ts

export class VolumeControl {
  @Link controller: VideoController
  @State currentVolume: number = 1.0

  build() {
    Slider({ value: this.currentVolume, min: 0, max: 1, step: 0.1 })
      .onChange((value: number) => {
        this.controller.volume = value
        this.currentVolume = value
      })
  }
}

4. brightnessControl.ts

export class BrightnessControl {
  @State currentBrightness: number = 1.0

  build() {
    Slider({ value: this.currentBrightness, min: 0.1, max: 1, step: 0.1 })
      .onChange((value: number) => {
        windowClass.setBrightness(value)
        this.currentBrightness = value
      })
  }
}

5. playbackSpeedControl.ts

export class PlaybackSpeedControl {
  @Link controller: VideoController
  private speeds: number[] = [0.5, 1.0, 1.5, 2.0]

  build() {
    SelectPicker(this.speeds)
      .onSelect((speed: number) => {
        this.controller.playbackSpeed = speed
      })
  }
}

6. loadingAnimation.ts

export class LoadingAnimation {
  @State static isVisible: boolean = false

  static show() {
    this.isVisible = true
  }

  static hide() {
    this.isVisible = false
  }

  static build() {
    if (this.isVisible) {
      Progress({ width: '60%', height: '60%' })
        .color(Color.Blue)
    }
  }
}

二、完整使用示例

// MainPage.ets
import { VideoPlayer } from './videoPlayer'

@Entry
@Component
struct MediaPage {
  private player: VideoPlayer = new VideoPlayer()

  aboutToAppear() {
    // 初始化播放器(支持网络/本地/推流地址)
    this.player.initPlayer('rtmp://live.example.com/stream')
    
    // 或使用对象配置
    /* this.player.initPlayer({
      src: 'https://example.com/video.mp4',
      type: 'network',
      drm: { 
        type: 'widevine',
        licenseServer: 'https://drm.example.com'
      }
    }) */
  }

  build() {
    Column() {
      // 主播放器
      this.player.build()
      
      // 自定义控件
      Button('切换全屏')
        .onClick(() => this.player.toggleFullscreen())
    }
    .onClick(() => this.player.showControls())
  }
}

三、完整技术文档

视频播放器说明文档

1. 概述

本播放器组件基于HarmonyOS NEXT的ArkTS框架开发,提供以下核心功能:

  • 支持多种视频源(本地文件/网络视频/实时流媒体)
  • 模块化控制组件
  • 自定义UI扩展能力
  • 硬件加速解码
  • DRM数字版权管理

2. 功能特性

模块功能说明
VideoPlayer核心播放控制/生命周期管理
VolumeControl音量调节(0-100%)
BrightnessControl屏幕亮度调节(10%-100%)
PlaybackSpeed支持0.5x-2.0x倍速播放
LoadingAnimation加载指示器(支持自定义动画)

3. 使用指南

3.1 快速集成

// 初始化播放器
const player = new VideoPlayer()
player.initPlayer('https://example.com/video.mp4')

// 在UI中渲染
player.build()

3.2 播放控制

// 播放/暂停
player.controller.start()
player.controller.pause()

// 跳转到指定位置
player.controller.seekTo(120) // 单位:秒

// 全屏切换
player.toggleFullscreen()

3.3 事件监听

Video()
  .onEnded(() => {
    console.log('播放结束')
  })
  .onError((error: BusinessError) => {
    console.error('播放错误:', error.code)
  })

4. API参考

VideoPlayer 类

方法参数说明返回值
initPlayer(source)初始化视频源void
toggleFullscreen()切换全屏模式void
destroy()释放播放器资源void

VideoController 属性

属性类型说明
currentTimenumber当前播放位置(秒)
durationnumber视频总时长(秒)
playbackRatenumber播放速度(0.5-2.0)
volumenumber音量(0.0-1.0)

5. 注意事项

  1. 网络视频需要配置权限:

    {
      "reqPermissions": [
        {
          "name": "ohos.permission.INTERNET"
        }
      ]
    }
    
  2. 实时流媒体协议支持:

    • RTMP:需服务端开启TCP 1935端口
    • HLS:建议使用HTTPS协议
    • RTSP:支持Basic/Digest认证
  3. 性能优化建议:

    Video()
      .decoding({
        hardwareAccelerated: true,  // 启用硬件解码
        preferredCodec: {           // 优先解码格式
          video: 'video/hevc'       
        }
      })
      .cacheControl({               // 缓存策略
        maxCacheSize: 512MB,        
        preloadSize: 10MB
      })
    
  4. DRM支持:

    initPlayer({
      src: 'video.mp4',
      drm: {
        type: 'widevine',
        licenseServer: 'https://drm.example.com',
        headers: {
          'Authorization': 'Bearer xxx'
        }
      }
    })
    

本播放器组件可根据具体业务需求进行扩展,建议通过继承VideoPlayer基类实现自定义功能扩展。

一、组件架构

graph TD
    A[VideoPlayer] --> B(Controls)
    A --> C(LoadingAnimation)
    B --> D(VolumeControl)
    B --> E(BrightnessControl)
    B --> F(PlaybackSpeedControl)

二、模块说明

1. videoPlayer.ts

核心功能

  • 播放器生命周期管理
  • 多媒体资源加载
  • 播放状态管理
  • 全屏控制

关键接口

interface IVideoPlayer {
  // 初始化播放器
  initPlayer(source: string | VideoResource): void
  
  // 渲染播放器组件
  build(): void
  
  // 全屏切换
  toggleFullscreen(enable?: boolean): void
  
  // 释放资源
  destroy(): void
}

配置参数

interface PlayerConfig {
  autoplay?: boolean       // 自动播放(默认false)
  loop?: boolean           // 循环播放
  controls?: boolean       // 显示控制面板
  aspectRatio?: 'fit' | 'fill' // 画面比例
}

2. controls.ts

功能组成

pie
    title 控制面板功能分布
    "播放/暂停" : 35
    "进度控制" : 25
    "音量调节" : 20
    "亮度调节" : 15
    "倍速播放" : 5

交互逻辑

// 手势操作示例
GestureGroup(GesturePriority.Low)
  .onPan(event => {
    if (Math.abs(event.offsetX) > 20) {
      this.handleSeek(event.offsetX)
    }
    if (Math.abs(event.offsetY) > 20) {
      this.handleVolume(event.offsetY)
    }
  })

3. volumeControl.ts

实现原理

// 系统音量与UI同步
private syncSystemVolume() {
  systemVolume.getVolume().then(vol => {
    this.currentVolume = vol / 100
  })
}

// 音量渐变控制
private smoothAdjust(target: number) {
  animateTo({ duration: 300 }, () => {
    this.currentVolume = target
  })
}

4. brightnessControl.ts

亮度调节矩阵

手势方向亮度变化灵敏度
垂直上滑增加亮度每像素0.5%
垂直下滑降低亮度每像素0.5%
水平滑动无响应-

5. playbackSpeedControl.ts

速率支持表

倍率实现方式音频处理
0.5x帧丢弃重采样
1.0x正常播放原声输出
1.5x时间戳压缩音调修正
2.0x关键帧加速智能降噪

6. loadingAnimation.ts

状态机转换

stateDiagram
    [*] --> Idle
    Idle --> Loading: 开始缓冲
    Loading --> Idle: 缓冲完成
    Loading --> Error: 缓冲失败
    Error --> Loading: 重试操作

三、集成指南

基础集成示例

// 初始化播放器
const player = new VideoPlayer()

// 配置播放源(支持多种格式)
player.initPlayer({
  src: 'https://example.com/4k.mp4',
  type: 'adaptive',  // 自适应流
  drm: {
    type: 'widevine',
    licenseUrl: 'https://drm.example.com/license'
  }
})

// 添加事件监听
player.on('resolutionChanged', (res) => {
  console.log(`分辨率切换至: ${res.width}x${res.height}`)
})

推流地址示例

player.initPlayer({
  src: 'rtmp://live.example.com/stream',
  type: 'live',
  config: {
    bufferSize: 10,     // 缓冲秒数
    reconnectTimes: 3   // 重连次数
  }
})

自定义样式

player.setStyle({
  controlPanel: {
    backgroundColor: '#333',
    buttonColor: '#00ff87',
    sliderTrack: '#4a4a4a',
    sliderThumb: '#00ff87'
  },
  loadingIndicator: {
    type: 'spiral',    // 可选:spinner/pulse/spiral
    color: '#00ff87',
    size: 'large'
  }
})

四、API参考手册

VideoController 方法

方法参数返回值说明
setPlaybackRate()rate: number (0.5-2.0)void设置播放速率
snapshot()quality: number (1-100)string截取当前帧(base64)
getAudioTracks()-Array获取音轨列表
setAudioTrack()index: numberbool切换音轨

事件系统

监听方式

player.addEventListener('bufferingstart', () => {
  LoadingAnimation.show()
})

player.addEventListener('resolutionchange', (detail) => {
  console.log(`New resolution: ${detail.width}x${detail.height}`)
})

事件类型

事件名称触发条件回调参数
ready媒体数据加载完成-
resolutionchange视频分辨率改变{width, height}
audioTrackChange音轨切换trackIndex
subtitleUpdate字幕更新textContent

五、最佳实践

1. 性能优化建议

// 启用硬件解码
Video({
  decoding: {
    hardwareAccelerated: true,
    preferredCodec: 'video/hevc'
  }
})

// 内存管理配置
MemoryManager.configure({
  maxCache: 512MB,
  releasePolicy: 'lru'  // 最近最少使用策略
})

2. 异常处理方案

错误码对照表

错误码说明建议处理方式
1001网络连接失败检查URL/重试连接
1002解码器不支持切换视频格式/更新解码器
2001DRM授权失败验证许可证服务器
3001硬件资源不足降低分辨率/关闭其他应用

错误处理示例

try {
  player.initPlayer('https://invalid.url')
} catch (error) {
  if (error.code === 1001) {
    showToast('网络连接失败,请检查链接')
  }
  logger.error('播放器初始化失败:', error)
}

六、扩展开发

自定义控制组件

// 实现自定义控制接口
class CustomControls implements IPlayerControls {
  build() {
    Button('自定义按钮')
      .onClick(() => {
        this.dispatchEvent('customAction')
      })
  }
}

// 替换默认控制器
player.setControls(new CustomControls())

插件开发示例

字幕插件实现

class SubtitlePlugin implements IVideoPlugin {
  init(player: VideoPlayer) {
    player.addEventListener('texttrack', (track) => {
      this.renderSubtitles(track)
    })
  }
  
  private renderSubtitles(text: string) {
    // 实现字幕渲染逻辑
  }
}

// 注册插件
player.use(new SubtitlePlugin())

本组件遵循HarmonyOS应用开发规范,支持灵活扩展和深度定制,建议使用TypeScript 4.9+进行二次开发。