Video player documentation
catalogue
- 01. Introduction to the video player
- 02. Video player function
- 03. Video player architecture description
- 04. How to use the video player
- 05. Player detailed Api documents
- 06. Player packaging ideas
- 07. Player sample display diagram
- 08. Add a custom view
- 09. Video player optimization
- 10. Player problem record description
- 11. Performance optimization and library size
- 12. Video caching principle
- 13. View video player logs
- 14. The library has an abnormal code description
- 15. The library series of wiki documents
- 16. Version Updates document records
00. General framework for video player
- Basic package video player, can be in ExoPlayer, MediaPlayer, audio network RTC video player kernel, native MediaPlayer can be freely toggle
- For view state switching and later maintenance expansion, avoid coupling between functions and services. For example, you need to support player UI customization rather than the UI code in the lib library
- For video playback, audio playback, playback, and live video functions. Simple to use, strong code expansion, good encapsulation, mainly and business completely decoupled, exposed interface monitoring for developers to deal with specific business logic
- The overall architecture of the player: player kernel (free switching) + video player + play while caching + highly customized PLAYER UI view layer
- Code address: github.com/yangchong21…
- Maintenance for more than three years, if you feel ok, you can star
01. Introduction to the video player
1.1 Description of the library
Player functions | MediaPlayer | ExoPlayer | IjkPlayer | RTC | TXPlayer |
---|---|---|---|---|---|
UI/Player/ business decoupling | support | support | support | ||
Switch the video playback mode | support | support | support | ||
Seamless video switching | support | support | support | ||
Adjust playback progress | support | support | support | ||
Network Monitoring | support | support | support | ||
Slide to change brightness/sound | support | support | support | ||
Set the video playback ratio | support | support | support | ||
Freely switch video kernel | support | support | support | ||
Record playing Position | support | support | support | ||
Sharpness Mode switch | support | support | support | ||
Gravity sensor automatically enters | support | support | support | ||
Lock screen function | support | support | support | ||
Times the speed of playback | Does not support | support | support | ||
The video is played in a small window | support | support | support | ||
List small window play | support | support | support | ||
Caching while playing | support | support | support | ||
Play multiple videos at the same time | support | support | support | ||
Imitation fast hand preloading | support | support | support | ||
Kernel-based without UI | support | support | support | ||
Add a barrage | support | support | support | ||
Full screen display of power | support | support | support |
1.2 Function description of the library
type | Functional specifications |
---|---|
The project structure | VideoCache cache lib, VideoKernel VideoKernel lib, VideoPlayer video UIlib |
The kernel | MediaPlayer, ExoPlayer, IjkPlayer, later access Rtc and TXPlayer |
Protocol/Format | HTTP/HTTPS, concat, RTSP, HLS, RTMP, file, M3U8, MKV, webM, MP3, MP4, etc |
The picture | Adjust display ratio: default, 16:9, 4:3, fill; Rotate the picture Angle when playing (0,90,180,270); Image rotation |
layout | Separate kernel and UI, and market GitHub most players are different, easy to customize, add through addView |
play | Normal play, small window play, list play, imitation douyin play |
The custom | You can customize the video UI layer, so UI and Player are highly separated, support custom SurfaceView rendering layer |
02. Video player function
- A Basic Functions
- A.1.1 Can customize basic functions such as video loading type, video title, image at the bottom of video, and playback duration
- A.1.2 You can switch the video playing state of the player, including playing error, not starting, starting, Preparing, Playing, pausing, buffering and so on
- A.1.3 You can set the playback mode of the player freely, such as normal playback, full screen playback, and small screen playback. In full screen playback, you can rotate the screen.
- A.1.4 supports A variety of video playback types, such as native packaged video players and iJkPlayer-based players.
- A.1.5 You can set whether to hide the playback volume, progress, and brightness. You can drag the seekBar to change the video progress. It also supports the function of hiding the head and top layout if no operation is performed after n seconds
- A.1.6 You can set the full-screen mode in portrait mode and landscape mode to facilitate multiple application scenarios
- A.1.7 Disappearance and Display of Top and Bottom panels: Click the video screen to display and hide the operation panel; If no operation is performed after display, it will automatically disappear in 5 seconds.
- B Advanced Functions
- B.1.1 Supports the function of playing once and buffering once. Buffering includes two parts, the first is buffering during playing and the second is buffering during pausing
- B.1.2 package player based on ijkPlayer, ExoPlayer, Rtc, native MediaPlayer, etc., supporting multiple formats of video playback
- B.1.3 You can set whether to record the playing position, set the playing speed, and set the screen ratio
- B.1.4 Supports sliding to change the volume [right side of the screen], to change the screen brightness [left side of the screen], and to adjust the progress by sliding left and right at the bottom of the screen
- B.1.5 Supports video playback on the List page. After scrolling, pause the video playback. You can set whether to record the status of the video playback. It also supports deleting the video playing position state.
- B.1.6 Switching vertical and Horizontal screens: When switching full-screen, hide the status bar and display the customized TOP (display battery quantity); Restores the original state in portrait mode
- B.1.7 Switching the video resolution mode
- B.1.8 Added the screen lock function. The screen lock button is not provided in the portrait screen, but is displayed in the full landscape screen, and gesture processing is blocked when the screen is locked
- C Extended functions [This section can be selected according to the actual situation, general video payment App will have this eng eng]
- C1 product requirements: similar to some logic of Youku and IQiyi video player. For example, if the user is not logged in and does not have the permission to watch the video, it prompts to try the video [custom layout]; If the user does not log in but has permission to watch the video, the user can watch the video normally. If the user logs in but does not have a top-up member, some videos that require permission will enter the trial mode, and the top-up member interface will pop up after the trial. If the user’s balance is insufficient, such as only 99 yuan, but the video costs 199 yuan, there will be other prompts.
- C2’s own requirements: for example, if the video playback library is encapsulated, click the login button on the video to jump to the login page; Click the recharge member page to jump to the recharge page. This defines an interface that allows users to handle click events flexibly through method calls.
- C.1.1 You can set the trial mode and trial duration. When the trial is over, it prompts you to login or recharge…
- C.1.2 For setting the width and height of the video, it is recommended to set 4:3 or 16:9 or the common ratio. If the ratio is not common, there may be black edges. The background of the black edge can be set
- C.1.3 Can set various text descriptions when playing videos with permissions, instead of writing it in the encapsulation library, and users can set it by themselves
- C.1.4 Lock screen, a reference to most players, is only available in full screen mode
03. Video player architecture description
- Common layout views for videos
- Video base diagram (used to display the cover diagram when initializing the video), video state view [Loading loading, abnormal playing, video loading failure, video playing completion, etc.]
- Change brightness and Sound [Change sound view, change brightness view], change video fast forward and fast back, swipe left and right fast forward and fast back view (gesture swipe prompt box for fast forward and fast back)
- Top control area view (including return key, title, etc.), bottom control area view (including progress bar, play pause, time, switch to full screen, etc.)
- Lock screen layout view (full screen display, other hidden), bottom play progress bar view (many players have this), Clarity list view (Switch clarity popover)
- Layout views that may be involved later
- Gesture guide page (some players have novice guide function), offline download interface (this interface contains the download list, the list of items to edit (select all, delete))
- The user switches from wifi to 4G network, prompting the network switch popup interface (it will be displayed when the network changes from wifi to 4G)
- Image AD view (with countdown gone), start video AD view, non-member trial view
- Bullet screen view (this is important), watermark display view, double speed playback screen (for controlling double speed), bottom video list thumbnail view
- Screen projection video view interface, gift brushing interface in video studio, teacher start class interface, display more views (download, share, switch audio, etc.)
- Pain points for video players
- The player kernel is difficult to switch
- Different video player kernel, because of the API is different, so it is difficult to switch operation. If you want to be compatible with kernel switching, you must develop a video interface + implementation class player
- The player kernel is coupled to the UI layer
- In other words, the video player and UI are softer together, especially the interaction between the two. For example, the UI progress bar needs to be updated during playback, and the abnormal UI needs to be displayed during playback. It is difficult to handle the UI update operation when the player status changes
- The UI is difficult to customize or modify
- Common video players, for example, write the various views of the video to XML, which can be very large in the later code, and changing a small layout can have a big impact. In this way, in the later stage, the code is often only added, but not removed…
- Sometimes it is difficult to adapt to a new scene, such as adding a play AD, a teacher to start a class, or a video to guide the business needs, and you need to write a lot of business code into the player. In the late iteration, the open and closed principle is violated, and the video player needs to be separated from the business
- The structure of the video player is unclear
- This refers to whether the video player can quickly get started after reading the document and know the general process of packaging. It is convenient for others to modify and maintain later, so the video player function needs to be separated. For example, switch kernel + video player (Player + Controller + View)
- The player kernel is difficult to switch
- The purpose and effect to be achieved
- Basic package video player, can be in ExoPlayer, MediaPlayer, audio network RTC video player kernel, native MediaPlayer can be freely toggle
- For view state switching and later maintenance expansion, avoid coupling between functions and services. For example, you need to support player UI customization rather than the UI code in the lib library
- For video play, video screen, audio play, play back, and video live functions
- Universal video framework features
- Be sure to decouple
- Decoupling between player kernel and player: Support more playback scenarios and fast access of new playback services, without affecting other playback services, such as adding Ali Cloud player kernel or Tencent player kernel later
- Decoupling of player player and video UI: Supports adding custom video views, such as adding custom ads, novice guidance, or video playback exception views, which requires strong scalability
- Suitable for various service scenarios
- For example, it is suitable for playing single videos, multiple videos, and list videos, or one video per page like Douyin, and there are small Windows for playing videos. That is, for most business scenarios
- Be sure to decouple
- Video layered
- Player kernel
- AbstractVideoPlayer, MediaPlayer, IjkPlayer, AbstractVideoPlayer, etc
- Define abstract player, mainly including video initialization, Settings, state Settings, and play listener. Since each kernel player API may be different, we need a player class that implements AbstractVideoPlayer abstract class for the convenience of unified invocation later
- To make it easier to create different kernel players, you need to create a PlayerFactory, define an abstract method of creating a player for createPlayer, and then each kernel implements it to create its own player
- VideoPlayer player
- You can switch between video cores, Player+Controller. The player is responsible for the playback logic, the Controller is responsible for the view-specific logic, and they communicate with each other through an interface
- For Controller, an interface needs to be defined, which is mainly responsible for View UI processing logic and supports the addition of various customized View views [unified implementation of customized interface Control]. Each View should be as simple as possible, and finally added in the form of addView
- For Player, an interface needs to be defined, which is mainly responsible for the video playing processing logic, such as video playing, pause, setting the playing progress, setting the video link, switching the playing mode and other operations. Note that the Controller is set inside the Player, and the two interact via the interface
- UI Controller view
- Define a BaseVideoController class, this is mainly integrated with various events processing logic, such as player state changes, control view hide and display, play progress changes, lock state changes, device direction listening and so on
- Define a view interface InterControlView, in this class to define the binding view, view hide and display, play state, play mode, play progress, lock screen and other operations. Every implementation class can get those properties
- Use LinkedHashMap to save each custom view in BaseVideoController, put it in, and then add the view to the controller through addView, which makes it very easy to add custom views
- If the Player state needs to change the Controller view, for example, if the video exception needs to display the exception view, they interact with each other through ControlWrapper(which implements both the Controller and Player interfaces)
- Player kernel
04. How to use the video player
4.1 Description of Gradle References
- As shown below.
Implementation 'cn. Yc :VideoPlayer:3.0.1' Implementation 'cn. Yc :VideoCache:3.0.0' // implementation 'cn. Yc :VideoKernel:3.0.1'Copy the code
4.2 Adding a layout to XML
- Note that in the actual development, due to the serious fragmentation of Android phones, the resolution is too much, it is recommended to flexibly set the layout of the aspect ratio of 4:3 or 16:9 or you think appropriate, you can use code to set.
- If the aspect ratio is distorted, there will be black edges
<org.yczbj.ycvideoplayerlib.player.VideoPlayer android:id="@+id/video_player" android:layout_width="match_parent" android:layout_height="240dp"/> Copy the code
4.3 The simplest video player parameter setting
- As shown below.
BasisVideoController Controller = new BasisVideoController(this); / / set controller mVideoPlayer setVideoController (controller); // Set the link to play the video to mVideoPlayer.seturl (url); // start mVideoPlayer.start();Copy the code
4.4 Precautions
- If it is playing in full screen, you need to set the property value of the current activity in the manifest file
- Android :configChanges ensures that switching between vertical and horizontal screens while in full screen will not execute the Activity’s lifecycle and interrupt video playback
- Android: screenOrientation fixed the initial direction of the screen
- These two variables control the orientation of the screen after and after full screen
<activity android:name=".VideoActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:screenOrientation="portrait"/> Copy the code
- How do I start playing the video as soon as I enter the page
- The code is shown below. Avoid direct start() because the video may not be initialized yet…
mVideoPlayer.postDelayed(new Runnable() { @Override public void run() { mVideoPlayer.start(); } },300); Copy the code
- The code is shown below. Avoid direct start() because the video may not be initialized yet…
05. Player detailed Api documents
- 01. The simplest play
- 02. How to switch the video kernel
- 03. Switch video mode
- 04. Switch video resolution
- 05. Monitor video playback
- 06. Play in the list
- 07. Play in suspension window
- 08. Other important function APIS
- 09. Play multiple videos
- 10. VideoPlayer related Api
- 11. The Controller related Api
- 12. Play video imitation fast hand
- See this document: Video player Api description
06. Player packaging ideas
6.1 Video Hierarchy Example diagram
6.2 Video Player Flow Chart
- To be perfect
6.3 Video Player Lib library
6.4 Video kernel Lib library
6.5 Video Player UI Library
07. Player sample display diagram
08. Add a custom view
- For example, there is a business requirement to add an AD view at the beginning of the video player, wait 120 seconds for the AD countdown, and then go straight to the video logic. I believe this business scenario is very common, you have encountered, using the player is particularly simple, the code is as follows:
- I’m going to create a custom view, and I’m going to implement the InterControlView interface, and I’m going to rewrite all the abstract methods in that interface, and I’m going to omit a lot of code here, see the demo.
public class AdControlView extends FrameLayout implements InterControlView.View.OnClickListener { private ControlWrapper mControlWrapper; public AdControlView(@NonNull Context context) { super(context); init(context); } private void init(Context context){ LayoutInflater.from(getContext()).inflate(R.layout.layout_ad_control_view, this.true); } /** ** Play status * -1 play error * 0 Play not started * 1 Play ready * 2 Play ready * 3 Playing * 4 Pause playing * 5 Buffering (when the player is playing, the buffer is not enough, buffer, Buffer data enough to resume playing) * 6 pause buffering (when the player is playing, the buffer data is insufficient, buffering, pause the player, continue buffering, buffer data enough to resume pause * 7 play finished * 8 start play stop *@paramPlayState refers to the state of the player */ @Override public void onPlayStateChanged(int playState) { switch (playState) { case ConstantKeys.CurrentState.STATE_PLAYING: mControlWrapper.startProgress(); mPlayButton.setSelected(true); break; case ConstantKeys.CurrentState.STATE_PAUSED: mPlayButton.setSelected(false); break; }}/** * Play mode * Normal mode, small window mode, or normal mode * MODE_NORMAL Normal mode * MODE_FULL_SCREEN full screen mode * MODE_TINY_WINDOW Small screen mode *@paramPlayerState Play mode */ @Override public void onPlayerStateChanged(int playerState) { switch (playerState) { case ConstantKeys.PlayMode.MODE_NORMAL: mBack.setVisibility(GONE); mFullScreen.setSelected(false); break; case ConstantKeys.PlayMode.MODE_FULL_SCREEN: mBack.setVisibility(VISIBLE); mFullScreen.setSelected(true); break; } // The full screen adaptation logic is not implemented yet, you need to complete}}Copy the code
- And then how do I use this custom view? Very simple, in the previous basis, through the controller object add, code as shown below
controller = new BasisVideoController(this); AdControlView adControlView = new AdControlView(this); adControlView.setListener(new AdControlView.AdControlListener() { @Override public void onAdClick(a) { BaseToast.showRoundRectToast( "AD click jump"); } @Override public void onSkipAd(a) { playVideo(); }}); controller.addControlComponent(adControlView);// Set the controller mVideoPlayer.setController(controller); mVideoPlayer.setUrl(proxyUrl); mVideoPlayer.start(); Copy the code
09. Video player optimization
9.1 How can I Accommodate Different Kernel Players
- Question: there are different apis for different kernel players, such as ExoPlayer from Google, IjkPlayer from B, and native MediaPlayer. How to use the same API?
- For example, iJK and EXO’s video playback listener apis are completely different and need to be compatible
- Define interfaces, and then implement them in various kernel players, overriding abstract methods. When called, get the interface object to call the API, so that the API can be unified
- Define an interface. What does that interface have? This interface defines common video player methods, such as: video initialization, URL setting, load, and play state, which can be briefly divided into three parts.
- The first part: video initialization instance object method, mainly including: initPlayer initialization video, setDataSource set video player address, setSurface set video player render view, prepareAsync start ready to play operation
- The second part: video player state method, mainly including: play, pause, restore, remake, set progress, release resources, get progress, set speed, set volume
- Part 3: After player is bound to view, it needs to monitor the playback state, such as abnormal playback, completion of playback, ready to play, size change, and ready to play
- A factory abstract class is first defined, and then different kernel players create their own concrete factory implementation concrete classes
- PlayerFactory: Abstract Factory, which is the core of the factory method pattern. Any factory class that creates objects in the pattern must implement this interface
- ExoPlayerFactory: A concrete factory, a concrete factory role that contains business-specific logic and is called by the consumer to create concrete product objects.
- How to use it is divided into three steps, as follows
- 1. Call the createPlayer method in the concrete factory object. 2. Obtain specific product objects according to incoming product type parameters; 3. Return the product object and use it.
- In short, you only need to pass the type Type when creating an object, without the corresponding factory, to create a concrete product object
- This is the biggest advantage of creating objects
- The factory method is used to create the desired product while hiding the details of which specific product class will be instantiated. The user only needs to care about the factory for the desired product, not the creation details, or even the class name of the specific product class.
- When adding a new product, such as a new Ali player kernel, this time only needs to add a specific factory and specific products. The scalability of the system has become very good, completely in accordance with the “open and closed principle.”
9.2 UI extraction and encapsulation optimization of player
- Problems encountered in development
- The player can be played in multiple scenarios. Multiple products may use the same player, which causes a problem. When the player status of one player service changes, other player services must update the player status synchronously. Development and maintenance costs can increase dramatically, making subsequent development unsustainable.
- The UI is difficult to customize or modify
- Common video players, for example, write the various views of the video to XML, which can be very large in the later code, and changing a small layout can have a big impact. In this way, in the later stage, the code is often only added, but not removed…
- Sometimes it is difficult to adapt to a new scene, such as adding a play AD, a teacher to start a class, or a video to guide the business needs, and you need to write a lot of business code into the player. In the late iteration, the open and closed principle is violated, and the video player needs to be separated from the business
- The video player structure needs to be clear
- In other words, the video player and UI are softer together, especially the interaction between the two. For example, the UI progress bar needs to be updated during playback, and the abnormal UI needs to be displayed during playback. It is difficult to handle the UI update operation when the player status changes
- This refers to whether the video player can quickly get started after reading the document and know the general process of packaging. It is convenient for others to modify and maintain later, so the video player function needs to be separated. For example, switch kernel + video player (Player + Controller + View)
- Decoupled player and video UI: support to add custom video views, such as support to add custom ads, novice guidance, or video playback exceptions and other views, this requires strong scalability
- Suitable for various service scenarios
- For example, it is suitable for playing single videos, multiple videos, and list videos, or one video per page like Douyin, and there are small Windows for playing videos. That is, for most business scenarios
- This helps the playback service change
- The change of playback status causes cross-synchronization between different playback service scenarios. The direct control of playback services on the player is removed and interface listening is used to decouple the player. For example: player + controller + interface
- About Video Player
- Define a video player InterVideoPlayer interface, operation video play, pause, buffering, progress Settings, set play mode and other operations.
- Then write a concrete implementation class for the player interface, get the kernel player in this class, and do the relevant implementation operations.
- About the video View View
- Define a view InterVideoController interface, mainly responsible for view show/hide, play progress, lock screen, status bar and other operations.
- You then write a concrete implementation class for the player view interface, where the inflate view is operated and the interface method is implemented. To make it easier for developers to customize the view later, you need the addView action, which assembles the added view into a Map collection.
- The player interacts with the Controller
- When you create a BaseVideoController object in the Player, you need to add the Controller to the player, and there are two important things you need to do to pass the player state listener and the playmode listener to the controller
- SetPlayState Sets the playback logic state of the video player, mainly including buffering, loading, playing, pause, error, completion, abnormality, playing progress and other states, so as to facilitate the controller to do UI update operations
- SetPlayerState Sets the state of video playback switching mode, which is mainly normal mode, small window mode and normal mode, which is convenient for the controller to do UI update
- The player interacts with the View
- This is very critical, for example, video playback failure needs to display the control layer of the exception View View; To initialize video playing, display loading and update the UI playback progress bar. It’s all player and view layer interaction
- You can define a class that implements both the InterVideoPlayer interface and the InterVideoController interface, and then re-implement all the methods of both interfaces. The purpose of this class is to call both the VideoPlayer API and BaseVideoController API from the InterControlView interface implementation class
- How to add a custom player view
- Added custom player view, such as adding video ads, can choose to skip, choose to pause play. So this view, this view, definitely needs to manipulate the player or get the state of the player. In this case, it is necessary to expose the status interface listening for the video playback
- First define an InterControlView interface, that is to say, all custom video view view needs to realize this interface, the core method of the interface is: binding view to the player, view display hidden change monitoring, play state monitoring, play mode monitoring, progress monitoring, lock screen monitoring and so on
- In the BaseVideoController state listener, the player state can be passed to subclasses through the InterControlView interface object
9.4 Code optimization measures
- If you are in an Activity, the following code is recommended
@Override protected void onResume() { super.onResume(); if (mVideoPlayer ! Mvideoplayer.resume (); // Call this method to restart video playback when the video is paused or the buffer is paused. } } @Override protected void onPause() { super.onPause(); if (mVideoPlayer ! // Call this method to pause the video while it is playing or buffering. Mvideoplayer.pause (); } } @Override protected void onDestroy() { super.onDestroy(); if (mVideoPlayer ! = null) {// Destroy the page, release the internal player, and exit mVideoPlayer.release() if in full screen, small window mode; }} @override public void onBackPressed() {// Handle return key logic; If the screen is full, exit the screen. If it is a small window, exit is a small window if (mVideoPlayer = = null | |! mVideoPlayer.onBackPressed()) { super.onBackPressed(); }}Copy the code
10. Player problem record description
11. Performance optimization and library size
12. Video caching principle
- Better projects on the Network:Github.com/danikula/An…
- Network use of HttpURLConnection, file cache processing, file maximum policy, callback listening processing, breakpoint continuation, proxy services.
- But there are some problems, as shown below
- The file cache exceeded the limit and was not deleted according to the LRU algorithm.
- Handle HTTP response header messages returned to the player, and get the response header messages instead of the HEAD request (server support)
- Replace the network library with okHttp (because most projects use okHttp as the network request library), but this is a big change
- And let’s see how it works. It’s super easy. Pass in the video URL link, return a proxy link, and there you go
HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(this); String proxyUrl = cacheServer.getProxyUrl(URL_AD); mVideoPlayer.setUrl(proxyUrl); public static HttpProxyCacheServer getProxy(Context context) { return sharedProxy == null ? (sharedProxy = newProxy(context)) : sharedProxy; } private static HttpProxyCacheServer newProxy(Context context) { return new HttpProxyCacheServer.Builder(context) .maxCachesize (512 * 1024 * 1024) // 512MB for cache // No default value. //.cacheDirectory().build(); }Copy the code
- General principle
- The original way is to simply plug the address into the player and it can play directly. Now we are going to add a layer of local proxy in the middle, the player is playing through the address of our local proxy, so we can do some processing in the middle layer (local proxy layer), such as: file caching, pre-caching (second open processing), monitoring, etc.
- How to implement preloading
- In fact, the idea of preloading is very simple. After a video is played, the url of the next video to be preloaded is returned, and the thread is enabled to request the download data
- Start a thread to request and preload part of the data. If the preload data is greater than or equal to 1, use the queue first to load the data. Therefore, you can use the LinkedHashMap to save the task being preloaded.
- At the start of preloading, determine if the playback address is preloaded, and if not, create a threaded task and place it in the map collection. The preloading logic is then performed, that is, the HttpURLConnection request is executed
- The task of canceling the loading of the corresponding URL is provided, because the URL may no longer need to be preloaded. For example, for tiktok, when the user suddenly slides down several videos, many videos need to be skipped without preloading
- See the project code directly: VideoCache buffer module
13. View video player logs
- Manage video player encapsulation library logs in a unified manner to facilitate troubleshooting
- For example, video kernel, log filtering is aaa
- For example, video player, log filtering is BBB
14. The library has an abnormal code description
- For the video encapsulation library, exceptions thrown are uniformly processed. In order to facilitate developers to quickly know the reason for exceptions, they can query the code of the convention.
- This is particularly common in SDKS, so the library is partly borrowed from Tencent Player…