{"version":3,"file":"index.mjs","names":["db","parser","Player","config"],"sources":["../src/parser/index.ts","../src/parser/db.ts","../src/player/video/animator.ts","../src/player/video/videoEvents.ts","../src/player/loopCheck.ts","../src/player/player_utils.ts","../src/player/index.ts","../src/index.ts"],"sourcesContent":["import {logger} from 'src/helper/logger'\nimport type {VideoAnimateType} from 'src/type/mix'\nimport {inflate} from 'zlib.es'\nconst yyExp = /yyeffectmp4json\\[\\[(.*?)\\]\\]yyeffectmp4json/\nclass Parser {\n  exp: any\n  constructor() {\n    this.exp = /eJzt3U1v20gMgOH/g\n  }\n  // base64Regex(exact?: boolean): RegExp {\n  //   const regex = '(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)'\n  //   return exact ? new RegExp(`(?:^${regex}?$)`) : new RegExp(regex, 'g')\n  // }\n  getdata(raw: string): VideoAnimateType | undefined {\n    try {\n      const mc = raw.match(yyExp)\n      if (!mc) return undefined\n      const zlibBase64String = mc[1]\n      const u8 = this.inflate(zlibBase64String)\n      let d: any = this.unit8Tostring(u8)\n      d = JSON.parse(d)\n      logger.debug('[ParserGetData]', d)\n      return d\n    } catch (e) {\n      logger.warn(e)\n      return undefined\n    }\n  }\n  base64ToArrayBuffer(base64: string) {\n    const binary_string = window.atob(base64)\n    const len = binary_string.length\n    const bytes = new Uint8Array(len)\n    for (let i = 0; i < len; i++) {\n      bytes[i] = binary_string.charCodeAt(i)\n    }\n    return bytes.buffer\n  }\n  unit8Tostring(u8data: Uint8Array) {\n    return new TextDecoder().decode(u8data)\n  }\n  inflate(str: string): Uint8Array {\n    const u8data = inflate(new Uint8Array(this.base64ToArrayBuffer(str)))\n    return u8data\n  }\n}\nexport default new Parser()\n","import {logger} from 'src/helper/logger'\n\ntype VideoEntity = any\nclass DB {\n  private readonly storeName: string\n  private readonly dbPromise: Promise<IDBDatabase>\n  constructor(\n    {\n      name,\n      version,\n      storeName,\n    }: {\n      name: string\n      version: number //版本号要比老版本高 否则会报错\n      storeName: string\n    } = {name: 'e-video', version: 1, storeName: 'video'},\n  ) {\n    logger.debug('[DBCache] DB', name, version, storeName)\n    this.storeName = storeName\n    this.dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n      if (self.indexedDB !== undefined) {\n        const request = self.indexedDB.open(name, version)\n        // request.onerror = error => reject(new Error(`IndexedDB open fail, ${error.type}`))\n        // request.onerror = error => reject(`IndexedDB open fail, ${error.type}`)\n        request.onerror = error => {\n          // 在保证实例化一次的情况下不报错 可继续送礼\n          logger.warn(`IndexedDB open fail, ${error.type}`)\n          return resolve(undefined)\n        }\n        request.onsuccess = () => resolve(request.result)\n        request.onupgradeneeded = e => {\n          const db = request.result\n          if (e.oldVersion && e.oldVersion < e.newVersion) {\n            logger.debug('[DB] deleteObjectStore')\n            db.deleteObjectStore(storeName)\n          }\n          db.createObjectStore(storeName)\n        }\n      } else {\n        reject('IndexedDB not supported')\n      }\n    })\n  }\n\n  async find(id: IDBValidKey): Promise<VideoEntity | undefined> {\n    return await this.dbPromise.then(\n      async db =>\n        await new Promise((resolve, reject) => {\n          const tx = db.transaction([this.storeName], 'readonly')\n          const request = tx.objectStore(this.storeName).get(id)\n          request.onsuccess = () => {\n            /* if (typeof request.result === 'string') {\n              resolve(this.stringToMovie(request.result))\n            } else {\n              resolve(undefined)\n            } */\n            resolve(request.result)\n          }\n          request.onerror = () => reject(new Error('Find Error'))\n        }),\n    )\n  }\n  // stringToMovie(m: string) {\n  //   return JSON.parse(m)\n  // }\n  // moiveToString(m: VideoEntity) {\n  //   return JSON.stringify(m)\n  // }\n  async insert(id: IDBValidKey, data: VideoEntity): Promise<void> {\n    // const d = this.moiveToString(data)\n    return await this.dbPromise.then(\n      async db =>\n        await new Promise((resolve, reject) => {\n          const tx = db.transaction([this.storeName], 'readwrite')\n          const request = tx.objectStore(this.storeName).put(data, id)\n          tx.oncomplete = () => resolve()\n          request.onerror = () => reject(new Error('Insert Error'))\n        }),\n    )\n  }\n\n  async delete(id: IDBValidKey): Promise<void> {\n    return await this.dbPromise.then(\n      async db =>\n        await new Promise((resolve, reject) => {\n          const tx = db.transaction([this.storeName], 'readwrite')\n          const request = tx.objectStore(this.storeName).delete(id)\n          request.onsuccess = () => resolve()\n          request.onerror = () => reject(new Error('Delete Error'))\n        }),\n    )\n  }\n}\n/**\n * 适配多浏览器兼容性、SSR方案\n * DBCache\n *  options 必须\n *  usePrefetch: true,\n    useVideoDBCache: true,\n\t\t使用方式：\n\t\timport db from 'src/parser/db'\n\t\tdb.IndexDB = true\n\t\tdb.model().find\n\t\tdb.model().insert\n\t\tdb.model().delete\n */\nclass DBCache {\n  private useIndexDB = true\n  private db?: DB\n  constructor() {\n    // logger.debug('[DBCache] constructor')\n  }\n  set IndexDB(isUse: boolean) {\n    this.useIndexDB = isUse\n    logger.debug('[DBCache] IndexDB', this.useIndexDB)\n  }\n  model() {\n    // logger.debug('[DBCache] model', this.useIndexDB)\n    if (typeof window !== 'undefined' && this.useIndexDB) {\n      if (!this.db) {\n        logger.debug('[DBCache] new DB')\n        this.db = new DB()\n      }\n      return this.db\n    } else {\n      return this\n    }\n  }\n  async find(id: IDBValidKey) {}\n  async insert(id: IDBValidKey, data: VideoEntity) {}\n  async delete(id: IDBValidKey) {}\n}\n// export {DBCache}\nexport default new DBCache()\n// export default typeof window !== 'undefined' ? new DB() : ({} as DB)\n","import {logger} from 'src/helper/logger'\nimport type {MetaDataType, MixEvideoOptions} from 'src/type/mix'\n// import VideoEntity from 'src/player/render/videoEntity'\n//\nexport type AnimatorType = 'requestVideoFrameCallback' | 'requestAnimationFrame' | 'setTimeout'\n\nexport default class Animator {\n  private animateId: number\n  public animationType: AnimatorType\n  private video: HTMLVideoElement\n  private fps = 20\n  private videoFps = 0\n  private frameDelay = 0\n  private frameStartTime = 0\n  private op: MixEvideoOptions\n  //\n  public isPlay: boolean\n  public requestAnim: (...args: any[]) => number\n  public cancelAnim: (...args: any[]) => void\n  //\n  public onUpdate?: (frame: number) => void\n  //\n  constructor(video: HTMLVideoElement, op: MixEvideoOptions) {\n    this.video = video\n    this.op = op\n    this.isPlay = false\n\n    if ('requestVideoFrameCallback' in HTMLVideoElement.prototype && this.op.useAccurate) {\n      this.animationType = 'requestVideoFrameCallback'\n    } else if (typeof requestAnimationFrame !== 'undefined') {\n      this.animationType = 'requestAnimationFrame'\n      this.op.useAccurate = false\n    } else {\n      this.animationType = 'setTimeout'\n      this.op.useAccurate = false\n    }\n    //\n    // if (this.op.fps) {\n    //   this.fps = this.op.fps\n    // }\n    //\n    this.requestAnim = this.returnRequestAnim()\n    this.cancelAnim = this.returnCancelAnim()\n  }\n  public setVideoFps({videoFps, fps}: any) {\n    this.fps = fps\n    this.videoFps = videoFps\n    if (this.animationType !== 'requestVideoFrameCallback' && this.fps > 20) {\n      this.fps = 20\n    }\n  }\n  public async setup() {\n    this.frameDelay = 1000 / this.fps\n  }\n  private currentTimeMillsecond: () => number = () => {\n    if (typeof performance === 'undefined') {\n      return new Date().getTime()\n    }\n    return performance.now()\n  }\n  start() {\n    if (this.frameDelay === 0 && this.fps > 0) this.frameDelay = 1000 / this.fps\n    logger.debug('animator start', this.animateId, this.frameDelay, this.fps)\n    this.frameStartTime = this.currentTimeMillsecond()\n    this.cancelAnim()\n    this.animateId = this.requestAnim(this.drawFrame)\n  }\n  stop() {\n    logger.debug('animator stop', this.animateId)\n    this.cancelAnim()\n  }\n\n  destroy() {\n    logger.debug('[animator destroy]', this.animateId)\n    this.cancelAnim()\n    this.op = undefined as any\n    this.video = undefined as any\n    this.cancelAnim = undefined as any\n    this.requestAnim = undefined as any\n    this.onUpdate = undefined\n    this.drawFrame = undefined\n  }\n  drawFrame = (now = this.currentTimeMillsecond(), metadata?: MetaDataType) => {\n    if (!this.isPlay) return\n    this.cancelAnim()\n    this.animateId = this.requestAnim(this.drawFrame)\n    // if (!this.op.fps) {\n    const mediaTime = metadata?.mediaTime || this.video.currentTime\n    const frame = this.getCurrentFrame(mediaTime)\n    this.onUpdate && this.onUpdate(frame)\n    /*\n    } else {\n      let mediaTime = metadata?.mediaTime || this.video.currentTime\n      const delta = now - this.frameStartTime\n      if (delta > this.frameDelay) {\n        mediaTime = mediaTime - delta / 1000\n        const frame = this.getCurrentFrame(mediaTime)\n        this.onUpdate && this.onUpdate(frame)\n        this.frameStartTime = now - (delta % this.frameDelay)\n      }\n    }\n    */\n  }\n  getCurrentFrame(mediaTime = 0) {\n    // const videoFps = this.videoFps || this.fps\n    return Math.round(mediaTime * this.videoFps) + (this.op.offset || 0)\n  }\n  returnRequestAnim() {\n    switch (this.animationType) {\n      case 'requestVideoFrameCallback':\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n        //@ts-ignore\n        return fn => (this.animateId = this.video.requestVideoFrameCallback(fn))\n      case 'requestAnimationFrame':\n        // return (fn: FrameRequestCallback) => (this.animateId = requestAnimationFrame(fn))\n        return fn => {\n          return requestAnimationFrame(() => {\n            const now = this.currentTimeMillsecond()\n            const delta = now - this.frameStartTime\n            if (delta > this.frameDelay) {\n              this.frameStartTime = now - (delta % this.frameDelay)\n              return fn()\n            }\n            if (this.requestAnim) {\n              if (this.animateId) {\n                this.cancelAnim()\n              }\n              this.animateId = this.requestAnim(fn)\n            }\n          })\n        }\n      default:\n        return (fn: () => void) => (this.animateId = window.setTimeout(fn, 1000 / this.fps))\n    }\n  }\n  returnCancelAnim() {\n    switch (this.animationType) {\n      case 'requestVideoFrameCallback':\n        // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n        //@ts-ignore\n        return () => this.animateId && this.video.cancelVideoFrameCallback(this.animateId)\n      case 'requestAnimationFrame':\n        return () => this.animateId && cancelAnimationFrame(this.animateId)\n      default:\n        return () => this.animateId && clearTimeout(this.animateId)\n    }\n  }\n}\n","export default [\n  // 'canlplaythrough',\n  'playing', //开始播放\n  'pause',\n  // 'resume',\n  'ended',\n  'progress',\n  'loadstart',\n  'stop',\n  'loadeddata',\n  'loadedmetadata',\n  'ratechange',\n  //\n  'abort',\n  'emptied',\n  'error',\n  'mozaudioavailable',\n  'stalled',\n  'suspend',\n  'play', //状态是开始播放，但视频并未真正开始播放\n  'waiting', //等待数据\n  'canplay', //可以播放，但中途可能因为加载而暂停\n  'canplaythrough', //可以流畅播放\n  // 'timeupdate', //播放进度变化\n  'seeked', //播放完毕进度回到起点循环播放\n  'seeking', //寻找中\n]\n","import logger from 'src/helper/logger'\nimport type {EventCallback} from 'src/type/mix'\n\nexport class LoopChecker {\n  public loopCount = Number.POSITIVE_INFINITY\n  private _endFrame? = -1\n\n  private playedLoopCount = 0\n  private lastFrameIndex = 0\n\n  public onEnd: EventCallback\n  public onLoopCount: EventCallback\n\n  constructor(loop: boolean | number, endFrame?: number) {\n    const type = typeof loop\n    if (type === 'boolean') {\n      this.loopCount = loop ? Number.POSITIVE_INFINITY : 1\n    } else if (type === 'number') {\n      this.loopCount = Number(loop)\n    }\n\n    if (endFrame !== undefined) {\n      this._endFrame = endFrame\n    }\n\n    // logger.info('[LoopChecker] this._loopCount=', this.loopCount, ', loop=', loop)\n  }\n\n  reset(): void {\n    this.playedLoopCount = 0\n    this.lastFrameIndex = 0\n  }\n\n  public setEndFrame(value: number) {\n    logger.debug('[LoopChecker]setEndFrame value=', value)\n    if (value !== undefined) {\n      this._endFrame = value\n    }\n  }\n\n  private checkFrame(frame: number) {\n    if (this._endFrame > 10) {\n      return (\n        this.lastFrameIndex < this._endFrame &&\n        this.lastFrameIndex > this._endFrame / 2 &&\n        (frame >= this._endFrame || frame <= this._endFrame / 2)\n      )\n    } else {\n      return (this.lastFrameIndex < this._endFrame || this.lastFrameIndex > 10) && frame >= this._endFrame && frame < 10\n    }\n  }\n\n  public updateFrame(frame: number) {\n    if (this.checkFrame(frame)) {\n      logger.debug(\n        '[LoopChecker] this.playedLoopCount=',\n        this.playedLoopCount,\n        ', this.lastFrameIndex=',\n        this.lastFrameIndex,\n        ', frame',\n        frame,\n        ', endFrame=',\n        this._endFrame,\n        ', this.loopCount=',\n        this.loopCount,\n      )\n\n      this.playedLoopCount = this.playedLoopCount + 1\n      this.onLoopCount && this.onLoopCount({count: this.playedLoopCount})\n\n      if (this.playedLoopCount === this.loopCount) {\n        // logger.info('[LoopChecker] finished.... this.playedLoopCount=', this.playedLoopCount)\n        this.onEnd && this.onEnd()\n        return false\n      }\n    }\n\n    this.lastFrameIndex = frame\n    return true\n  }\n}\n","import logger from 'src/helper/logger'\nexport function getVideoByHttp(videoSource: string) {\n  return new Promise((resolve, reject) => {\n    fetch(videoSource)\n      .then(r => {\n        if (r.ok) {\n          resolve(r.blob())\n        } else {\n          logger.error('fetch request failed, url: ' + this.op.videoSource)\n          return undefined\n        }\n      })\n      .catch(err => {\n        logger.error('getVideoByHttp fetch, err=', err)\n        return undefined\n      })\n  })\n}\n","import {logger} from 'src/helper/logger'\nimport parser from 'src/parser'\nimport db from 'src/parser/db'\nimport type Render2DType from 'src/player/render/canvas2d'\nimport type RenderWebglType from 'src/player/render/webgl'\nimport type RenderWebGPUType from 'src/player/render/webgpu'\n// import {prefetchVideoStream} from 'src/player/video/mse'\n// import {versionTips} from 'src/helper/logger'\nimport Animator, {type AnimatorType} from 'src/player/video/animator'\nimport videoEvents from 'src/player/video/videoEvents'\nimport {\n  EPlayError,\n  EPlayStep,\n  type EventCallback,\n  type MixEvideoOptions,\n  type RenderType,\n  type VideoAnimateType,\n  type WebglVersion,\n} from 'src/type/mix'\n// import Webgl from './render/webglEntity'\n\n// import {getVIdeoId} from 'src/helper/utils'\nimport {clickPlayBtn, isHevc, polyfill} from 'src/helper/polyfill'\n// import VideoEntity from './render/videoEntity'\nimport {LoopChecker} from './loopCheck'\nimport {getVideoByHttp} from './player_utils'\n\n//\nexport default class EVideo {\n  private video: HTMLVideoElement\n  private eventsFn: {[key: string]: (...args: any[]) => void} = {}\n  private animator: Animator\n  private blobUrl: string\n  private polyfillCreateObjectURL: boolean\n  private timeoutId = null\n  private loopChecker!: LoopChecker\n  private videoFile?: File\n  private isSupportHevc = false\n  private startFlag = false\n  // 绑定 浏览器无法自动播放显示的元素\n  private pollyfillTipsElement\n  //\n  public onStart: EventCallback\n  public onResume: EventCallback\n  public onPause: EventCallback\n  public onStop: EventCallback\n  public onProcess: EventCallback\n  public onEnd: EventCallback\n  public onError: EventCallback\n\n  private onLoadedmetadata: EventCallback\n  //\n  public isPlay = false\n  public renderer: RenderWebglType | Render2DType | RenderWebGPUType\n  public renderType: RenderType\n  public animationType: AnimatorType\n  public op: MixEvideoOptions\n  public fps = 0\n  public version: WebglVersion\n  public webglVersion: WebglVersion\n  /**\n   * 记录当前播放资源的 base64,当blob url播放失败时播放\n   */\n  constructor(op: MixEvideoOptions) {\n    if (!op.container) throw new Error('container is need!')\n    if (!op.videoUrl) throw new Error('videoUrl is need!')\n    //TODO 考虑到 除了 htmlinputelement http 应该还有 dataUrl 后续拓展\n    this.op = op\n    this.loopChecker = new LoopChecker(this.op.loop, this.op.endFrame)\n    this.loopChecker.onLoopCount = this.op.onLoopCount\n    this.video = this.videoCreate()\n    this.animator = new Animator(this.video, this.op)\n    // 是否创建 object url\n    this.polyfillCreateObjectURL = (polyfill.baidu || polyfill.quark || polyfill.uc) && this.op.forceBlob === false\n    // check IndexDB cache\n    db.IndexDB = this.op.useVideoDBCache\n\n    this.loopChecker.onEnd = () => {\n      logger.debug('[player] onEnd...url:', this.op.videoUrl)\n      this._onEnd()\n    }\n  }\n\n  private _onEnd() {\n    this.stop()\n    const onEnd = this.onEnd\n    if (!this.op.endPause) {\n      this.destroy()\n    }\n\n    onEnd && onEnd()\n  }\n\n  private _error(err: any) {\n    logger.error(`[YYEVA] error err:`, err)\n    const onEnd = this.onEnd\n    const onError = this.onError\n\n    this.stop()\n    this.destroy()\n    onEnd && onEnd?.(err)\n    onError && onError?.(err)\n  }\n  async selectRender(rt: RenderType) {\n    logger.debug('this.renderer', this.renderer, rt)\n    if (this.op.renderType !== rt) this.op.renderType = rt\n    const {default: Renderer} = await this.renderLoader[rt]()\n    this.renderer = new Renderer(this.op)\n    this.renderType = this.renderer.renderType as RenderType\n    /**\n     * 实例化后但是不支持 webgl后降级\n     * 兜底 canvas2d 渲染\n     */\n    const renderer = this.renderer as RenderWebglType\n    this.webglVersion = renderer ? renderer.version : null\n    if (renderer.renderType === 'webgl' && renderer.version === null) {\n      logger.debug('[player] webgl to canvas2d')\n      this.renderer.destroy()\n      this.selectRender('canvas2d')\n    }\n  }\n  private renderLoader = {\n    webgl: () => import(`src/player/render/webgl`),\n    webgpu: () => import(`src/player/render/webgpu`),\n    canvas2d: () => import(`src/player/render/canvas2d`),\n  }\n  async prepareRender() {\n    logger.debug('navigator.gpu', navigator.gpu)\n    if (this.op.renderType === 'webgpu') {\n      if (navigator.gpu) {\n        await this.selectRender('webgpu')\n      } else {\n        await this.selectRender('webgl')\n      }\n    } else if (this.op.renderType === 'canvas2d') {\n      await this.selectRender('canvas2d')\n    } else {\n      await this.selectRender('webgl')\n    }\n  }\n\n  public async setup() {\n    try {\n      logger.debug('[=== e-video setup ===]')\n\n      await this.prepareRender()\n\n      await this.videoLoad()\n      await this.renderer.setup(this.video)\n      // const hasAudio = await detectAudio(this.video)\n      // logger.debug('hasAudio', hasAudio, 'mute', this.op.mute)\n\n      this.video.muted = this.op.mute\n\n      this.fps = this.renderer.videoEntity.fps\n      logger.debug(`[YYEVA] this.renderer.videoEntity.fps`, this.renderer.videoEntity.fps)\n      this.animator.setVideoFps({\n        fps: this.renderer.videoEntity.fps,\n        videoFps: this.renderer.videoEntity.videoFps,\n      })\n\n      this._updateEndFrame()\n      //\n      await this.animator.setup()\n      this.animator.onUpdate = frame => {\n        if (this.loopChecker.updateFrame(frame)) {\n          try {\n            this.renderer.render(frame)\n          } catch (err) {\n            logger.error(`[YYEVA] render frame error`)\n            this._error(err)\n          }\n        }\n      }\n      this.animationType = this.animator.animationType\n      //\n      this.renderer.renderCache.mCache.setOptions({\n        fps: this.fps,\n        animationType: this.animationType,\n        videoDurationTime: this.video.duration,\n      })\n      //\n      logger.debug('[setup]', this.animationType, this.webglVersion)\n      // 纯在缓存后不再显示 video标签 节省性能\n      if (this.webglVersion && this.op.renderType === 'webgl') {\n        const render = this.renderer as RenderWebglType\n        const isCache = this.op.useFrameCache ? render.renderCache.isCache() : false\n        if (\n          this.animationType !== 'requestVideoFrameCallback' &&\n          !this.op.showVideo &&\n          // Webgl.version === 1 &&\n          !isCache\n        ) {\n          const video = this.video\n          video.style.position = 'fixed' //防止撑开页面\n          video.style.opacity = '0.1'\n          video.style.left = '0'\n          video.style.top = '0'\n          video.style.visibility = 'visible'\n          video.style.width = '2px'\n          video.style.height = '2px'\n          video.style.pointerEvents = 'none'\n          video.style.userSelect = 'none'\n        }\n      }\n    } catch (e) {\n      // this.onEnd?.(e)\n      // this.onError?.(e)\n      // this.destroy()\n      logger.error(e)\n    }\n\n    //this.op.showPlayerInfo && versionTips(this.op, this)\n  }\n\n  private _updateEndFrame() {\n    let endFrame = this.op.endFrame\n\n    const duration = this.video.duration\n    const maxFrame = Math.max(0, Math.floor(this.fps * duration) - 5)\n    if (this.op.endPause && (endFrame === undefined || endFrame < 0)) {\n      endFrame = maxFrame\n    }\n    endFrame = Math.min(maxFrame, endFrame || 0)\n    logger.debug('[player]_updateEndFrame, endFrame=', endFrame, ', op.endFrame=', this.op.endFrame)\n    this.loopChecker.setEndFrame(endFrame)\n  }\n\n  private setPlay = (isPlay: boolean) => {\n    if (this.renderer) {\n      this.renderer.isPlay = isPlay\n      this.animator.isPlay = isPlay\n      this.isPlay = isPlay\n    }\n  }\n  private isDestroyed() {\n    logger.debug('player is destroyed!')\n  }\n  public start() {\n    logger.debug('player start!, url=', this.op.videoUrl)\n    //::TODO 做播放兼容性处理\n    if (!this.renderer) return this.isDestroyed()\n    this.startFlag = true\n    this.startEvent()\n  }\n\n  private cleanTimer() {\n    if (this.timeoutId) {\n      clearTimeout(this.timeoutId)\n      this.timeoutId = null\n    }\n  }\n\n  private beginTimer() {\n    logger.debug(\n      '[player]beginTimer..., duration=',\n      this.video.duration,\n      'loop=',\n      this.loop(),\n      'checkTimeout=',\n      this.op.checkTimeout,\n    )\n    if (this.loopChecker.loopCount === 1 && this.op.checkTimeout && this.video.duration > 0) {\n      this.cleanTimer()\n      this.timeoutId = setTimeout(\n        () => {\n          logger.debug('[player] timeout...url:', this.op.videoUrl)\n          this._onEnd()\n          // this.stop()\n          // this.destroy()\n          // this.onEnd && this.onEnd()\n        },\n        this.video.duration * 1000 + 100,\n      )\n    }\n  }\n\n  private clickToPlay() {\n    if (this.op.onRequestClickPlay) {\n      this.pollyfillTipsElement = this.op.onRequestClickPlay(this.op.container, this.video)\n    } else {\n      this.pollyfillTipsElement = clickPlayBtn(this.op.container, this.video)\n    }\n  }\n  private hidePollyfileTips() {\n    if (this.pollyfillTipsElement && this.pollyfillTipsElement) {\n      this.pollyfillTipsElement.style.display = 'none'\n    }\n  }\n  private startEvent() {\n    if (!this.startFlag && !this.op.autoplay) {\n      logger.info(`startEvent() this.startFlag is false`)\n      return\n    }\n\n    if (!this.renderer || this.renderer.isPlay === true) return\n    this.setPlay(true)\n    this.animator.start()\n    this.beginTimer()\n    this.loopChecker.reset()\n    this.video.currentTime = 0\n    // this.video.load()\n    if (document.hidden) {\n      logger.debug(`startEvent() document.hidden..`)\n      return\n    }\n    const tryPlay = (isMuted = false) => {\n      if (isMuted) {\n        this.video.muted = true\n      }\n\n      const videoPromise = this.video.play()\n      if (videoPromise) {\n        videoPromise\n          .then(() => {\n            logger.debug(`${this.video.muted ? '静音播放' : '声音播放'}`)\n          })\n          .catch(e => {\n            if (isMuted) {\n              // 已经尝试过静音播放仍然失败\n              logger.error(\n                `play error: `,\n                this.op.videoSource,\n                e,\n                'e?.code=',\n                e?.code,\n                ', e?.name=',\n                e?.name,\n                ', url=',\n                this.op.videoUrl,\n              )\n              if (e?.code === 20) {\n                return\n              }\n              this.clickToPlay()\n              if (e?.code === 0 && e?.name === EPlayError.NotAllowedError) {\n                this.op?.onError?.({\n                  playError: EPlayError.NotAllowedError,\n                  video: this.video,\n                  playStep: EPlayStep.muted,\n                })\n              }\n              return\n            }\n\n            // 第一次播放失败，尝试静音播放\n            logger.warn('尝试切换到静音播放', this.op.videoSource)\n            tryPlay(true)\n          })\n      } else {\n        this.op?.onEnd?.()\n      }\n    }\n\n    tryPlay(this.op.mute)\n  }\n  public seek(time: number) {\n    if (!this.renderer) return this.isDestroyed()\n    if (this.video.readyState >= 1) {\n      this.video.currentTime = time\n    }\n  }\n\n  public stop(resetToStart = false) {\n    logger.debug('[player]stop.')\n    if (!this.renderer) return this.isDestroyed()\n    if (this.renderer.isPlay === false) return\n    this.setPlay(false)\n    this.animator.stop()\n    this.video.pause()\n    this.cleanTimer()\n    if (resetToStart) {\n      this.seek(0)\n    }\n  }\n  private videoEvent = (e: any, ...args) => {\n    logger.debug(`[${e.type}]:`)\n    this.eventsFn[e.type] && this.eventsFn[e.type](e, ...args)\n  }\n\n  private loop() {\n    if (!this.op.endPause) {\n      return this.loopChecker.loopCount > 1\n    }\n    return true // this.loopChecker.loopCount > 1\n  }\n\n  private _playVideo() {\n    if (!this.startFlag && !this.op.autoplay) {\n      this.video.pause()\n      logger.info(`_playVideo() this.startFlag is false`)\n      return\n    }\n\n    const videoPromise = this.video.play()\n    if (videoPromise)\n      videoPromise.catch(e => {\n        logger.warn(`_playVideo() error canplaythrough to play`, e.code, e.message, e.name)\n        if (e?.code === 0 && e?.name === EPlayError.NotAllowedError) {\n          this.op?.onError?.({\n            playError: EPlayError.NotAllowedError,\n            video: this.video,\n            playStep: EPlayStep.canplaythrough,\n          })\n        }\n      })\n  }\n\n  private _updateVideoSource(source: string | File) {\n    const op = this.op\n    if (source instanceof File) {\n      op.useVideoDBCache = false\n      this.videoFile = source\n      this.op.videoSource = source.name\n    } else {\n      this.op.videoSource = source\n    }\n  }\n\n  private videoCreate() {\n    //\n    const op = this.op\n    this._updateVideoSource(op.videoUrl)\n\n    // quark & android 必须改变URL 否则 video currentTime 不重置\n    if (polyfill.quark && polyfill.android) {\n      const urlSp = this.op.videoSource.indexOf('?') > -1 ? '&' : '?'\n      this.op.videoSource = `${this.op.videoSource}${urlSp}_quark_${Math.round(Math.random() * 100000)}`\n      this.op.useFrameCache = false\n      this.op.useVideoDBCache = false\n    }\n    //\n    // const videoID = this.op.videoID || getVIdeoId(this.op.videoSource)\n    const videoID = this.op.videoID || this.op.videoSource\n    logger.debug('[videoID]', videoID)\n    const videoElm = videoID ? document.getElementById(videoID) : undefined\n    let video: HTMLVideoElement\n    if (videoElm instanceof HTMLVideoElement) {\n      video = videoElm\n    } else {\n      video = document.createElement('video')\n      video.setAttribute('id', videoID)\n      video.setAttribute('poster', 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7')\n      // 插入video 解决IOS不播放问题\n      document.body.appendChild(video)\n    }\n    // ========== check hevc ==============\n    this.isSupportHevc = isHevc(video)\n    if (this.isSupportHevc && op.hevcUrl) {\n      this._updateVideoSource(op.hevcUrl)\n      op.videoUrl = op.hevcUrl\n      this.op.isHevc = true\n    }\n    //重置 videoID\n    // if (!videoID) {\n    //   videoID = getVIdeoId(this.op.videoSource)\n    // }\n    // video.setAttribute('id', videoID)\n    // ========== ============================\n    if (!this.op.showVideo) {\n      video.style.position = 'fixed' //防止撑开页面\n      video.style.opacity = '0'\n      video.style.left = '-9999px'\n      video.style.top = '9999px'\n      video.style.visibility = 'hidden'\n    }\n    //\n    // video.crossOrigin = 'crossOrigin'\n    /**\n     * metadata 当页面加载后只载入元数据\n     * auto 当页面加载后载入整个视频\n     * none 当页面加载后不载入视频\n     */\n\n    //\n    // video.muted = typeof this.op.mute !== 'undefined' ? this.op.mute : true\n    video.loop = this.loop()\n    video.crossOrigin = 'anonymous'\n    video.autoplay = this.op.autoplay\n    video.preload = 'auto'\n    // video.preload = 'metadata'\n    video.setAttribute('preload', 'auto') // 这个视频优先加载\n    // 标志视频将被“inline”播放，即在元素的播放区域内。\n    video.setAttribute('x5-playsinline', 'true')\n    video.setAttribute('playsinline', 'true')\n    video.setAttribute('webkit-playsinline', 'true')\n    video.setAttribute('x-webkit-airplay', 'allow') //用于禁用使用有线连接的设备(HDMI、DVI等)的远程播放功能。\n\n    // 启用同层H5播放器，就是在视频全屏的时候，div可以呈现在视频层上，也是WeChat安卓版特有的属性。同层播放别名也叫做沉浸式播放\n    video.setAttribute('t7-video-player-type', 'h5')\n    video.setAttribute('x5-video-player-type', 'h5')\n    // UC 内联播放\n    if (polyfill.quark || polyfill.uc) video.setAttribute('renderer', 'standard')\n    return video\n  }\n  private async videoAddEvents() {\n    const video = this.video\n    // register events\n    this.eventsFn.canplaythrough = () => {\n      logger.debug('[canplaythrough paused] ', video.paused)\n      if (video.paused) {\n        logger.debug('[canplaythrough] isPlay=', this.isPlay)\n        if (this.isPlay) {\n          this._playVideo()\n        } else {\n          logger.debug('[canplaythrough] isPlay is false!')\n        }\n      }\n    }\n    this.eventsFn.stalled = () => {\n      this.video.load()\n      // this.start()\n    }\n    this.eventsFn.playing = () => {\n      // this.setPlay(true)\n      //\n      logger.debug('[player]on playing.')\n      this.startEvent()\n      this.onStart && this.onStart()\n      //\n      //隐藏 非自动播放按钮提示\n      this.hidePollyfileTips()\n    }\n    this.eventsFn.pause = () => {\n      logger.debug('[player]on pause.')\n      // this.stop()\n      this.onPause && this.onPause()\n    }\n    this.eventsFn.resume = () => {\n      this.startEvent()\n      this.onResume && this.onResume()\n    }\n    this.eventsFn.ended = () => {\n      const onEnd = this.onEnd\n      this.op.onLoopCount && this.op.onLoopCount({count: 1})\n      this.destroy()\n      onEnd && onEnd()\n    }\n    this.eventsFn.progress = () => {\n      this.onProcess && this.onProcess()\n    }\n    this.eventsFn.stop = () => {\n      this.onStop && this.onStop()\n    }\n    //循环播放的时候触发\n    this.eventsFn.seeked = () => {\n      // logger.debug('=== [seeked] === 重新播放')\n      this.renderer.videoSeekedEvent()\n    }\n    this.eventsFn.error = e => {\n      logger.error(e)\n      this.onError && this.onError(e)\n    }\n    videoEvents.map(name => {\n      video.addEventListener(name, this.videoEvent, false)\n    })\n    // 防止 Safari 暂停 后无法播放\n    document.addEventListener('visibilitychange', this.videoVisbility, false)\n    //\n    //\n    // if (this.op.showVideo) document.body.appendChild(video)\n    // onready\n    return new Promise(resolve => {\n      // IOS 微信会卡住在这里 不能注销 video\n      if (this.onLoadedmetadata) {\n        video.removeEventListener('loadedmetadata', this.onLoadedmetadata)\n      }\n      this.onLoadedmetadata = e => {\n        this.videoEvent(e)\n        resolve(e)\n        logger.debug('[video loadedmetadata]', video.videoWidth, video.videoHeight, video.src.length)\n      }\n      video.addEventListener('loadedmetadata', this.onLoadedmetadata)\n    })\n  }\n  private async videoLoad() {\n    const video = this.video\n    if (this.op.usePrefetch) {\n      const url = await this.prefetch()\n      video.src = url\n      logger.debug('[prefetch url]', url)\n    } else {\n      video.src = this.op.videoSource\n      if (this.op.useMetaData) {\n        const file = await this.getVideoFile()\n        await this.readFileToBlobUrl(file)\n      }\n      logger.debug('[videoSource url]', this.op.videoSource)\n    }\n    video.load()\n    logger.debug('[video load]')\n    await this.videoAddEvents()\n  }\n\n  /**\n   * 页面隐藏时执行\n   */\n  private videoVisbility = () => {\n    logger.debug('[visibilitychange]', document.hidden, 'this.isPlay=', this.isPlay)\n    if (document.hidden) {\n      logger.debug('[visibilitychange] pause')\n      this.video.pause()\n    } else {\n      logger.debug('[visibilitychange] play')\n      if (this.isPlay) {\n        this._playVideo()\n      }\n    }\n  }\n\n  private removeVideoEvent() {\n    //清除监听事件\n    videoEvents.map(name => {\n      this.video.removeEventListener(name, this.videoEvent, false)\n    })\n    //\n    document.removeEventListener('visibilitychange', this.videoVisbility, false)\n    //\n    if (this.video) {\n      this.video.removeEventListener('loadedmetadata', this.onLoadedmetadata, false)\n      this.video.pause()\n      // console.log('[removeVideoEvent]', !(polyfill.weixin && polyfill.ios) && !this.op.videoID)\n      if (!this.op.videoID) {\n        // this.video.src = ''\n        this.video.removeAttribute('src')\n        this.video.load()\n        this.video.remove()\n        // console.log('this.video', this.video, this.video.currentTime, this.video.currentSrc)\n      }\n    }\n  }\n  private revokeObjectURL(tips: string) {\n    if (this.blobUrl) {\n      URL.revokeObjectURL(this.blobUrl)\n      logger.debug(`[${tips} revokeObjectURL]`, this.blobUrl.length)\n      this.blobUrl = undefined as any\n    }\n  }\n  private createObjectURL(blob: Blob | MediaSource): any {\n    logger.debug('[createObjectURL]')\n    return URL.createObjectURL(blob)\n  }\n  public destroy() {\n    if (!this.renderer) return this.isDestroyed()\n    this.revokeObjectURL('destroy')\n    logger.debug('[destroy]')\n    // this.stop()\n    this.setPlay(false)\n    this.removeVideoEvent()\n    this.renderer.destroy()\n    this.animator.destroy()\n    //\n    this.renderer = undefined as any\n    this.animator = undefined as any\n    this.version = undefined as any\n    // 释放 file 文件\n    this.videoFile = undefined\n    this.videoVisbility = undefined\n    this.onLoadedmetadata = undefined\n    this.onStart = undefined\n    this.onResume = undefined\n    this.onPause = undefined\n    this.onStop = undefined\n    this.onProcess = undefined\n    this.onEnd = undefined\n    this.onError = undefined\n    this.cleanTimer()\n    this.videoEvent = undefined\n    this.eventsFn = {}\n  }\n  private async checkVideoCache(): Promise<string | undefined> {\n    try {\n      const d = await db.model().find(this.op.videoSource)\n      if (d) {\n        const {blob, data} = d\n        if (this.op.useMetaData) {\n          if (!data) {\n            logger.debug('[checkVideoCache] cache miss: requires metadata but cache has none')\n            return undefined // 丢弃失效旧缓存并重新请求\n          }\n          this.renderer.videoEntity.setConfig(data)\n        }\n        logger.debug('[checkVideoCache]')\n        this.blobUrl = this.createObjectURL(blob)\n        return this.blobUrl\n      }\n    } catch (e) {\n      logger.error(e)\n    }\n    return undefined\n  }\n  async getVideoFile() {\n    let file\n    if (!this.videoFile) {\n      file = await getVideoByHttp(this.op.videoSource)\n    } else {\n      file = this.videoFile\n    }\n    return file\n  }\n  async prefetch(): Promise<string> {\n    // const URL = (window as any).webkitURL || window.URL\n    // const polyfillCreateObjectURL = polyfill.baidu || ((polyfill.quark || polyfill.uc) && polyfill.android)\n    //\n    // const polyfillCreateObjectURL = (polyfill.baidu || polyfill.quark || polyfill.uc) && this.op.forceBlob === false\n    //\n    if (this.op.useVideoDBCache && !this.polyfillCreateObjectURL) {\n      const url = await this.checkVideoCache()\n      if (url) return url\n    }\n    //\n    const file = await this.getVideoFile()\n    const url = await this.readFileToBlobUrl(file)\n    logger.debug('[prefetch result]', url, `this.op.useVideoDBCache`, this.op.useVideoDBCache)\n    return url\n  }\n  private readFileToBlobUrl(file): Promise<string> {\n    return new Promise((resolve, reject) => {\n      const fileReader = new FileReader()\n      fileReader.readAsDataURL(file)\n      fileReader.onloadend = () => {\n        let rs = fileReader.result as string\n        let raw = atob(rs.slice(rs.indexOf(',') + 1)) //获取视频信息\n        /**\n         * 判断 videoUrl 资源 是否为 H.265\n         */\n        const codecRegex = /H.265\\/HEVC/\n        const isHevc = codecRegex.test(raw)\n        if (isHevc) {\n          this.op.isHevc = true\n        }\n        /**\n         * 根据 useMetaData 获取 yy视频 metadata 信息\n         */\n        let data: VideoAnimateType\n        if (this.op.useMetaData) {\n          data = parser.getdata(raw)\n          if (data) {\n            this.renderer.videoEntity.setConfig(data)\n          }\n        }\n        //\n        if (!this.polyfillCreateObjectURL) {\n          const buf = Array(raw.length)\n          for (let d = 0; d < raw.length; d++) {\n            buf[d] = raw.charCodeAt(d)\n          }\n          const arr = new Uint8Array(buf)\n          const blob = new Blob([arr], {type: 'video/mp4'})\n          // 返回 metadata 数据\n          if (this.op.useVideoDBCache) {\n            db.model().insert(this.op.videoSource, {blob, data})\n          }\n          this.blobUrl = this.createObjectURL(blob)\n          resolve(this.blobUrl)\n        } else {\n          //获取 data 后 原路返回\n          resolve(this.op.videoSource)\n        }\n        // gc\n        rs = undefined\n        raw = undefined\n      }\n    })\n  }\n}\n","import config from 'src/helper/config'\nimport {logger, versionTips} from 'src/helper/logger'\nimport Player from 'src/player'\nimport {polyfill, wechatPolyfill} from './helper/polyfill'\nimport {isOffscreenCanvasSupported} from './helper/utils'\nimport type {MixEvideoOptions} from './type/mix'\n\nconst DEFAULT_OPTIONS: Partial<MixEvideoOptions> = {\n  showVideo: false,\n  useWorker: false,\n  loop: true,\n  autoplay: true,\n  videoUrl: '',\n  videoID: null,\n  dataUrl: '',\n  offset: 0,\n  usePrefetch: true,\n  useBitmap: true,\n  useAccurate: true,\n  useMetaData: false,\n  alphaDirection: 'left',\n  useVideoDBCache: true,\n  useFrameCache: false,\n  useOfsRender: false,\n  resizeCanvas: 'percent',\n  showPlayerInfo: true,\n  forceBlob: false,\n  checkTimeout: false,\n  endPause: false,\n  font: { overflow: 'cut' },\n}\n\nconst EVENTS = ['Start', 'Stop', 'End', 'Pause', 'Resume', 'Process', 'Error'] as const\n\nasync function yyEva(options: MixEvideoOptions): Promise<Player> {\n  const op = { ...DEFAULT_OPTIONS, ...options }\n\n  // 功能特性检测与降级处理\n  const featureChecks = {\n    bitmap: () => self.createImageBitmap,\n    offscreen: () => isOffscreenCanvasSupported() && op.useOfsRender,\n    indexedDB: () => self.indexedDB,\n    accurate: () => !(polyfill.android && polyfill.baidu)\n  }\n\n  if (!featureChecks.bitmap()) op.useBitmap = false\n  if (!featureChecks.offscreen()) {\n    op.useOfsRender = false\n    op.useFrameCache = false\n  }\n  if (!featureChecks.indexedDB()) op.useVideoDBCache = false\n  if (!featureChecks.accurate()) op.useAccurate = false\n\n  // 特殊配置处理\n  if (op.useMetaData) op.usePrefetch = true\n  if (op.useFrameCache) op.useOfsRender = true\n\n  // 日志设置\n  logger.setup({level: op.logLevel, showtips: !!op.showPlayerInfo})\n\n  // 微信环境处理\n  if (polyfill.weixin && polyfill.ios) await wechatPolyfill.wxReady()\n\n  // 创建播放器实例\n  const player = new Player(op)\n\n  // 绑定事件\n  EVENTS.forEach(event => {\n    const handler = op[`on${event}`]\n    if (handler) player[`on${event}`] = handler\n  })\n\n  // 初始化播放器\n  await player.setup()\n  op.showPlayerInfo && versionTips(op, player)\n  op.onGetConfig?.(op)\n\n  return player\n}\n\nexport const version = config.version\nexport const mode = config.mode\nexport {yyEva, wechatPolyfill}\nexport type YYEvaType = Player\nexport type YYEvaOptionsType = MixEvideoOptions\nexport default yyEva\n"],"mappings":"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"}