ywl5320
wlmedia
Java

Android&HarmonyOS Next 音视频播放器SDK,几句代码即可实现音视频播放功能(支持:手机、车机系统、电视盒子等设备。支持:http、https、rtsp、rtp、rtmp、byte[]、加密视频和各种文件格式视频;包含视频截图、音轨选择、字幕选择、循环播放、设置软解或硬解、透明视频、变速变调、声道切换、无缝切换surface、多Surface渲染、视频比例设置、多实例音视频播放等。)~

Last updated Jul 3, 2026
837
Stars
163
Forks
0
Issues
+1
Stars/day
Attention Score
88
Language breakdown
Java 84.4%
TypeScript 15.6%
Files click to expand
README

🚀wlmedia🚀 English 中文

Android&HarmonyOS Next 音视频播放SDK,几句代码即可实现音视频播放功能~

使用简单,功能丰富,支持手机、车机系统、电视、电视盒子、手表等智能设备

源码可售,有意请联系:ywl5320@163.com

一 功能&特点

  • [x] 基本信息获取(音频:采样率、声道数、时长等,视频:宽、高、fps、时长等)
  • [x] 支持file、http、https、udp、rtmp、rtp、rtsp、byte[]等几乎所有协议
  • [x] 支持AV1解码
  • [x] 可选音频、视频、音视频播放模式
  • [x] 软解硬解设置
  • [x] 无缝切换surface
  • [x] 支持多实例播放
  • [x] 支持播放完成(EOF)后,再次seek又继续播放
  • [x] 支持媒体自由切换
  • [x] 支持FFmpeg参数设置
  • [x] 支持byte[]数据类型
  • [x] 音视频加密播放
  • [x] 支持音视频帧解码
  • [x] 支撑音视频变速变调
  • [x] 支撑透明视频播放(可实现不错的视觉效果)
  • [x] 字幕选择
  • [x] 内置循环播放
  • [x] 链接超时设置
  • [x] 缓存大小设置(时间维度)
  • [x] 音轨选择
  • [x] 音频指定采样率设置
  • [x] 音频指定声道播放
  • [x] 视频截屏
  • [x] 视频首帧图片或指定时间图片获取
  • [x] 视频任意比例设置
  • [x] 视频旋转角度设置(0,90,180,270)
  • [x] 视频镜像模式设置
  • [x] 视频背景颜色设置(默认黑色)
  • [x] 视频支持同时多个surface渲染(如:KTV大小屏幕)
  • [x] 支持实时获取音频PCM数据
  • [x] 支持设置音视频同步偏移
  • [x] 支持外部OpenGL渲染(如:Unity、Cocos2d等视频播放)

二 效果展示

Android

| 常规播放 | 透明视频 | 多Surface渲染 | 多实例播放 | 播放音频 | 音量分贝 | | :----: | :----: | :----: | :----: |:----:| ------ | | | | | | | |

HarmonyOS

| 常规播放 | 透明视频 | 多Surface渲染 | 多实例播放 | 播放音频 | 音量分贝 | | :----: | :----: | :----: | :----: |:----:| ------ | | | | | | | |

三 性能对比

Android

VS exoplayer

  • 设备:Xiaomi Redmi Note 7
  • 资源:bigbuckbunny_cut.mp4
| exoplayer | wlplayer(no opengl) | wlplayer(use opengl) | wlplayer 实时| | :----: | :----: | :----: | :----: | | | | | |

四 集成使用

4.1 Android

4.1.1 gradle

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
    
dependencies {
        implementation 'com.github.ywl5320:wlmedia:4.2.0'
}
#### 4.1.2 常用权限
<uses-permission android:name="android.permission.READEXTERNALSTORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>

#### 4.1.3 配置NDK编译平台

defaultConfig {     ...     ndk {         abiFilter("armeabi-v7a")         abiFilter("arm64-v8a")         abiFilter("x86")         abiFilter("x86_64")         } ... }
#### 4.1.4 设置Surface
<-- WlSurfaceView 一般播放使用 -->  <com.ywl5320.wlmedia.widget.WlSurfaceView      android:id="@+id/wlsurfaceview"      android:layoutwidth="matchparent"      android:layoutheight="matchparent" />

<-- WlTextureView 需要做透明、移动、旋转等使用 --> <com.ywl5320.wlmedia.widget.WlTextureView android:id="@+id/wltextureview" android:layoutwidth="matchparent" android:layoutheight="matchparent" />

#### 4.1.5 基础调用代码(更多功能见Demo)
// 1.创建播放器  WlPlayer wlPlayer = new WlPlayer();  wlPlayer.setOnMediaInfoListener(new WlOnMediaInfoListener() {     @Override     public void onPrepared() {         // 异步准备好后回调,这里调用 wlplayer.start() 开始播放         wlPlayer.start();     }

