# ccplayer
**Repository Path**: seagazer/ccplayer
## Basic Information
- **Project Name**: ccplayer
- **Description**: A media player for OpenHarmony.
- **Primary Language**: TypeScript
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2023-10-29
- **Last Updated**: 2026-01-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# ccplayer
## 简介
CcPlayer 是一个为 OpenHarmony和HarmonyOS Next 设计,支持音视频媒体的轻量级播放器应用框架。
- 支持音频/视频播放
- 支持绑定播控中心(**HarmonyOS**)
- 支持长时后台播放
- 支持画中画悬浮窗播放(**HarmonyOS**)
- 支持音频焦点监听及默认处理策略
- 提供视频播放组件CcPlayerView,支持视频宽高比切换及手势操作
- 提供视频播放组件CcPlayerViewV2,支持状态管理框架V2版本
- 提供默认手势控制面板组件CcGestureOverlay
- 提供默认媒体控制面板组件CcControllerOverlay
- 提供默认标题面板组件CcTitleBarOverlay
- 提供默认加载面板组件CcLoadingOverlay
- 提供播放器实例缓存池,资源管理及复用能力
- 支持获取本地视频文件缩略图
- 支持接入自定义播放业务(切换播放内核,自定义类需要实现IPlayer接口)
- 支持IjkPlayer扩展插件(需要依赖@seagazer/ccplayer-ijk插件,仅支持网络媒体播放)
## 示例效果
| 视频组件 | 音乐播放 | 播控中心 | PIP模式 |
| --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
|
|
|
## 依赖方式
```shell
ohpm install @seagazer/ccplayer
```
## 注意事项
- 从1.0.6版本开始基于API 12进行重构,仅支持OpenHarmony-5.0+ Release和HarmonyOS 5.0.0+。
- 如果需要在5.0-Release之前的系统版本中使用,请采用1.0.5及以下版本。各个版本详情可以参照之前版本的ChangeLog说明。
- 因为OpenHarmony缺失部分能力,某些能力仅支持HarmonyOS,上述简介中已标注。
## 接口能力
- CcPlayer 媒体播放器
| 接口 | 参数 | 返回值 | 说明 |
| ------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------- |
| construct | context: BaseContxt | CcPlayer | 创建CcPlayer实例 |
| setPlayer | player: IPlayer | void | 设置播放器实例,用户可通过实现IPlayer接口来自定义播放业务实现 |
| start | void | void | 开始/恢复播放 |
| startTo | position: number | void | 从指定时间戳开始播放 |
| pause | void | void | 暂停播放 |
| stop | void | void | 停止播放 |
| reset | void | void | 重置播放器 |
| release | void | void | 释放播放器 |
| seekTo | position: number | void | 跳转至指定进度 |
| setSeekMode | mode: media.SeekMode | void | 设置seek模式,默认SEEK_CLOSEST |
| setMediaSource | mediaSource: MediaSource , onReady?: ()=>void | void | 设置媒体资源,在onReady回调中可以调用start开启播放 |
| getMediaSource | void | MediaSource | 获取当前播放的媒体资源 |
| setLooper | isLoop: boolean | void | 设置循环播放 |
| setVolume | vol: number | void | 设置音量 |
| setPlaySpeed | speed: number \| media.PlaybackSpeed | void | 设置播放倍速 |
| isPlaying | void | boolean | 是否正在播放 |
| getDuration | void | number | 获取媒体资源的总时长 |
| getCurrentPosition | void | number | 获取当前播放时长 |
| getPlayerState | void | PlayerState | 获取当前播放状态 |
| getSystemPlayer | void | AVPlayer \| IPlayer | 获取当前系统播放器实例 |
| setSurface | surfaceId: string | void | 绑定 surafce(仅媒体类型为视频时有效) |
| bindXComponent | controller: XComponentController, loadContext: object | void | 绑定 surafce和Native对象 |
| addOnPreparedListener | listener: () => void | IPlayer | 添加媒体资源 prepare 状态监听 |
| removeOnPreparedListener | listener: () => void | IPlayer | 移除媒体资源 preapare 状态监听 |
| addOnCompletionListener | listener: () => void | IPlayer | 添加媒体资源播放结束状态监听 |
| removeOnCompletionListener | listener: () => void | IPlayer | 移除媒体资源播放结束状态监听 |
| addOnErrorListener | listener: (code: number, message: string) => void | IPlayer | 添加媒体资源播放异常状态监听 |
| removeOnErrorListener | listener: (code: number, message: string) => void | IPlayer | 移除媒体资源播放异常状态监听 |
| addOnProgressChangedListener | listener: (duration: number) => void | IPlayer | 添加播放进度状态监听 |
| removeOnProgressChangedListener | listener: (duration: number) => void | IPlayer | 移除播放进度状态监听 |
| addOnSeekChangedListener | listener: (duration: number) => void | IPlayer | 添加播放快进快退状态监听 |
| removeOnSeekChangedListener | listener: (duration: number) => void | IPlayer | 移除播放快进快退状态监听 |
| addOnVolumeChangedListener | listener: (volume: number) => void | IPlayer | 添加媒体音量变化状态监听 |
| removeOnVolumeChangedListener | listener: (volume: number) => void | IPlayer | 移除媒体音量变化状态监听 |
| addOnStateChangedListener | listener: (state: PlayerState) => void | IPlayer | 添加播放状态变更监听 |
| removeOnStateChangedListener | listener: (state: PlayerState) => void | IPlayer | 移除播放状态变更监听 |
| addOnVideoSizeChangedListener | listener: (width: number, height: number) => void | IPlayer | 添加视频尺寸变化监听 |
| removeOnVideoSizeChangedListener | listener: (width: number, height: number) => void | IPlayer | 移除视频尺寸变化监听 |
| addOnRenderFirstFrameListener | listener: () => void | IPlayer | 添加首帧画面渲染监听 |
| removeOnRenderFirstFrameListener | listener: () => void | IPlayer | 移除首帧画面渲染监听 |
| addOnAudioFocusChangedListener | (event: AudioFocusEvent) => void | IPlayer | 添加音频焦点变化监听 |
| removeOnAudioFocusChangedListener | (event: AudioFocusEvent) => void | IPlayer | 移除音频焦点变化监听 |
| addOnMediaChangedListener | (source: MediaSource) => void | void | 添加切换媒体资源监听 |
| removeOnMediaChangedListener | (source: MediaSource) => void | void | 移除切换媒体资源监听 |
| bindAvSession | context:BaseContext, sessioName:string, type:AVSessionType, agentInfo:WantAgentInfo | void | 绑定播控中心 |
| addAvSessionCallback | callback: AvSessionCallback | void | 添加播控中心操作事件监听 |
| removeAvSessionCallback | callback: AvSessionCallback | void | 移除播控中心操作事件监听 |
| setBackgroundPlayEnable | backgroundPlay: boolean | Promise\ | 设置是否开启后台长时播放 |
| setXComponentController | controller: XComponentController | void | 设置xComponent的controller,pip必须设置 |
| getXComponentController | void | XComponentController | 返回xComponent的controller |
| enablePip | navigationId: string, pipType: PiPWindow.PiPTemplateType | PiPWindow.PiPController | 启用pip画中画能力 |
| disablePip | void | void | 禁用pip画中画能力 |
| startPip | void | void | 开启pip画中画 |
| stopPip | void | void | 关闭pip画中画 |
| addOnPipStateChangedListener | listener: (state: PiPWindow.PiPState, reason: string) => void | void | 添加pip状态监听 |
| removeOnPipStateChangedListener | listener: (state: PiPWindow.PiPState, reason: string) => void | void | 移除pip状态监听 |
| getSnapshotFromFile | filePath: string, width: number, height: number, timestamp: number | Promise\ | 获取视频文件缩略图 |
| getSnapshotFromAssets | rawPath: string, width: number, height: number, timestamp: number | Promise\ | 获取视频文件缩略图 |
| setKeepScreenOn | uiContext: UIContext, keepScreenOn: boolean | Promise\ | 设置屏幕是否常亮 |
| addOnBufferProgressChangedListener | listener: (duration: number) => void | void | 添加缓冲进度监听 |
| removeOnBufferProgressChangedListener | listener: (duration: number) => void | void | 移除缓冲进度监听 |
| getBufferPosition | void | number | 获取当前缓冲进度 |
- MediaSourceFactory 媒体资源构建器
| 接口 | 参数 | 返回值 | 说明 |
| ------------ | ------------------------------------------------------------------------------------------------------------------------ | --------------------- | ----------------------------- |
| createFile | title: string, filePath: string, cover?: string\|Pixelmap | Promise\ | 通过本地文件创建媒体资源 |
| createAssets | title: string, rawAssetsPath: string, cover?: string\|PixelMap | MediaSource | 通过 Raw 文件创建媒体资源 |
| createUrl | title: string, url: string, cover?: string\|Pixelmap, header?: Record, strategy?: media.PlaybackStrategy | MediaSource | 通过网络 url 地址创建媒体资源 |
- MediaLogger 调试信息开关
| 接口 | 参数 | 返回值 | 说明 |
| ----------- | -------------- | ------ | ----------------------------------- |
| setDebugger | debug: boolean | void | 设置是否开始调试信息打印,默认false |
- CcPlayerPool 播放器实例缓存池(用于同页面多视频需要频繁切换的播放场景,实现预加载能力)
| 接口 | 参数 | 返回值 | 说明 |
| ----------- | ----------------------------------- | ------------ | ------------------------------------------- |
| getInstance | void | CcPlayerPool | 获取CcPlayerPool实例(单例) |
| init | context: Context, cacheSize: number | void | 设置播放器实例缓存池大小 |
| get | void | CcPlayer | 从缓存池获取一个可用的播放器实例 |
| recycle | player: CcPlayer | void | 回收从缓存池中获取且使用过的播放器实例 |
| destroy | void | void | 清空缓存池中播放器实例,并且重置CcPlayerPool |
- CcPlayerView 视频播放组件 / CcPlayerViewV2(适用于状态管理框架V2版本)
| 属性 | 类型 | 说明 | 是否必填 |
| ---------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------- | -------- |
| player | CcPlayer | 媒体播放器 | 是 |
| gestureAreaConfig | GestureAreaConfig | 手势区域配置,默认左半边亮度,右半边音量 | 否 |
| horizontalGestureDamping | number | 手势水平滑动阻尼系数,默认2,手势滑动距离与进度换算比为2:1 | 否 |
| verticalGestureDamping | number | 手势垂直滑动阻尼系数,默认1.5,手势滑动距离与进度换算比为1.5:1 | 否 |
| renderType | XComponentType | 视频渲染模式,默认SURFACE | 否 |
| asRatio | AspectRatio | 视频画面比例 | 是 |
| autoHideControllerDelay | number | 自动隐藏手势 UI 的延时,默认1.5s | 否 |
| isSupportGesture | boolean | 是否支持手势操作,默认true | 否 |
| onTouchCallback | (event: TouchEvent) => void | 触摸事件回调 | 否 |
| onSurfaceCreated | (surfaceId: string) => void | Surface 创建事件回调 | 否 |
| onSurfaceDestroy | (surfaceId: string) => void | Surface 销毁事件回调 | 否 |
| onGestureUIListener | (visible: boolean) => void | 手势 UI 显示/隐藏回调 | 否 |
| onGestureAction | (type: GestureType, percent: number, isTouchUp: boolean) => void | 手势操作回调 | 否 |
| aspectRatioChangeAnimationDuration | number | 视频切换宽高比动效时长,默认150ms | 否 |
| defaultBrightness | number | 组件启用的默认手势亮度值,取值0-1,默认0.5 | 否 |
| defaultVolume | number | 组件启用的默认手势音量值,取值0-1,默认1 | 否 |
- CcGestureOverlay 手势控制UI面板,需要结合NodeContainer使用,实时的UI状态值可以通过CcPlayerView的onGestureAction和onGestureUIListener回调中获取
| 接口 | 参数 | 返回值 | 说明 |
| ------------------- | ---------------------------------------------------------------------------- | ---------------- | ------------------------------------- |
| construct | player: CcPlayer | CcGestureOverlay | 创建CcGestureOverlay实例 |
| setTextSize | size: Length | void | 设置overlay字体大小,单位fp,默认14fp |
| setIconSize | size: Length | void | 设置overlay图标大小,单位vp,默认16vp |
| setTextColor | color: ResourceColor | void | 设置overlay字体颜色,默认#ffffffff |
| setBackgroundColor | type: GestureType | void | 设置overlay背景颜色,默认#a6000000 |
| setGestureType | size: number | void | 设置当前CcPlayerView的手势类型 |
| setGesturePercent | percent: number | void | 设置当前CcPlayerView的手势进度值 |
| handleGestureAction | uiContext: UIContext, type: GestureType, percent: number, isTouchUp: boolean | void | 手势默认处理 |
| setVisible | visible: boolean | void | 设置当前Overlay的显示状态 |
- CcControllerOverlay 媒体播放控制UI面板
| 接口 | 参数 | 返回值 | 说明 |
| ---------------------- | -------------------------- | ---------------- | ----------------------------------------------------------- |
| construct | player: CcPlayer | CcGestureOverlay | 创建CcControllerOverlay实例 |
| setTextSize | size: Length | void | 设置进度值字体大小,单位fp,默认14fp |
| setTextColor | color: ResourceColor | void | 设置进度值字体颜色,默认#ffffffff |
| setSliderTrackColor | color: ResourceColor | void | 设置进度条轨道颜色,默认#ccffffff |
| setSliderBlockColor | color: ResourceColor | void | 设置进度条滑块颜色,默认#ffffffff |
| setSliderSelectedColor | color: ResourceColor | void | 设置进度条的进度颜色,默认sys.color.ohos_id_color_emphasize |
| setPadding | padding: Length \| Padding | void | 设置overlay字体与左右边缘的水平边距 |
| setSliderMargin | margin: Margin | void | 设置seekbar与文本的水平间距 |
| setVisible | visible: boolean | void | 设置当前Overlay的显示状态 |
- CcTitleBarOverlay 媒体标题UI面板
| 接口 | 参数 | 返回值 | 说明 |
| ------------------ | -------------------------- | ---------------- | -------------------------------------- |
| construct | player: CcPlayer | CcGestureOverlay | 创建CcTitleBarOverlay实例 |
| setTextSize | size: Length | void | 设置标题字体大小,单位fp,默认14fp |
| setTextColor | color: ResourceColor | void | 设置标题字体颜色,默认#ffffffff |
| setBackgroundColor | type: GestureType | void | 设置overlay背景颜色,默认#a6000000 |
| setPadding | padding: Length \| Padding | void | 设置当前CcPlayerView的标题组件的内边距 |
| setVisible | visible: boolean | void | 设置当前Overlay的显示状态 |
- CcLoadingOverlay 视频加载UI面板
| 接口 | 参数 | 返回值 | 说明 |
| ------------------ | -------------------------- | ---------------- | ----------------------------------------- |
| construct | player: CcPlayer | CcGestureOverlay | 创建CcLoadingOverlay实例 |
| setLoadingText | text: string | void | 设置loading提示文本 |
| setLoadingSize | size: Length | void | 设置loading的大小,单位vp,默认56vp |
| setLoadingMargin | margin: Length | void | 设置loading和文本的间距,单位vp,默认16vp |
| setPadding | padding: Length \| Padding | void | 设置loading组件四周边距 |
| setTextSize | size: Length | void | 设置loading字体大小,单位fp,默认14fp |
| setTextColor | color: ResourceColor | void | 设置loading字体颜色,默认#ffffffff |
| setBackgroundColor | type: GestureType | void | 设置overlay背景颜色,默认#a6000000 |
| setVisible | visible: boolean | void | 设置当前Overlay的显示状态 |
- GestureType 视频播放组件手势类型
| 枚举值 | 说明 |
| ---------- | -------- |
| BRIGHTNESS | 亮度调节 |
| PROGRESS | 进度调节 |
| VOLUME | 音量调节 |
- GestureAreaConfig 视频播放组件手势区域配置
| 属性 | 类型 | 说明 | 是否必填 |
| ----- | ----------- | ---------------------------- | -------- |
| left | GestureType | 左半边区域手势类型,默认亮度 | 否 |
| right | GestureType | 右半边区域手势类型,默认音量 | 否 |
- AspectRatio 视频画面比例
| 枚举值 | 说明 |
| ------- | ---------------- |
| AUTO | 自动匹配 |
| W_16_9 | 16:9 宽屏 |
| W_4_3 | 4:3 |
| W_21_9 | 21:9 宽屏 |
| STRETCH | 保持比例裁切填充 |
| FILL | 拉伸填充 |
- AudioFocusEvent 音频焦点变更事件
| 枚举值 | 说明 |
| ---------------- | ------------ |
| AUDIO_FOCUS_LOST | 音频焦点丢失 |
| AUDIO_FOCUS_GAIN | 音频焦点获取 |
- AvSessionCallback 播控中心事件回调
| 属性 | 类型 | 说明 |
| ---------- | ---------- | ---------- |
| onNext | () => void | 播放下一首 |
| onPrevious | () => void | 播放上一首 |
- PlayerState 播放器状态
| 枚举值 | 说明 |
| --------------- | ---------------------- |
| STATE_NOT_INIT | 初始状态(未实例化) |
| STATE_IDLE | 播放器实例化且闲置状态 |
| STATE_PREPARED | 播放器加载资源完成状态 |
| STATE_STARTED | 播放器正在播放状态 |
| STATE_PAUSED | 播放器暂停状态 |
| STATE_STOPPED | 播放器停止状态 |
| STATE_COMPLETED | 播放器播放结束状态 |
| STATE_ERROR | 播放器播放异常状态 |
## 场景示例
- 使用 CcPlayerView 播放视频,以及快速集成默认手势和加载Overlay的方式(V2版本使用流程一致):
```typescript
@Entry
@Component
struct PlayerViewPage {
// 视频画面比例模式
@State videoRatio: AspectRatio = AspectRatio.AUTO
// 1.实例化CcPlayer
private player: CcPlayer = new CcPlayer(getContext(this))
// 2.实例化手势UI面板
private gestureOverlay: CcGestureOverlay = new CcGestureOverlay(this.player)
aboutToAppear(): void {
// 如果使用ijk插件,需要先绑定插件
const ijkPlayer = new IjkPlayer()
this.player.setPlayer(ijkPlayer)
// 3.设置手势UI面板各项参数
this.gestureOverlay.setTextSize(18)
this.gestureOverlay.setTextColor('#ffead981')
}
build() {
Column() {
// 注意:Overlay面板采用层叠的组合方式,需要使用Stack或者RelativeContainer作为根容器
Stack() {
// 4.引用CcPlayerView视频播放组件,设置参数,绑定CcPlayer
CcPlayerView({
player: this.player,
asRatio: this.videoRatio,
})
// 5.使用NodeContainer结合CcGestureOverlay默认手势面板
NodeContainer(this.gestureOverlay)
// 6.参照上面的手势Overlay使用其他Overlay进行组合
}
.width(400)
.height(300)
.clip(true)
// play actions
Button("play")
.onClick(() => {
this.play()
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
private async play() {
// 7.创建mediaSource
let src = await MediaSourceFactory.createFile(getContext(this).filesDir + "/test.mp4", "test.mp4")
// 8.设置mediaSource
this.player!.setMediaSource(src, () => {
// 9.设置成功回调,开始播放
this.player.start()
})
}
aboutToDisappear() {
// 10.释放资源
this.player.release()
}
}
```
- 使用 CcPlayer 播放视频的方式:
```typescript
@Entry
@Component
struct PlayerViewPage {
private controller = new XComponentController()
// 1.实例化CcPlayer
private player = new CcPlayer(getContext(this))
build() {
Column() {
// render surface
XComponent({
type: "surface",
id: "video",
controller: this.controller
}).onLoad(() => {
let surfaceId = this.controller.getXComponentSurfaceId()
// 2.设置surface,播放前必须设置
this.player.setSurface(surfaceId)
})
.width(400)
.height(300)
// play actions
Button("play")
.onClick(() => {
this.play()
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
private async play() {
// 3.创建mediaSource
let src = await MediaSourceFactory.createFile(getContext(this).filesDir + "/test.mp4", "test.mp4")
// 4.设置mediaSource
this.player.setMediaSource(src, () => {
// 5.设置成功回调,开始播放
this.player.start()
})
}
aboutToDisappear() {
// 6.释放资源
this.player.release()
}
}
```
- 使用 CcPlayer 播放音乐的方式:
```typescript
@Entry
@Component
struct PlayerViewPage {
// 1.实例化CcPlayer
private player = new CcPlayer(getContext(this))
build() {
Column() {
// play actions
Button("play")
.onClick(() => {
this.play()
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
private async play() {
// 2.创建mediaSource
let src = await MediaSourceFactory.createFile(getContext(this).filesDir + "/test.mp3", "test.mp3")
// 3.设置mediaSource
this.player.setMediaSource(src, () => {
// 4.设置成功回调,开始播放
this.player!.start()
})
}
aboutToDisappear() {
// 5.释放资源
this.player.release()
}
}
```
- 使用 CcPlayerView 结合 CcPlayerPool 进行页面上下滑动切换播放(预加载快速启播):
```typescript
// 主页面
@Component
export struct PagePlayerSample {
private dataList = new DataProvider() //懒加载数据源
@State curIndex: number = 0
private playerPool: CcPlayerPool = CcPlayerPool.getInstance()
aboutToAppear(): void {
// 初始化缓存池
this.playerPool.init(getContext(this), 4)
// 添加mock数据
this.dataList.uriList.push('video1.mp4')
this.dataList.uriList.push('video2.mp4')
this.dataList.uriList.push('video3.mp4')
this.dataList.uriList.push('video4.mp4')
this.dataList.uriList.push('video5.mp4')
}
aboutToDisappear(): void {
// 销毁缓存池
this.playerPool.destroy()
}
build() {
NavDestination() {
Swiper() {
LazyForEach(this.dataList, (uri: string, index: number) => {
VideoItemPageView({
uri: uri,
pageIndex: index,
curPageIndex: this.curIndex
})
})
}
.width('100%')
.height('100%')
.vertical(true) //设置垂直滑动
.loop(true) //设置可循环滑动
.cachedCount(1) //设置缓存量
.duration(300)
.onAnimationStart((_, targetIndex) => { //刷新当前滑动结束的页面索引
this.curIndex = targetIndex
})
}
.width('100%')
.height('100%')
.title("PagePlayerSample")
}
}
```
```typescript
// 单个子页面
@Component
struct VideoItemPageView {
// 每个page页面从缓存池中获取播放器实例,进行视频播放
private player = CcPlayerPool.getInstance().get()
pageIndex: number = 0 //自身索引
uri: string = "" //媒体资源uri
@Watch('onPageChanged') @Prop curPageIndex: number = 0 // 父组件传递过来,当前页面索引
@State ratio: AspectRatio = AspectRatio.AUTO
onPageChanged() {
if (this.curPageIndex == this.pageIndex) { //索引变化,如果当前页面显示,直接开启播放
this.player.start()
} else {
if (this.player.isPlaying()) { //索引变化,如果当前页面隐藏且正在播放,直接暂停播放
this.player.pause()
}
}
}
aboutToDisappear(): void {
// 通知缓存池进行播放器实例回收
CcPlayerPool.getInstance().recycle(this.player)
}
build() {
Stack() {
CcPlayerView({
player: this.player,
asRatio: this.ratio,
renderType: XComponentType.SURFACE,
isSupportGesture: false,
onSurfaceCreated: () => { //在该回调中,提前预加载资源
let src = MediaSourceFactory.createAssets('', this.uri)
this.player.setMediaSource(src, () => {
if (this.curPageIndex == this.pageIndex) { //如果当前页面显示,则开启播放,否则仅预加载资源
this.player.start()
}
})
}
}).width('100%')
.height('100%')
}
.width('100%')
.height('100%')
}
}
```
- 使用 CcPlayer 获取本地文件缩略图,仅支持视频文件,部分编码格式的视频文件可能获取失败:(注意:该方法不支持在开始播放流程之后调用(包括MediaSourceFactory创建资源),因为获取缩略图会操作媒体文件,播放过程不允许和播放器同时操作同一个文件)
```typescript
@Entry
@Component
struct PlayerViewPage {
@State snapshot?: PixelMap = undefined
// 1.实例化CcPlayer
private player = new CcPlayer(getContext(this))
build() {
Column() {
Image(this.snapshot ? this.snapshot : $r('app.media.app_icon'))
.objectFit(ImageFit.Cover)
.width(200)
.height(150)
Button("getSnapshot")
.onClick(() => {
// 注意:该方法不支持在开始播放流程之后调用,因为获取缩略图会操作媒体文件,播放过程不允许和播放器同时操作同一个文件
// 2.从raw文件获取缩略图
this.player.getSnapshotFromAssets('video1.mp4', 200, 150, 1500)
.then((result: PixelMap) => {
this.snapshot = result
})
// 从file文件获取调用该接口:getSnapshotFromFile
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
```
- 使用 IjkPlayer 插件播放网络视频
``` typescript
@Entry
@Component
struct IjkSample {
// 1.实例化CcPlayer
private player: CcPlayer = new CcPlayer(getContext(this))
// 2.实例化controller
private controller = new XComponentController()
aboutToAppear(): void {
// 3.设置插件
const ijkPlayer = new IjkPlayer()
this.player.setPlayer(ijkPlayer)
}
build() {
Column() {
Stack() {
XComponent({
controller: this.controller,
type: XComponentType.SURFACE,
id: IjkPlayer.getXComponentId(), // 4.需要绑定插件的id
libraryname: IjkPlayer.getLibrary(), // 5.需要绑定插件的so名
}).onLoad((context) => {
Logger.d(TAG, "onLoad= " + context)
if (context) {
// 6.绑定surface
this.player.bindXComponent(this.controller, context)
}
})
}
.width(400)
.height(300)
.clip(true)
// play actions
Button("play")
.onClick(() => {
this.play()
})
}
.width("100%")
.height("100%")
.justifyContent(FlexAlign.Center)
}
private async play() {
// 7.创建mediaSource
const source = MediaSourceFactory.createUrl("", "https:xxx.mp4")
// 8.设置source
this.player.setMediaSource(source)
// 9.开始播放
this.player.start()
}
aboutToDisappear() {
// 10.释放资源
this.player.release()
}
}
```
更多使用场景和示例,例如自定义手势操作 UI,播放器状态事件监听,绑定播控中心等,类似抖音的列表预加载播放,可以参考本库代码仓的 entry 示例工程:
https://github.com/seagazer/ccplayer
使用过程中存在任何相关问题欢迎各位开发者提Issue和PR,或者加群反馈(Q群:1051643574),欢迎大家一起共建完善该库,如果觉得对你有用,请给个star鼓励一下谢谢。