# JZVideo (Jzvd) Review: A Customizable Android Video Framework With Swappable Media Engines

> JZVideo wraps MediaPlayer, ExoPlayer and ijkplayer behind one Android view, so you can change playback engines without rewriting your UI. It is a good fit for apps that need heavy UI customisation, and a poor fit for projects that expect frequent releases or a modern Media3 stack.

**Jzvd/JZVideo** — 高度自定义的安卓视频框架 MediaPlayer exoplayer ijkplayer ffmpeg

- Repository: https://github.com/Jzvd/JZVideo
- Stars: 3,013 · Forks: 542
- Language: Java
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/jzvd-jzvideo

## What JZVideo Solves, and Who It Is Built For

Android has never shipped a single answer for video playback. MediaPlayer is in the platform but limited; ExoPlayer covers formats MediaPlayer does not; ijkplayer wraps FFmpeg for streams the other two struggle with. An app that starts on one and later needs another usually ends up rewriting the view layer around it. JZVideo's pitch is that the view layer stays put and the engine underneath is replaceable. The README describes it as a "高度自定义的安卓视频框架", a highly customisable Android video framework, and the repository topics list MediaPlayer, exoplayer, ijkplayer and ffmpeg together, which is the whole argument in four words.

The audience is narrower than "Android developers". This is a Java library, the primary language of the repository is Java, and the API surface is built around Android View classes rather than Compose. If your app already has a player screen with a specific look (a poster image, a title bar, a fullscreen toggle, gesture controls) and you want to keep that look while changing what decodes the bytes, this is the shape of library you are looking for. If you are starting a greenfield app in Kotlin with Jetpack Compose and no legacy playback code, the cost of adopting a View-based framework is higher than the benefit.

## The Engine Abstraction Behind JzvdStd

The mechanism is visible in the README's own setup steps. You put a cn.jzvd.JzvdStd element in your layout XML, then in Java you call setUp with a video URL and a title, and set the poster image separately through posterImageView. The view owns the surface, the controls and the state machine; the media engine is a class behind it.

That indirection is why the proguard rules in the README name several media classes individually: cn.jzvd.JZMediaSystem for the platform MediaPlayer path, and custom classes such as CustomMedia and JZMediaIjk for other engines. The README's example keeps tv.danmaku.ijk.media.player classes as well, which is the ijkplayer namespace. In other words, the engine is a pluggable class, and the keep rules exist because obfuscation would otherwise strip classes that are only reached through that indirection. That is a real design decision with a real cost: every engine you enable adds its own transitive dependencies and its own proguard surface.

The lifecycle is also explicit rather than automatic. The README tells you to route the back button through Jzvd.backPress() and to call Jzvd.releaseAllVideos() from onPause. That is a static, global release call, which is convenient for a single-player screen and awkward if you ever want two players alive at once in different fragments.

## Installing JZVideo and Playing a First Video

The README gives a six-step QuickStart. Step one is the Gradle dependency. Add it to your module's build file:

```gradle
implementation 'cn.jzvd:jiaozivideoplayer:7.7.0'
```

The version string here matches the newest release listed for the project, v7.7.0, published 2021-06-29. There is no newer published artifact in the release list, so treat this coordinate as the current published version rather than as an example.

Step two is the layout. The README shows JzvdStd with a fixed height of 200dp:

```xml
<cn.jzvd.JzvdStd
    android:id="@+id/jz_video"
    android:layout_width="match_parent"
    android:layout_height="200dp" />
```

Step three binds a URL, a title and a poster image. The README's example uses a MyJzvdStd subclass, so replace that with JzvdStd unless you have created your own:

```java
JzvdStd jzvdStd = findViewById(R.id.jz_video);
jzvdStd.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4", "饺子闭眼睛");
jzvdStd.posterImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
```

After setUp, the view has a source and a title but does not start playing on its own. The poster image is set through the view's posterImageView, not through setUp, which is why the README treats them as two separate calls.

Step four is lifecycle wiring in the Activity, and step five is the manifest declaration. The README's manifest entry sets configChanges to orientation|screenSize|keyboardHidden and pins screenOrientation to portrait (or landscape). That combination matters: the activity handles its own rotation instead of being recreated, which is how the player survives a fullscreen toggle without losing position.

Step six is proguard. The README says to add the keep rules "按需添加", as needed, and lists JZMediaSystem plus the demo's custom media classes and the ijkplayer namespace. If you only ship the system player, you do not need the ijkplayer lines. The README also shows ./gradlew build -x androidJavadocs as the build command, which skips the Javadoc task.

## Where JZVideo Gets in the Way

The release history is the first limitation, and it is not a small one. The releases listed are v7.5.0 (2020-09-23), v7.6.0 (2020-12-26) and v7.7.0 (2021-06-29). The develop branch was pushed on 2026-03-26, so work has happened since, but none of it appears in a published release. Anyone depending on the Maven coordinate gets the 2021 artifact. Anyone wanting the newer code has to build from source or depend on a snapshot, and the README does not document a snapshot repository or a rollback path.

