Mobile player


H5 own player


  • Out of the box, support full screen and other functions


Using video on PC can play normally, but using video tag on mobile will have many problems. Can refer toWhat H5 video can do & pit of existence

1. The video UI in each environment is inconsistent

Mobile player

2. Differences in API implementation and support in various environments:

What the hell are the following configurations? (References in this section)


We must make some configurations that meet its requirements for different environments, hoping to achieve the goal we want as much as possible.

  • However, it has to be said that the controls, poster and autoplay in the standard API may not be effective.
  • Automatic playback is not allowed on the mobile browser, you can try whether automatic playback under mute is supported
  • As mentioned earlier, some browsers may not recognize the scheme of setting different media sources through source.
  • For example, the scene where the monitoring data is loaded and the video data is obtained,canplayandcanplaythroughThe degree of support is different on devices of different system versions. Generally, we will use those with good compatibilityonloadedmetadataTo get the videoduration

    3. Inconsistent event interaction behavior

    adoptMediaevents & API detection, you’ll findIn each environment, the playback progress changes, the event triggering frequency is different, the corresponding state value may not be reliable when some events are triggered, and some scenes lack events(full screen state change, system player hijacking), play may not be triggered during seek

  • For example, some IOS environments are monitoredcanplayandcanplaythrough(whether enough data has been buffered to play smoothly), whenIt will not be triggered when loadingYes, even ifpreload="auto"It’s useless, but under the chrome debugger on PC and Android, it will be triggered in the loading phase, and IOS will not be triggered until it is played.
  • In some environments, there will be a short black screen from the beginning of video broadcasting to the time when the picture can be displayed(time for processing video source data). In order to avoid this black screen, you can add a floating layer on the video or set the container background, hide the video before playing, then listen to relevant events, start playing or switch to the video interface when you think there is a picture.
  • Part of the environment in youWhen you click play without setting the poster, you will also try to load the poster, resulting in a black screen during the playback period

4. Media format support cannot be guaranteed

Mp4 is generally supported well, m3u8 is better in the high-version mobile environment, and there are a large number of FLV playback requirements in media on demand live broadcast. Native video is not supported.

Handwriting mobile terminal player


  • cover
  • Play / pause / replay
  • Drag the scroll bar to adjust progress
  • Full screen and non full screen
  • Customize buttons such as share


Step 1: H5 adaptation template

  • preload: property specifies that the video is loaded after the page is loaded.
  • controls: defaultfalseLater, we will implement the control bar control by ourselves.
  • webkit-playsinline ,x5-playsinlineandplaysinline: the video is played locally without breaking away from the document stream.
  • x5-video-player-type: enable the same layer H5 player, that is, when the video is full screen, the div can be presented on the video layer, which is also a unique attribute of wechat Android
  • x5-video-orientation: declare the directions supported by the player:landscapeHorizontal screen,portraintVertical screen
  • x5-video-player-fullscreen: full screen setting:trueSupport full screen playback,falseFull screen playback is not supported.
  • object-fill: fill(the player will be forced to fill up, and the video scale may be changed)/contain(the video can be played in proportion, and the width and height can not be full at the same time) /

Step 2: Post

Principle: put a div container on the video and let the container fill the video component. By setting the divbackground-imageLoad pictures.

<script lang="ts">
import {
  Vue, Prop, Component
} from 'vue-property-decorator';

export default  class extends Vue {
  public videoPoster?: string;

  get style() {
    return `background-image:url(${this.videoPoster})`;
<style lang="scss" scoped>
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  z-index: 3; //  Displayed at the top of the video component
  background-repeat: no-repeat;
  background-size: 100% 100%; //  100% fill
  background-position: 50%;//  Center

Step 3: realize scroll bar progress control

Click the progress bar to adjust the progress and drag the dot to adjust the progress: place a scroll bar container with an actual progress area and a dot element.

Currenttime determines the progress of the progress bar

Active progress bar length / total progress bar length = currenttime / duration

adoptDifferent progress displays can be achieved by passing in different currenttime
On this basis, the progress bar under full screen and non full screen including play / pause and other actions can be encapsulated.

There are two progress bar advance schemes:

  1. The length of the activity progress bar is 100%. Initially, offset the activity progress bar to the left by 100%, and set it to exceed the containerhidden。 By calculating the distance, usetranslateXControl movement.

    • Advantage: very smooth forward
    • Disadvantages: the position needs to be recalculated when switching between horizontal and vertical screens
  2. Length of progress bar through activity0-100%To control progress

    • Advantages: automatic adaptation of horizontal and vertical screen switching
    • Disadvantages: there is flicker when moving forward, and the worse the performance, the more obvious it is.

It is found that the flicker is acceptable when moving forward, and the second scheme is used.

//Active controls style
  public getWindowActiveMoveStyle(): Object {
    const percent = this.currentTime / this.duration;
    return {
      'width':`${Math.round(percent * 10000) / 100}%`,
Click the progress bar to convert it to currenttime
//Click the progress bar to convert it to currenttime
  private getTouchedTime(e: TouchEvent): number {
    const clientRects = this.windowProgressEl.getClientRects() || []; // IOS>=6
    const touchedClientX = e.touches[0].clientX;
    const touchedClientY = e.touches[0].clientY;
    const { left = 1, top = 0, width = 0, height= 0 } = clientRects[0] || {};

    /**The calculation method is also different depending on whether the screen is full or not: mainly because some attribute values change after rotation*/
    const unit = this.fullscreen ? height : width;
    const touchedClientUnit = this.fullscreen ? touchedClientY : touchedClientX;
    const positionUnit = this.fullscreen ? top : left;
    return (touchedClientUnit - positionUnit) / unit * this.duration;

Step 4: full screen playback

  • Screen size setting after full screen:

      // object-fit: fill;  This will fill the area. There are some problems
      object-fit: contain
  • When the screen is not full, the size of the playing picture is limited by the outer container; How to make the screen full without being limited by the outer container

      width : 100vmax;
      height : 100vmin;
      transform-origin: top left;
      transform: rotate(90deg) translate(0,-100vmin);
      background-color: #000;

Attention should be paid to converting the screen to currenttime

private getTouchedTime(e: TouchEvent): number {

    /**The calculation method is also different depending on whether the screen is full or not: mainly because some attribute values change after rotation*/
    const unit = this.fullscreen ? height : width;
    const touchedClientUnit = this.fullscreen ? touchedClientY : touchedClientX;
    const positionUnit = this.fullscreen ? top : left;
    return (touchedClientUnit - positionUnit) / unit * this.duration;


  • Global loading

      this.videoRef.addEventListener('waiting', () => {
        this.isLoading = true;
      }, false);
  • Network disconnection treatment

    public mounted(){
    //Network condition processing
      window.addEventListener('offline', this.handleNetwork, false);
      window.addEventListener('online', this.handleNetwork, false);
    private handleNetwork() {
      if (navigator.onLine) {
        this.isOnline = true;
      } else {
        this.isOnline = false;
Detail processing
  • Margin problem

    • The position of the return button and progress bar / play button shall consider the curved screen
    • The progress circle shall be padded to prevent it from being missed
  • Mask is required as a whole

    • A mask is needed under loading to show the loading animation turning up
    • A mask is required under each icon (white) and progress bar on the player to prevent the video content from being displayed when it is white

reference material:

Recommended Today

Object memory layout and object access location

First, feel the memory layout through an example CustomerTest public class CustomerTest { public static void main(String[] args) { Customer cust = new Customer(); } } Customer image.png Memory layout at this time image.png notice: 1. Runtime metadata:There are some information describing the current instance, such as hash value and lock status.2. Name is the […]