VideoPlayerManager
This is a project designed to help controlling Android MediaPlayer class. It makes it easier to use MediaPlayer ListView and RecyclerView. Also it tracks the most visible item in scrolling list. When new item in the list become the most visible, this library gives an API to track it.
Top Related Projects
This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support.
视频播放器(IJKplayer、ExoPlayer、MediaPlayer),HTTPS,16k page size,支持 弹幕,外挂字幕,支持滤镜、水印、gif截图,片头广告、中间广告,多个同时播放,支持基本的拖动,声音、亮度调节,支持边播边缓存,支持视频自带rotation的旋转(90,270之类),重力旋转与手动旋转的同步支持,支持列表播放 ,列表全屏动画,视频加载速度,列表小窗口支持拖动,动画效果,调整比例,多分辨率切换,支持切换播放器,进度条小窗口预览,列表切换详情页面无缝播放,rtsp、concat、mpeg。
MediaPlayer exoplayer ijkplayer ffmpeg
An Android ExoPlayer wrapper to simplify Audio and Video implementations
Vitamio for Android
Quick Overview
VideoPlayerManager is an Android library that simplifies the management of multiple video players in a single view or RecyclerView. It handles the complexities of playing, pausing, and releasing video resources efficiently, especially when scrolling through a list of videos.
Pros
- Efficient management of multiple video players in a scrollable list
- Automatic handling of video playback states during scrolling
- Supports both single video view and RecyclerView implementations
- Customizable video player UI and controls
Cons
- Limited documentation and examples
- May require additional setup for more complex video playback scenarios
- Not actively maintained (last update was in 2017)
- Potential performance issues with a large number of video players
Code Examples
- Setting up a single video player:
val videoPlayerManager = SingleVideoPlayerManager(PlayerItemChangeListener())
val videoPlayerView = findViewById<VideoPlayerView>(R.id.video_player_view)
videoPlayerManager.playNewVideo(null, videoPlayerView, "https://example.com/video.mp4")
- Implementing a video player in a RecyclerView:
class VideoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val videoPlayerView: VideoPlayerView = itemView.findViewById(R.id.video_player_view)
}
override fun onBindViewHolder(holder: VideoViewHolder, position: Int) {
val videoItem = videoList[position]
videoPlayerManager.playNewVideo(null, holder.videoPlayerView, videoItem.videoUrl)
}
- Handling video player lifecycle:
override fun onResume() {
super.onResume()
videoPlayerManager.resumeCurrentVideo()
}
override fun onPause() {
super.onPause()
videoPlayerManager.pauseCurrentVideo()
}
override fun onDestroy() {
super.onDestroy()
videoPlayerManager.releaseAllVideos()
}
Getting Started
- Add the dependency to your
build.gradle
file:
dependencies {
implementation 'com.github.danylovolokh:video-player-manager:0.2.0'
}
- Initialize the VideoPlayerManager in your activity or fragment:
private lateinit var videoPlayerManager: SingleVideoPlayerManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
videoPlayerManager = SingleVideoPlayerManager(PlayerItemChangeListener())
}
- Use the VideoPlayerManager to play videos in your layout:
val videoPlayerView = findViewById<VideoPlayerView>(R.id.video_player_view)
videoPlayerManager.playNewVideo(null, videoPlayerView, "https://example.com/video.mp4")
Remember to handle the video player lifecycle in your activity or fragment's lifecycle methods as shown in the code examples above.
Competitor Comparisons
This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
Pros of ExoPlayer
- More comprehensive and feature-rich, supporting a wide range of media formats and streaming protocols
- Actively maintained by Google, ensuring regular updates and improvements
- Extensive documentation and community support
Cons of ExoPlayer
- Steeper learning curve due to its complexity and extensive feature set
- Larger library size, which may impact app size and performance
Code Comparison
VideoPlayerManager:
VideoPlayerManager videoPlayerManager = new VideoPlayerManager();
videoPlayerManager.playNewVideo(videoItem, videoView);
ExoPlayer:
SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build();
player.setMediaItem(MediaItem.fromUri(videoUri));
player.prepare();
player.play();
Key Differences
- VideoPlayerManager focuses on managing multiple video players in a list, while ExoPlayer is a more general-purpose media player
- ExoPlayer offers more advanced features like adaptive streaming and custom renderers
- VideoPlayerManager provides a simpler API for basic video playback scenarios
Use Cases
- Choose VideoPlayerManager for simpler projects with basic video playback needs, especially in scrollable lists
- Opt for ExoPlayer when building more complex media applications with advanced streaming requirements or custom playback features
Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support.
Pros of ijkplayer
- More comprehensive and feature-rich video player solution
- Supports a wider range of video formats and codecs
- Better performance for high-quality video playback
Cons of ijkplayer
- More complex to implement and integrate
- Larger library size, which may increase app size
- Steeper learning curve for developers
Code Comparison
VideoPlayerManager focuses on managing multiple video players:
VideoPlayerManager<MetaData> videoPlayerManager = new SingleVideoPlayerManager(new PlayerItemChangeListener() {
@Override
public void onPlayerItemChanged(MetaData metaData) {
// Handle player item change
}
});
ijkplayer provides lower-level control over video playback:
IjkMediaPlayer ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.setDataSource(videoPath);
ijkMediaPlayer.prepareAsync();
ijkMediaPlayer.start();
Summary
VideoPlayerManager is a simpler solution focused on managing multiple video players, while ijkplayer is a more comprehensive video player library with broader format support and lower-level control. VideoPlayerManager may be easier to implement for basic use cases, while ijkplayer offers more advanced features and better performance for complex video playback scenarios.
视频播放器(IJKplayer、ExoPlayer、MediaPlayer),HTTPS,16k page size,支持弹幕,外挂字幕,支持滤镜、水印、gif截图,片 头广告、中间广告,多个同时播放,支持基本的拖动,声音、亮度调节,支持边播边缓存,支持视频自带rotation的旋转(90,270之类),重力旋转与手动旋转的同步支持,支持列表播放 ,列表全屏动画,视频加载速度,列表小窗口支持拖动,动画效果,调整比例,多分辨率切换,支持切换播放器,进度条小窗口预览,列表切换详情页面无缝播放,rtsp、concat、mpeg。
Pros of GSYVideoPlayer
- More comprehensive feature set, including support for various video formats and streaming protocols
- Active development with frequent updates and bug fixes
- Extensive documentation and examples for easier implementation
Cons of GSYVideoPlayer
- Larger codebase and potentially higher complexity for simple use cases
- May have a steeper learning curve for developers new to video playback in Android
Code Comparison
VideoPlayerManager:
ItemsPositionGetter itemsPositionGetter = new RecyclerViewItemPositionGetter(mRecyclerView, layoutManager);
VideoPlayerManager<MetaData> videoPlayerManager = new SingleVideoPlayerManager(new PlayerItemChangeListener() {
@Override
public void onPlayerItemChanged(MetaData metaData) {
// Handle player item change
}
});
GSYVideoPlayer:
GSYVideoOptionBuilder gsyVideoOption = new GSYVideoOptionBuilder();
gsyVideoOption.setIsTouchWiget(true)
.setRotateViewAuto(false)
.setLockLand(false)
.setShowFullAnimation(false)
.setNeedLockFull(true)
.setSeekRatio(1f)
.build(videoPlayer);
Summary
GSYVideoPlayer offers a more feature-rich and actively maintained solution for video playback in Android applications. It provides extensive customization options and supports various video formats. However, this comes at the cost of increased complexity and a potentially steeper learning curve. VideoPlayerManager, on the other hand, may be simpler to implement for basic video playback needs but lacks some of the advanced features and ongoing development of GSYVideoPlayer.
MediaPlayer exoplayer ijkplayer ffmpeg
Pros of JiaoZiVideoPlayer
- More comprehensive feature set, including support for various video sources and formats
- Better documentation and examples, making it easier for developers to implement
- Active community and frequent updates, ensuring ongoing support and improvements
Cons of JiaoZiVideoPlayer
- Larger codebase and potentially higher complexity, which may impact app size and performance
- Less focused on specific use cases, potentially making it overkill for simpler video playback needs
Code Comparison
VideoPlayerManager:
VideoPlayerManager<MetaData> videoPlayerManager = new SingleVideoPlayerManager(new PlayerItemChangeListener() {
@Override
public void onPlayerItemChanged(MetaData metaData) {
// Handle player item change
}
});
JiaoZiVideoPlayer:
JzvdStd jzvdStd = findViewById(R.id.videoplayer);
jzvdStd.setUp("http://jzvd.nathen.cn/c6e3dc12a1154626b3476d9bf3bd7266/6b56c5f0dc31428083757a45764763b0-5287d2089db37e62345123a1be272f8b.mp4"
, "Title");
jzvdStd.posterImageView.setImage("http://p.qpic.cn/videoyun/0/2449_43b6f696980311e59ed467f22794e792_1/640");
The code comparison shows that JiaoZiVideoPlayer offers a more straightforward setup process with built-in UI components, while VideoPlayerManager focuses on managing video playback without providing a default UI.
An Android ExoPlayer wrapper to simplify Audio and Video implementations
Pros of ExoMedia
- Built on top of ExoPlayer, providing a more robust and feature-rich foundation
- Supports a wider range of media formats and streaming protocols
- Offers better customization options and easier integration with Android UI components
Cons of ExoMedia
- Larger library size due to ExoPlayer dependency
- May have a steeper learning curve for developers unfamiliar with ExoPlayer
- Potentially higher memory usage compared to VideoPlayerManager
Code Comparison
VideoPlayerManager:
val videoPlayerManager = VideoPlayerManager()
videoPlayerManager.playNewVideo(null, videoListItem)
ExoMedia:
val videoView = ExoVideoView(context)
videoView.setMedia(Uri.parse(videoUrl))
videoView.start()
Both libraries aim to simplify video playback in Android applications, but they take different approaches. VideoPlayerManager focuses on managing multiple video players and handling transitions between them, while ExoMedia provides a more comprehensive media playback solution built on top of ExoPlayer.
ExoMedia offers more advanced features and better format support, making it suitable for complex media playback requirements. However, VideoPlayerManager may be a lighter-weight option for simpler use cases, especially when dealing with multiple video players in a single view.
The choice between these libraries depends on the specific needs of your project, such as required media formats, streaming protocols, and the complexity of your video playback implementation.
Vitamio for Android
Pros of VitamioBundle
- Supports a wider range of video formats and codecs
- Offers hardware acceleration for improved performance
- Provides cross-platform compatibility (Android, iOS, and PC)
Cons of VitamioBundle
- Less actively maintained (last update in 2017)
- Larger library size, potentially increasing app size
- More complex setup and integration process
Code Comparison
VideoPlayerManager:
VideoPlayerManager<MetaData> videoPlayerManager = new SingleVideoPlayerManager(new PlayerItemChangeListener() {
@Override
public void onPlayerItemChanged(MetaData metaData) {
// Handle player item change
}
});
VitamioBundle:
IO.vInit(this);
mVideoView = (VideoView) findViewById(R.id.surface_view);
mVideoView.setVideoPath(path);
mVideoView.setMediaController(new MediaController(this));
mVideoView.requestFocus();
VideoPlayerManager focuses on managing multiple video players, while VitamioBundle provides a more comprehensive media playback solution with broader format support. VideoPlayerManager offers a simpler integration process and is more actively maintained, making it suitable for projects requiring basic video playback functionality. VitamioBundle is better suited for applications needing extensive format support and cross-platform compatibility, despite its larger size and more complex setup.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
VideoPlayerManager
This is a project designed to help controlling Android MediaPlayer class. It makes it easier to use MediaPlayer ListView and RecyclerView. Also it tracks the most visible item in scrolling list. When new item in the list become the most visible, this library gives and API to track it.
It consists from two libraries:
-
Video-Player-Manager - it gives the ability to invoke MediaPlayer methods in a background thread. It has utilities to have only one playback when multiple media files are in the list. Before new playback starts, it stops the old playback and releases all the resources.
-
List-Visibility-Utils - it's a library that tracks the most visible item in the list and notifies when it changes. NOTE: there should be the most visible item. If there will be 3 or more items with the same visibility percent the result might be unpredictable. Recommendation is to have few views visible on the screen. View that are big enough so that only one view is the most visible, look at the demo below.
These two libraries combined are the tool to get a Video Playback in the scrolling list: ListView, RecyclerView.
Details of implementation
Problems with video list
-
We cannot use usual VideoView in the list. VideoView extends SurfaceView, and SurfaceView doesn't have UI synchronization buffers. All this will lead us to the situation where video that is playing is trying to catch up the list when you scroll it. Synchronization buffers are present in TextureView but there is no VideoView that is based on TextureView in Android SDK version 15. So we need a view that extends TextureView and works with Android MediaPlayer.
-
Almost all methods (prepare, start, stop etc...) from MediaPlayer are basically calling native methods that work with hardware. Hardware can be tricky and if will do any work longer than 16ms (And it sure will) then we will see a lagging list. That's why need to call them from background thread.
Usage
Add this snippet to your project build.gradle file:
buildscript {
repositories {
jcenter()
}
}
Usage of Video-Player-Manager
dependencies {
compile 'com.github.danylovolokh:video-player-manager:0.2.0'
}
Put multiple VideoPlayerViews into your xml file. In most cases you also need a images above that will be shown when playback is stopped.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Top Player-->
<com.volokh.danylo.video_player_manager.ui.VideoPlayerView
android:id="@+id/video_player_1"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"
/>
<com.volokh.danylo.video_player_manager.ui.VideoPlayerView
android:id="@+id/video_player_2"
android:layout_height="0dp"
android:layout_width="match_parent"
android:layout_weight="1"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Top Player-->
<ImageView
android:id="@+id/video_cover_1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:layout_weight="1"/>
<ImageView
android:id="@+id/video_cover_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:scaleType="centerCrop"
android:layout_weight="1"/>
</LinearLayout>
Now you can use SingleVideoPlayerManager to playback only a single video at once:
//... some code
private VideoPlayerManager<MetaData> mVideoPlayerManager = new SingleVideoPlayerManager(new PlayerItemChangeListener() {
@Override
public void onPlayerItemChanged(MetaData metaData) {
}
});
//... some code
mVideoPlayer_1 = (VideoPlayerView)root.findViewById(R.id.video_player_1);
mVideoPlayer_1.addMediaPlayerListener(new SimpleMainThreadMediaPlayerListener(){
@Override
public void onVideoPreparedMainThread() {
// We hide the cover when video is prepared. Playback is about to start
mVideoCover.setVisibility(View.INVISIBLE);
}
@Override
public void onVideoStoppedMainThread() {
// We show the cover when video is stopped
mVideoCover.setVisibility(View.VISIBLE);
}
@Override
public void onVideoCompletionMainThread() {
// We show the cover when video is completed
mVideoCover.setVisibility(View.VISIBLE);
}
});
mVideoCover = (ImageView)root.findViewById(R.id.video_cover_1);
mVideoCover.setOnClickListener(this);
mVideoPlayer_2 = (VideoPlayerView)root.findViewById(R.id.video_player_2);
mVideoPlayer_2.addMediaPlayerListener(new SimpleMainThreadMediaPlayerListener(){
@Override
public void onVideoPreparedMainThread() {
// We hide the cover when video is prepared. Playback is about to start
mVideoCover2.setVisibility(View.INVISIBLE);
}
@Override
public void onVideoStoppedMainThread() {
// We show the cover when video is stopped
mVideoCover2.setVisibility(View.VISIBLE);
}
@Override
public void onVideoCompletionMainThread() {
// We show the cover when video is completed
mVideoCover2.setVisibility(View.VISIBLE);
}
});
mVideoCover2 = (ImageView)root.findViewById(R.id.video_cover_2);
mVideoCover2.setOnClickListener(this);
// some code
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.video_cover_1:
mVideoPlayerManager.playNewVideo(null, mVideoPlayer_1, "http:\\url_to_you_video_1_source");
break;
case R.id.video_cover_2:
mVideoPlayerManager.playNewVideo(null, mVideoPlayer_2, "http:\\url_to_you_video_2_source");
break;
}
}
The Demo of Video-Player-Manager:
Usage of List-Visibility-Utils
dependencies {
compile 'com.github.danylovolokh:list-visibility-utils:0.2.0'
}
The models of your adapter need to implement ListItem
public interface ListItem {
int getVisibilityPercents(View view);
void setActive(View newActiveView, int newActiveViewPosition);
void deactivate(View currentView, int position);
}
This messes up a bit with separating model from the logic. Here you need to handle the login in the model.
The ListItemsVisibilityCalculator will call according methods to:
-
Get view visibility
-
Set this item to active
-
Deactivate the item
// some code...
private final ListItemsVisibilityCalculator mListItemVisibilityCalculator =
new SingleListViewItemActiveCalculator(new DefaultSingleItemCalculatorCallback(), mList);
// some code...
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int scrollState) {
mScrollState = scrollState;
if(scrollState == RecyclerView.SCROLL_STATE_IDLE && !mList.isEmpty()){
mListItemVisibilityCalculator.onScrollStateIdle(
mItemsPositionGetter,
mLayoutManager.findFirstVisibleItemPosition(),
mLayoutManager.findLastVisibleItemPosition());
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if(!mList.isEmpty()){
mListItemVisibilityCalculator.onScroll(
mItemsPositionGetter,
mLayoutManager.findFirstVisibleItemPosition(),
mLayoutManager.findLastVisibleItemPosition() - mLayoutManager.findFirstVisibleItemPosition() + 1,
mScrollState);
}
}
});
mItemsPositionGetter = new RecyclerViewItemPositionGetter(mLayoutManager, mRecyclerView);
@Override
public void onResume() {
super.onResume();
if(!mList.isEmpty()){
// need to call this method from list view handler in order to have filled list
mRecyclerView.post(new Runnable() {
@Override
public void run() {
mListItemVisibilityCalculator.onScrollStateIdle(
mItemsPositionGetter,
mLayoutManager.findFirstVisibleItemPosition(),
mLayoutManager.findLastVisibleItemPosition());
}
});
}
}
The Demo of List-Visibility-Utils:
Usage in scrolling list (ListView, RecyclerView)
Add this snippet to your module build.gradle file:
dependencies {
compile 'com.github.danylovolokh:video-player-manager:0.2.0'
compile 'com.github.danylovolokh:list-visibility-utils:0.2.0'
}
Here is the relevant code combanation of two libraries fro implementing Video Playback in scrolling list.
// Code of your acitivty
/**
* Only the one (most visible) view should be active (and playing).
* To calculate visibility of views we use {@link SingleListViewItemActiveCalculator}
*/
private final ListItemsVisibilityCalculator mVideoVisibilityCalculator =
new SingleListViewItemActiveCalculator(new DefaultSingleItemCalculatorCallback(), mList);
/**
* ItemsPositionGetter is used by {@link ListItemsVisibilityCalculator} for getting information about
* items position in the RecyclerView and LayoutManager
*/
private ItemsPositionGetter mItemsPositionGetter;
/**
* Here we use {@link SingleVideoPlayerManager}, which means that only one video playback is possible.
*/
private final VideoPlayerManager<MetaData> mVideoPlayerManager = new SingleVideoPlayerManager(new PlayerItemChangeListener() {
@Override
public void onPlayerItemChanged(MetaData metaData) {
}
});
private int mScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// fill the list of items with an items
// some initialization code here
VideoRecyclerViewAdapter videoRecyclerViewAdapter = new VideoRecyclerViewAdapter(mVideoPlayerManager, getActivity(), mList);
mRecyclerView.setAdapter(videoRecyclerViewAdapter);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int scrollState) {
mScrollState = scrollState;
if(scrollState == RecyclerView.SCROLL_STATE_IDLE && !mList.isEmpty()){
mVideoVisibilityCalculator.onScrollStateIdle(
mItemsPositionGetter,
mLayoutManager.findFirstVisibleItemPosition(),
mLayoutManager.findLastVisibleItemPosition());
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if(!mList.isEmpty()){
mVideoVisibilityCalculator.onScroll(
mItemsPositionGetter,
mLayoutManager.findFirstVisibleItemPosition(),
mLayoutManager.findLastVisibleItemPosition() - mLayoutManager.findFirstVisibleItemPosition() + 1,
mScrollState);
}
}
});
mItemsPositionGetter = new RecyclerViewItemPositionGetter(mLayoutManager, mRecyclerView);
return rootView;
}
@Override
public void onResume() {
super.onResume();
if(!mList.isEmpty()){
// need to call this method from list view handler in order to have filled list
mRecyclerView.post(new Runnable() {
@Override
public void run() {
mVideoVisibilityCalculator.onScrollStateIdle(
mItemsPositionGetter,
mLayoutManager.findFirstVisibleItemPosition(),
mLayoutManager.findLastVisibleItemPosition());
}
});
}
}
@Override
public void onStop() {
super.onStop();
// we have to stop any playback in onStop
mVideoPlayerManager.resetMediaPlayer();
}
When visibility utils calls method "setActive" on your implementation of ListItem you have to call "playNewVideo". Please find the working code on this Demo application.
/**
* When this item becomes active we start playback on the video in this item
*/
@Override
public void setActive(View newActiveView, int newActiveViewPosition) {
VideoViewHolder viewHolder = (VideoViewHolder) newActiveView.getTag();
playNewVideo(new CurrentItemMetaData(newActiveViewPosition, newActiveView), viewHolder.mPlayer, mVideoPlayerManager);
}
@Override
public void playNewVideo(MetaData currentItemMetaData, VideoPlayerView player, VideoPlayerManager<MetaData> videoPlayerManager) {
videoPlayerManager.playNewVideo(currentItemMetaData, player, mDirectUrl);
}
Demo of usage in scrolling list (ListView, RecyclerView)
AndroidX support
Migration to AndroidX gladly provided by https://github.com/prensmiskin
License
Copyright 2015 Danylo Volokh
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Top Related Projects
This project is deprecated and stale. The latest ExoPlayer code is available in https://github.com/androidx/media
Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support.
视频播放器(IJKplayer、ExoPlayer、MediaPlayer),HTTPS,16k page size,支持弹幕,外挂字幕,支持滤镜、水印、gif截图,片头广告、中间广告,多个同时播放,支持基本的拖动,声音、亮度调节,支持边播边缓存,支持视频自带rotation的旋转(90,270之类),重力旋转与手动旋转的同步支持,支持列表播放 ,列表全屏动画,视频加载速度,列表小窗口支持拖动,动画效果,调整比例,多分辨率切换,支持切换播放器,进度条小窗口预览,列表切换详情页面无缝播放,rtsp、concat、mpeg。
MediaPlayer exoplayer ijkplayer ffmpeg
An Android ExoPlayer wrapper to simplify Audio and Video implementations
Vitamio for Android
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot