HarmonyOS APP开发---"刷刷"短视频App,需要用到这个库
想做一个短视频 App,上下滑动切换视频、支持倍速、还能拉 RTMP 直播流?系统播放器搞不定冷门编码和直播协议------
@ohos/ijkplayer把 B 站同源播放器搬进了鸿蒙,FFmpeg 内核,啥格式都能播。
📦 仓库地址:https://gitcode.com/CPF-ApplicationTPC/ohos_ijkplayer | 安装:ohpm install @ohos/ijkplayer
写在前面
"刷刷"的核心体验是"滑到就播"------用户上滑切换下一条视频,几乎无感知地开始播放。这背后对播放器的要求很高:
- 首帧要快:滑到新视频,500ms 内出画面,不然用户觉得卡
- 格式要全:MP4、FLV、HLS、甚至 RTMP 直播流都要能播
- 硬解码:省电不发烫,长时间刷不热
- 倍速播放:1.5x/2x 看视频是刚需
系统 AVPlayer 对直播流(RTMP/RTSP)和部分编码支持不全。ijkplayer 是 B 站开源的、基于 FFmpeg 的播放器,久经亿级 DAU 考验,@ohos/ijkplayer 是它在 OpenHarmony 上的官方移植。
这篇文章聊什么
- 播放器初始化------XComponent + IjkMediaPlayer 接入渲染
- 上下滑动切换------列表 + 播放器复用
- 倍速 + 截图------进阶控制能力
#mermaid-svg-cq1F1LnDnkG9DsTz{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cq1F1LnDnkG9DsTz .error-icon{fill:#552222;}#mermaid-svg-cq1F1LnDnkG9DsTz .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cq1F1LnDnkG9DsTz .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cq1F1LnDnkG9DsTz .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cq1F1LnDnkG9DsTz .marker.cross{stroke:#333333;}#mermaid-svg-cq1F1LnDnkG9DsTz svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cq1F1LnDnkG9DsTz p{margin:0;}#mermaid-svg-cq1F1LnDnkG9DsTz .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz .cluster-label text{fill:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz .cluster-label span{color:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz .cluster-label span p{background-color:transparent;}#mermaid-svg-cq1F1LnDnkG9DsTz .label text,#mermaid-svg-cq1F1LnDnkG9DsTz span{fill:#333;color:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz .node rect,#mermaid-svg-cq1F1LnDnkG9DsTz .node circle,#mermaid-svg-cq1F1LnDnkG9DsTz .node ellipse,#mermaid-svg-cq1F1LnDnkG9DsTz .node polygon,#mermaid-svg-cq1F1LnDnkG9DsTz .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cq1F1LnDnkG9DsTz .rough-node .label text,#mermaid-svg-cq1F1LnDnkG9DsTz .node .label text,#mermaid-svg-cq1F1LnDnkG9DsTz .image-shape .label,#mermaid-svg-cq1F1LnDnkG9DsTz .icon-shape .label{text-anchor:middle;}#mermaid-svg-cq1F1LnDnkG9DsTz .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cq1F1LnDnkG9DsTz .rough-node .label,#mermaid-svg-cq1F1LnDnkG9DsTz .node .label,#mermaid-svg-cq1F1LnDnkG9DsTz .image-shape .label,#mermaid-svg-cq1F1LnDnkG9DsTz .icon-shape .label{text-align:center;}#mermaid-svg-cq1F1LnDnkG9DsTz .node.clickable{cursor:pointer;}#mermaid-svg-cq1F1LnDnkG9DsTz .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cq1F1LnDnkG9DsTz .arrowheadPath{fill:#333333;}#mermaid-svg-cq1F1LnDnkG9DsTz .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cq1F1LnDnkG9DsTz .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cq1F1LnDnkG9DsTz .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cq1F1LnDnkG9DsTz .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cq1F1LnDnkG9DsTz .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cq1F1LnDnkG9DsTz .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cq1F1LnDnkG9DsTz .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cq1F1LnDnkG9DsTz .cluster text{fill:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz .cluster span{color:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cq1F1LnDnkG9DsTz .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cq1F1LnDnkG9DsTz rect.text{fill:none;stroke-width:0;}#mermaid-svg-cq1F1LnDnkG9DsTz .icon-shape,#mermaid-svg-cq1F1LnDnkG9DsTz .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cq1F1LnDnkG9DsTz .icon-shape p,#mermaid-svg-cq1F1LnDnkG9DsTz .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cq1F1LnDnkG9DsTz .icon-shape .label rect,#mermaid-svg-cq1F1LnDnkG9DsTz .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cq1F1LnDnkG9DsTz .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cq1F1LnDnkG9DsTz .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cq1F1LnDnkG9DsTz :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 视频列表
用户上滑
停止当前播放
复用 IjkMediaPlayer
setDataSource 新 URL
prepareAsync
onPrepared 回调
start 播放
首帧渲染
用户可操作: 倍速/暂停/截图
第一步:安装与权限
bash
ohpm install @ohos/ijkplayer
json
"requestPermissions": [
{ "name": "ohos.permission.INTERNET", "reason": "$string:NET_REASON" }
]
第二步:播放器与 XComponent 集成
ijkplayer 通过 XComponent 接入 ArkUI 渲染管线:
typescript
import { IjkMediaPlayer, OnPreparedListener, OnErrorListener } from '@ohos/ijkplayer'
@Entry
@Component
struct VideoFeedPage {
@State currentUrl: string = 'https://cdn.example.com/video_001.mp4'
private player = IjkMediaPlayer.getInstance()
build() {
Stack() {
XComponent({
id: 'player-surface',
type: 'SURFACE',
libraryname: 'ijkplayer_napi',
controller: this.player.getSurfaceController()
})
.onLoad(() => this.prepareAndPlay())
.width('100%').height('100%')
}
}
private prepareAndPlay() {
this.player.setOnPreparedListener(() => {
this.player.start() // 准备完成,开始播放
})
this.player.setOnErrorListener((what, extra) => {
console.error(`播放错误: what=${what} extra=${extra}`)
})
this.player.setDataSource(this.currentUrl)
this.player.prepareAsync()
}
}
第三步:上下滑动切换视频
用户上滑,切换到下一条视频,复用同一个播放器实例:
typescript
private videoList: string[] = [
'https://cdn.example.com/video_001.mp4',
'https://cdn.example.com/video_002.mp4',
'https://cdn.example.com/video_003.flv',
]
private currentIndex: number = 0
// 上滑切换下一条
onSwipeUp() {
this.player.stop()
this.player.reset() // 重置播放器状态
this.currentIndex++
if (this.currentIndex >= this.videoList.length) {
this.currentIndex = 0
}
this.currentUrl = this.videoList[this.currentIndex]
this.player.setDataSource(this.currentUrl)
this.player.prepareAsync()
// onPrepared 回调里会自动 start
}
reset() 是关键------它清空上一条视频的状态,但不销毁播放器实例,避免了反复创建/销毁的开销,首帧速度更快。
第四步:倍速、暂停、截图
typescript
// 倍速播放(API 12+)
setSpeed(speed: number) {
this.player.setSpeed(speed) // 0.5 / 1.0 / 1.5 / 2.0
}
// 暂停/继续
togglePlay() {
if (this.isPlaying) {
this.player.pause()
} else {
this.player.start()
}
this.isPlaying = !this.isPlaying
}
// 截图(保存到相册)
captureFrame() {
this.player.capture(async (path) => {
if (path) {
console.info('截图已保存: ' + path)
promptAction.showToast({ message: '截图已保存到相册' })
}
})
}
第五步:拉直播流
ijkplayer 不只能播点播,RTMP/HLS/RTSP 直播流也行:
typescript
// RTMP 直播流
this.player.setDataSource('rtmp://live.example.com/live/stream_001')
this.player.prepareAsync()
// HLS 直播流
this.player.setDataSource('https://live.example.com/hls/stream_001.m3u8')
this.player.prepareAsync()
系统播放器对 RTMP 支持有限,而 ijkplayer 底层是 FFmpeg,RTMP/RTSP/HLS 全覆盖。
为什么"刷刷"选了 ijkplayer?
| 需求 | 系统 AVPlayer | @ohos/ijkplayer |
|---|---|---|
| 点播 MP4 | ✅ | ✅ |
| FLV/MKV 冷门格式 | ❌ | ✅ FFmpeg 内核 |
| RTMP/RTSP 直播 | ❌ 部分 | ✅ 全支持 |
| 硬解码 | ✅ | ✅ 自动启用 |
| 倍速播放 | ✅ | ✅ |
| 截图 | ❌ | ✅ |
| B 站验证 | ❌ | ✅ 亿级 DAU |
总结
"刷刷"这个场景里,@ohos/ijkplayer 解决了三件事:
- 快速切换 ------
reset()复用实例,上滑切换首帧快 - 全格式覆盖------点播 MP4/FLV + 直播 RTMP/HLS 都能播
- 进阶控制------倍速、截图、音量,API 齐全
如果你也在做短视频、直播、在线教育等视频播放类 App,@ohos/ijkplayer 的 FFmpeg 内核给你最大兼容性,B 站同源给你最大信心。