# Gsy Kernel Switch

> 在 IJK / System / ExoPlayer2(Media3) / Aliyun 四个媒体内核之间自由切换，以及自定义 Manager 的方法。

- Skill: `carguo/gsy-kernel-switch` (Agent Skill)
- Install (CLI): `npx skillmds@latest add carguo/gsy-kernel-switch`
- Raw SKILL.md: https://api.skillmd.com/api/skills/carguo/gsy-kernel-switch/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: carguo (https://skillmd.com/u/carguo)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/carguo/gsy-kernel-switch

---


# gsy-kernel-switch

## 内核矩阵

| Kernel | Class | 来源模块 | 特点 |
|---|---|---|---|
| **IJK**（默认） | [IjkPlayerManager](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/player/IjkPlayerManager.java) | `gsyVideoPlayer-java` + `armv*/ex_so` | ffmpeg 全格式；so ~15 MB/ABI；软/硬解双通道 |
| **System** | [SystemPlayerManager](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/player/SystemPlayerManager.java) | `gsyVideoPlayer-java` | 无 so；靠 `android.media.MediaPlayer`；直播/复杂容器兼容差 |
| **Exo/Media3** | `GSYExoPlayerManager`（Demo 内）／`GSYExo2MediaPlayer` | `gsyVideoPlayer-exo_player2` | DASH / HLS / SmoothStreaming / TrackSelection |
| **Aliyun** | [AliPlayerManager](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-aliplay/src/main/java/com/shuyu/aliplay/AliPlayerManager.java) | `gsyVideoPlayer-aliplay` | 阿里云 vid/authInfo；HLS 加密 |

## 切换 API

**全局切换**：`PlayerFactory.setPlayManager(Class<? extends IPlayerManager>)`（内部 `getPlayManager` 用 `sPlayerManager.newInstance()` 反射构造，故被切入的类**必须**有 `public` 无参构造）。见 [PlayerFactory#L15-L27](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/player/PlayerFactory.java#L15-L27) 与本仓库 R8 保留规则 [proguard-rules.pro](file:///D:/workspace/project/GSYVideoPlayer/app/proguard-rules.pro)。

```java
// Exo
PlayerFactory.setPlayManager(Exo2PlayerManager.class);
CacheFactory.setCacheManager(ExoPlayerCacheManager.class);

// System
PlayerFactory.setPlayManager(SystemPlayerManager.class);

// Aliyun
PlayerFactory.setPlayManager(AliPlayerManager.class);
```

必须在 `player.setUp(...)` **之前**调用；否则本次实例仍用旧内核。

## `IPlayerManager` 抽象

统一接口见 [IPlayerManager](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-base/src/main/java/com/shuyu/gsyvideoplayer/player/IPlayerManager.java)。核心方法（子类必须实现）：

| 方法 | 说明 |
|---|---|
| `initVideoPlayer(Context, Message, List<VideoOptionModel>, ICacheManager)` | 初始化内核；`Message.obj` 是 `GSYModel` |
| `showDisplay(Message)` | 绑定 Surface / SurfaceHolder |
| `setSpeed(float, boolean soundTouch)` | 速率 + 变速不变调 |
| `setNeedMute(boolean)` | 静音 |
| `setVolume(float, float)` | 双通道音量 |
| `getMediaPlayer()` | 底层 player 实例 |
| `isSurfaceSupportLockCanvas()` | 是否支持 `lockCanvas`（TextureView 补帧） |
| `start / pause / stop / seekTo / release / getCurrentPosition / getDuration / getVideoSarNum / getVideoSarDen / getVideoWidth / getVideoHeight` | 基础控制 |

推荐继承 [BasePlayerManager](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-base/src/main/java/com/shuyu/gsyvideoplayer/player/BasePlayerManager.java) 以少写模板。

## `IPlayerInitSuccessListener` hook

[IPlayerInitSuccessListener](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-base/src/main/java/com/shuyu/gsyvideoplayer/player/IPlayerInitSuccessListener.java) 允许在 `initVideoPlayer` 完成后对底层 Player 拿手（比如设置 Exo 的 TrackSelector）：

```java
IjkPlayerManager.setIjkLibLoader(...);
// 或
GSYExoVideoManager.setPlayerInitSuccessListener(new IPlayerInitSuccessListener() {
    @Override public void onPlayerInitSuccess(IMediaPlayer mp, GSYModel model) { ... }
});
```

## `CacheFactory` 同步切换

不同内核有各自缓存方案；切内核记得配套：

| Player Manager | 对应 CacheManager |
|---|---|
| `IjkPlayerManager` / `SystemPlayerManager` | [ProxyCacheManager](file:///D:/workspace/project/GSYVideoPlayer/gsyVideoPlayer-java/src/main/java/com/shuyu/gsyvideoplayer/cache/ProxyCacheManager.java)（默认） |
| Exo/Media3 | `ExoPlayerCacheManager`（`gsyvideoplayer-exo_player2` 内） |
| Aliyun | 由 Aliyun SDK 自身管理，一般 `CacheFactory` 保持 `ProxyCacheManager` 或自定义空实现 |

## 多实例并行

用 [CustomManager](file:///D:/workspace/project/GSYVideoPlayer/app/src/main/java/com/example/gsyvideoplayer/video/manager/CustomManager.java) 模式：拷贝 `GSYVideoManager` 单例套壳，在自定义 `GSYVideoView` 里覆盖 `getGSYVideoManager()`；不同页面互不影响，参考 [MultiSampleVideo](file:///D:/workspace/project/GSYVideoPlayer/app/src/main/java/com/example/gsyvideoplayer/video/MultiSampleVideo.java) + [ListMultiVideoActivity](file:///D:/workspace/project/GSYVideoPlayer/app/src/main/java/com/example/gsyvideoplayer/ListMultiVideoActivity.java)。

## Demo 对照

- Exo 切源 / 无缝切换：[DetailExoListPlayer](file:///D:/workspace/project/GSYVideoPlayer/app/src/main/java/com/example/gsyvideoplayer/exo/DetailExoListPlayer.java)、[ExoAdaptiveTrackActivity](file:///D:/workspace/project/GSYVideoPlayer/app/src/main/java/com/example/gsyvideoplayer/exo/ExoAdaptiveTrackActivity.java)
- MediaCodec 智能回退：[SmartMediaCodecFallbackActivity](file:///D:/workspace/project/GSYVideoPlayer/app/src/main/java/com/example/gsyvideoplayer/SmartMediaCodecFallbackActivity.java) + [doc/SMART_MEDIACODEC_FALLBACK_RESEARCH.md](file:///D:/workspace/project/GSYVideoPlayer/doc/SMART_MEDIACODEC_FALLBACK_RESEARCH.md)

## 常见坑

- `PlayerFactory.setPlayManager` 传入的类**必须**有 `public` 无参构造，且被 ProGuard 保留。
- Exo 切源建议用 `Exo2PlayerManager` + `GSYExo2MediaPlayer`；直接换 Manager 但用 Ijk 的 URL 会走缓存代理导致 DASH 解析失败——记得 `setOverrideExtension("mpd")` 或关闭缓存。
- 系统内核 `SystemPlayerManager` 不支持 `soundTouch`、多数直播格式；生产环境仅作 fallback。