The second limitation is the lifecycle model. Jzvd.releaseAllVideos() is a static call that releases every player the library knows about. On a single-video screen that is exactly what you want. In a feed with several video cells, or in a ViewPager where two fragments can be resumed close together, a global release is a blunt instrument. The README does not describe a per-instance release API in the QuickStart, so the safe assumption is that you manage visibility and playback yourself.

The third is the engine choice itself. Supporting MediaPlayer, ExoPlayer and ijkplayer means the library carries an abstraction over three APIs with different capabilities. Format support, DRM support and error reporting are not uniform across them, and the README does not publish a compatibility matrix. If your content needs Widevine or a specific adaptive streaming profile, verify it against the engine you actually enable rather than against the framework as a whole.

## JZVideo Compared With ExoPlayer and Media3

The honest comparison is not JZVideo versus another wrapper, it is JZVideo versus using the engine directly. ExoPlayer, and now the Media3 ExoPlayer that Google publishes under the Media3 umbrella, gives you a player object and a PlayerView, with format support, DRM and track selection handled by the engine itself. The trade-off is symmetrical. With Media3 you get first-party maintenance and a current API, but you own the UI: custom controls, fullscreen transitions and poster handling are your code. With JZVideo you get the UI scaffolding and the engine swap for free, but you inherit a 2021 artifact and a View-based API.

Other Android wrappers exist in the same space, and the related searches around this project name several of them. The distinction that matters when comparing is what each one abstracts. A wrapper that only wraps ExoPlayer inherits ExoPlayer's format support and its release cadence, and gives up the ability to fall back to ijkplayer for a stream ExoPlayer cannot open. JZVideo's multi-engine design is precisely the reason its proguard rules are longer and its dependency graph is heavier. If you have never needed anything but ExoPlayer, that flexibility is cost without benefit.

## Licence and the Cost of Upgrading

The repository is MIT licensed, and the README carries the full text with a copyright line of "Copyright (c) 2015-2021 jzvd.io". MIT permits use, modification, distribution and sublicensing provided the copyright notice and permission notice are included in copies or substantial portions. That is a permissive arrangement, and it does not impose copyleft obligations on your app. It also means there is no commercial support contract implied, and no warranty: the licence text states the software is provided "AS IS", without warranty of any kind. This is a description of the licence, not legal advice; if your organisation has specific compliance requirements, have counsel review the notice you ship.

The upgrade cost is dominated by the engine, not by JZVideo. Because the library delegates decoding to MediaPlayer, ExoPlayer or ijkplayer, a security or compatibility fix in the underlying engine reaches you through that engine's own dependency, not through a JZVideo release. That is good in principle and awkward in practice: you are pinning two version lines, the framework's and the engine's, and the README does not state which engine versions the 7.7.0 artifact was built against. Expect to verify that combination yourself on each upgrade.

## Conclusion

Adopt JZVideo if you are shipping a Java-heavy Android app that needs a heavily customised player UI and you are willing to pin the playback engine yourself, starting from the Gradle coordinate cn.jzvd:jiaozivideoplayer:7.7.0 and the JzvdStd layout element. Do not adopt it if you need current Media3 APIs, Kotlin-first ergonomics, or a release cadence you can plan around: the newest release listed is v7.7.0 from 2021-06-29, even though the develop branch was pushed on 2026-03-26. Before committing, verify that your chosen engine still builds against your target SDK, that the proguard rules in the README cover your custom media class, and that the orientation handling in your manifest matches how your activity is declared.

## FAQ

### What is JZVideo (Jzvd) used for?

It is an Android video framework whose view layer can be paired with different playback engines, including the platform MediaPlayer, ExoPlayer and ijkplayer. The README describes it as a highly customisable Android video framework and its QuickStart shows a JzvdStd view with a URL, title and poster image.

### How do I install JZVideo in an Android project?

Add the Gradle dependency cn.jzvd:jiaozivideoplayer:7.7.0, place a cn.jzvd.JzvdStd element in your layout, and call setUp with the video URL and title. The README also requires routing the back button through Jzvd.backPress() and calling Jzvd.releaseAllVideos() from onPause.

### What is the latest version of JZVideo?

The newest release listed for the project is v7.7.0, published on 2021-06-29, and that is the version shown in the README's Gradle coordinate. The develop branch was pushed on 2026-03-26, but no release after v7.7.0 appears in the release list.

### Does JZVideo support ExoPlayer and ijkplayer?

The repository topics list MediaPlayer, exoplayer, ijkplayer and ffmpeg, and the README's proguard rules name JZMediaSystem alongside custom media classes and the tv.danmaku.ijk.media.player namespace. The README does not publish a compatibility matrix showing which formats or features each engine supports.

## Sources

- [Issues](https://github.com/Jzvd/JZVideo/issues)
- [Jzvd/JZVideo on GitHub](https://github.com/Jzvd/JZVideo)
- [License: MIT](https://github.com/Jzvd/JZVideo/blob/develop/LICENSE)
- [README](https://github.com/Jzvd/JZVideo/blob/develop/README.md)
- [Releases](https://github.com/Jzvd/JZVideo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jzvd-jzvideo
