西瓜播放器 HTML5 video video.js 播放器 HTML5播放器 mp4 hls hls.js flv flv.js dash dash.js 无缝切换

Hooks

Hooks

为了业务定制或者复用播放器的内置功能,播放器内部实现了一个hook机制, hook分为两类

  • 1. 内置插件在触发用户行为处理的hook

此类hook通常在由用户行为触发的时候执行,方便业务自由定制内置插件行为,例如定制error插件内部的重试行为

  • 2. 播放器核心控制播放流程的hook

此类hook用于实现一些高阶功能,例如hls、flv插件等在用户调用play之前要加载数据源之类的功能,业务层面使用不到, 也不建议使用

hook的执行流程如下所示

pluginHook

hookNamepluginName执行时机
errorRetryerror错误插件用户点击刷新重试
showErrorerror错误插件监听到出错显示错误提示信息之前
fullscreenChangefullscreen用户点击全屏按钮的时候
playNextplaynext用户点击播放下一个按钮的时候
previewClickprogresspreview进度条预览图插件用户点击某个预览图的时候
replayHandlerreplay重播插件用户点击重播按钮的时候
clickstart用户点击中间大播放按钮的时候
mutedChangevolume音量调节插件用户调节音量的时候

demo

在播放出错的时候,显示错误面板,用户点击刷新按钮的时候,重新请求服务端获取播放地址,然后重新恢复播放

import Player, { Events } from 'xgplayer'

const player = new Player({...})
/**
 * 以下demo为启用error插件的errorRetry hook, 在出现错误的时候,用户点击【刷新】按钮的时候调用
 */

// hook逻辑为同步的时候
player.usePluginHooks('error', 'errorRetry', (plugin, ...args) => {
  /**
   * handler接收到的第一个参数为插件实例
   * 其余参数根据不同hook的不同实现,具体看插件内hook的说明
   */

  // playerInfo为提前获取到的对象
  const url = playerInfo.back_up_url
  const { player } = plugin
  if (url) {
    player.config.url = player.src = url
    player.play()
    // 阻止重试插件默认逻辑
    return false
  } else {
    // 执行插件默认重试逻辑
    return true
  }

  /**
   *  return true, 会执行插件内默认行为;
   *  return false, 插件内默认行为将不执行
   */
})

// hook逻辑为异步的时候
player.usePluginHooks('error', 'errorRetry', (plugin, ...args) => {
  return new Promise(resolve => {
    /**
     *  resolve(true) 继续执行默认行为
     *  resolve(false)或者reject() 不再执行默认行为
     */

    const { player } = plugin

    // getPlayerInfo为服务端播放数据
    getPlayerInfo().then(data => {
      // 重置播放源
      player.config.url = player.src = data.url
      player.play()
      // 阻止重试插件默认逻辑
      resolve(false)
    }).catch(() => {
      // 执行插件默认重试逻辑
      resolve(true)
    })
  })
})

// 以上调用等同于在error插件上调用useHook
player.getPlugin('error').useHooks('errorRetry', (plugin, ...args) => {
  // hook
})

playerHook

播放器可使用的hook如下列表如下所示

hookName含义
play用户调用player.play的时候执行
pause用户调用player.pause()的时候执行
replay用户调用player.replay()的时候执行
retry用户调用player.retry()的时候执行

demo

假设hls插件需要在用户调用play接口之前加载相关的播放资源,实现如下

import Player, { Events } from 'xgplayer'

const player = new Player({...})

player.on(Events.PLAY, () => {
  console.log('play Callback')
})

// 启用hook
player.useHooks('play', (player, ...args) => {
  return new Promise(resolve => {
    console.log('step1: play hook handler')
    setTimeout() => {
      if (资源ready) {
        console.log('step2: source ready, can executed player.play()')
        resolve(true)
      } else {
        console.log('step3: source not ready, block player.play()')
        resolve(false)
      }
    }
  })
})

// 用户点击按钮调用play接口
player.play()

// 以上代码执行顺序如下
/**
 * 资源ready
 * -- player.play()
 * -- step1: play hook handler
 * -- step2: source ready, can executed player.play()
 * -- player.video.play()
 * -- console.log('play Callback')
 */

/**
 * !资源ready
 * -- player.play()
 * -- step1: play hook handler
 * -- step3: source not ready, block player.play()
 */

EventsMiddleware

事件中间件,在媒体事件emit之前执行,用于决定某个事件是否下发,所有媒体事件都可添加中间件,使用demo如下

// 以下demo实现功能为
import Player, { Events } from 'xgplayer'

const player = new Player({...})

player.on(Events.WAITING, () => {
  console.log('waiting Callback')
})

player.setEventsMiddleware({
  waiting: (e, callback) => {
    const { player, eventName } = e
    if (canEmit) {
      callback(eventName, e)
    } else {
      console.log('not need emit waiting')
    }
  }
})