@Override public void onTimeInfo(double currentTime, double bufferTime) { // 时间进度回调 }

@Override public void onComplete(WlCompleteType wlCompleteType, String s) { // 播放完成回调,根据 WlCompleteType 区分对应类型 if (wlCompleteType == WlCompleteType.WLCOMPLETEEOF) { // 正常播放完成 } else if (wlCompleteType == WlCompleteType.WLCOMPLETEERROR) { // 播放出错,原因为:msg 字段 } else if (wlCompleteType == WlCompleteType.WLCOMPLETEHANDLE) { // 主动调用 wlPlayer.stop() 会回调此类型 } else if (wlCompleteType == WlCompleteType.WLCOMPLETENEXT) { // 正在播放中,切换了新的数据源,会回调此类型 } else if (wlCompleteType == WlCompleteType.WLCOMPLETETIMEOUT) { // 播放超时,会回调此接口 } else if (wlCompleteType == WlCompleteType.WLCOMPLETELOOP) { // 循环播放中,每开始新的一次循环,会回调此接口 } }

@Override public void onLoad(WlLoadStatus loadStatus, int progress, long speed) { // 加载状态回调 if (wlLoadStatus == WlLoadStatus.WLLOADINGSTATUS_START) { // 开始加载 } else if (wlLoadStatus == WlLoadStatus.WLLOADINGSTATUS_PROGRESS) { // 加载进度 } else if (wlLoadStatus == WlLoadStatus.WLLOADINGSTATUS_FINISH) { // 加载完成 } }

@Override public void onSeekFinish() { // seek 完成回调 }

@Override public void onFirstFrameRendered() { // 首帧渲染回调 } });

// 2.获取 WlSurfaceView 并绑定播放器 WlSurfaceView wlSurfaceView = findViewById(R.id.wlsurfaceview); wlSurfaceView.setWlPlayer(wlPlayer); // 可选 wlSurfaceView.setClearLastVideoFrame(false); // 设置不清屏 wlSurfaceView.setVideoScale(WlScaleType.WLSCALEFIT); // 设置缩放模式 wlSurfaceView.setVideoRotate(WlRotateType.WLROTATE90); // 设置旋转角度 wlSurfaceView.setVideoMirror(WlMirrorType.WLMIRRORTOP_BOTTOM); // 设置镜像模式

// 3.设置数据源异步准备 wlPlayer.setSource(url); wlPlayer.prepare();

更多使用方式

4.2 HarmonyOS Next

4.2.1 导入SDK 仓库地址

ohpm i @ywl5320/libwlmedia

4.2.2 常用权限

#module.json5 "requestPermissions": [     {     "name": "ohos.permission.INTERNET"     } ]

4.2.3 设置XComponentController

let wlPlayer: WlPlayer = new WlPlayer();
let wlComponentController: WlComponentController = new WlComponentController(this.wlPlayer);
...
XComponent({
        type: XComponentType.SURFACE,
        controller: this.wlComponentController
    })
    .width('100%')
    .height('100%')
...

4.2.4 基础调用代码(更多功能见Demo)

@Entry
@Component
struct Index{
    private wlPlayer: WlPlayer | null = null;
    private wlComponentController: WlComponentController | null = null;

aboutToAppear(): void { this.wlPlayer = new WlPlayer(); this.wlPlayer.setOnMediaInfoListener({ onPrepared: (): void => { // 异步准备好后回调,这里调用 wlplayer.start() 开始播放 this.wlPlayer?.start(); }, onTimeInfo: (currentTime: number, bufferTime: number): void => { // 时间进度回调 }, onComplete: (wlCompleteType: WlCompleteType, msg: string): void => { if (wlCompleteType == WlCompleteType.WLCOMPLETEEOF) { // 正常播放完成 } else if (wlCompleteType == WlCompleteType.WLCOMPLETEERROR) { // 播放出错,原因为:msg 字段 } else if (wlCompleteType == WlCompleteType.WLCOMPLETEHANDLE) { // 主动调用 wlPlayer.stop() 会回调此类型 } else if (wlCompleteType == WlCompleteType.WLCOMPLETENEXT) { // 正在播放中,切换了新的数据源,会回调此类型 } else if (wlCompleteType == WlCompleteType.WLCOMPLETETIMEOUT) { // 播放超时,会回调此接口 } else if (wlCompleteType == WlCompleteType.WLCOMPLETELOOP) { // 循环播放中,每开始新的一次循环,会回调此接口 } }, onLoadInfo: (loadStatus: WlLoadStatus, progress: number, speed: number): void => { // 加载状态回调 if (wlLoadStatus == WlLoadStatus.WLLOADINGSTATUS_START) { // 开始加载 } else if (wlLoadStatus == WlLoadStatus.WLLOADINGSTATUS_PROGRESS) { // 加载进度 } else if (wlLoadStatus == WlLoadStatus.WLLOADINGSTATUS_FINISH) { // 加载完成 } }, onFirstFrameRendered: (): void => { // seek 完成回调 }, onSeekFinish: (): void => { // seek 完成回调 }, onAudioInterrupt: (type: WlAudioInterruptType, hint: WlAudioInterruptHint) => { // 音频打断,和系统一致 } this.wlComponentController = new WlComponentController(this.wlPlayer); this.wlPlayer.setClearLastVideoFrame(this.wlComponentController.getUniqueNum(), false); }

// 退出 销毁资源 onBackPress(): boolean | void { this.wlPlayer?.release() }

build() { Column() { XComponent({ type: XComponentType.SURFACE, controller: this.wlComponentController }) .onLoad((event) => { // 加载完成后就开始播放 this.wlPlayer?.setSource(this.filesDir + "/huoying_cut.mkv"); this.wlPlayer?.prepare(); }) .width('100%') .height('100%') } } }

更多使用方式

五 免费和增值服务

WlMedia 是按应用根据 包名 定制的,分免费版和付费定制版

免费版

  • HarmonyOS Next鸿蒙平台免费
  • 仅Android平台视频画面带有wlmedia水印,其余功能无限制

增值版

  • 如要定制去水印,可付费根据包名定制打包,具体费用和规则请邮件联系:
- 邮箱:ywl5320@163.com

六 讨论群(1085618246)

QQ

七 核心三方库

Update By:ywl5320 2025-04-05

Create By:ywl5320 2019-12-16

© 2026 GitRepoTrend · ywl5320/wlmedia · Updated daily from GitHub