Komponente aus 'importieren. /component.js ';
importiere mergeOptions aus './utils/merge-options.js';
dokument aus 'global/document' importieren;
importiere * as browser aus './utils/browser.js';
import window from 'global/window';
import * as Fn from './utils/fn.js';

konstante Standardwerte = {
  Schwellenwert für die Nachverfolgung: 20,
  Lebenstoleranz: 15
};

/*
  verfolgen, wann wir am Live-Rand sind, und andere Helfer für die Live-Wiedergabe */

/**
 * Eine Klasse, in der die aktuelle Uhrzeit überprüft und festgestellt wird, wann der Spieler
 * befindet sich am oder hinter dem Live-Edge.
 * /
Klasse LiveTracker erweitert Komponente {

  /**
   * Erzeugt eine Instanz dieser Klasse.
   *
   * @param {Player} Spieler
   *        Der `Player`, dem diese Klasse zugeordnet werden soll.
   *
   * @param {Object} [Optionen]
   *        Der Schlüssel/Wertspeicher der Playeroptionen.
   *
   * @param {Zahl} [options.trackingThreshold=20]
   * Anzahl der Sekunden des Live-Fensters (SeekableEnd - SeekableStart), die
   * Die Medien müssen dies haben, bevor das Liveui gezeigt wird.
   *
   * @param {Zahl} [options.LiveTolerance=15]
   * Anzahl der Sekunden hinter dem Live-Spiel, die wir haben müssen
   * bevor wir als nicht lebend gelten. Beachten Sie, dass dies nur
   * kann verwendet werden, wenn am Live-Edge gespielt wird. Dies ermöglicht ein großes durchsuchbares Ende
   * Änderungen haben keinen Einfluss darauf, ob wir live sind oder nicht.
   * /
  constructor(spieler, optionen) {
    //LiveTracker benötigt kein Element
    const options_ = mergeOptions (Standardwerte, Optionen, {createEl: falsch});

    super(spieler, optionen_);

    this.handleVisibilityChange_ = (e) => this.handleVisibilityChange (e);
    this.trackLiveHandler_ = () => this.trackLive_ ();
    this.handlePlay_ = (e) => this.handlePlay (e);
    this.handleFirstTimeUpdate_ = (e) => this.handleFirstTimeUpdate (e);
    this.handleSeeked_ = (e) => this.handleSeeked (e);
    this.seekToLiveEdge_ = (e) => this.seekToLiveEdge (e);

    this.reset_();

    this.on (this.player_, 'durationchange', (e) => this.handleDurationChange (e));
    //wir sollten versuchen, das Tracking auf Canplay als native Playback-Engines wie Safari umzuschalten
    //hat bis dahin möglicherweise nicht die richtigen Werte für Dinge wie seekableEnd
    this.on (this.player_, 'canplay', () => this.toggleTracking ());

    //Wir müssen die Live-Wiedergabe nicht verfolgen, wenn das Dokument versteckt ist,
    //außerdem kann nachverfolgt werden, wann das Dokument versteckt ist
    //die CPU in die Höhe treiben und schließlich die Seite auf IE11 zum Absturz bringen.
    if (browser.IE_Version && 'versteckt' im Dokument && 'VisibilityState' im Dokument) {
      this.on (document, 'visibilitychange', this.handleVisibilityChange_);
    }
  }

  /**
   * Schalten Sie die Nachverfolgung basierend auf der Sichtbarkeit von Dokumenten ein
   * /
  handleVisibilityChange () {
    wenn (this.player_.duration ()! == Unendlichkeit) {
      rückkehr;
    }

    wenn (document.hidden) {
      this.stopTracking();
    } sonst {
      this.startTracking();
    }
  }

  /**
   * alle Funktionen zur Nachverfolgung von Änderungen am Ende der Suche
   * und um zu verfolgen, wie weit wir nach dem Ende der Woche sein sollten
   * /
  TrackLive_ () {
    const seekable = this.player_.seekable();

    //undefiniertes Suchbares überspringen
    wenn (! suchbar ||! suchbar.länge) {
      rückkehr;
    }

    const newTime = Zahl (window.performance.now () .toFixed (4));
    const deltaTime = this.LastTime_ === -1? 0: (NewTime - this.LastTime_)/1000;

    this.lastTime_ = Neue Uhrzeit;

    this.pastSeekend_ = this.PastSeekend () + deltaTime;

    const liveCurrentTime = this.liveCurrentTime();
    const currentTime = this.player_.currentTime ();

    //wir stehen hinter live, falls welche stimmen
    //1. der Spieler ist angehalten
    //2. Der Benutzer hat zu einem Ort gesucht, der 2 Sekunden vom Live-Stream entfernt ist
    //3. der Unterschied zwischen Live-Zeit und aktueller Zeit ist größer
    //LiveTolerance, die standardmäßig auf 15s gesetzt ist
    let isBehind = this.player_.paused () || this.seekedBehindLive_ ||
      Math.abs (LiveCurrentTime - CurrentTime) > this.options_.liveTolerance;

    //wir können nicht hinterherhinken, wenn
    //1. bis wir noch kein Timeupdate gesehen haben
    //2. LiveCurrentTime ist Infinity, was auf Android und Native Safari passiert
    wenn (! this.timeUpdateSeen_ || liveCurrentTime === Unendlich) {
      isBehind = falsch;
    }

    if (isBehind! == Das.hinter LiveEdge_) {
      this.behindLiveEdge_ = istHinten;
      this.trigger('liveedgechange');
    }
  }

  /**
   * wickle ein Ereignis zur Änderung der Dauer des Spielers ab
   * und starten/beenden Sie das Tracking entsprechend.
   * /
  hat DurationChange () behandelt {
    this.toggleTracking ();
  }

  /**
   * Tracking starten/beenden
   * /
  ToggleTracking () {
    if (this.player_.duration () === Infinity && this.liveWindow () >= this.options_.trackingThreshold) {
      wenn (this.player_.options_.liveui) {
        this.player_.addClass ('vjs-liveui');
      }
      this.startTracking();
    } sonst {
      this.player_.removeClass ('vjs-liveui');
      this.stopTracking();
    }
  }

  /**
   * beginnen Sie mit dem Verfolgen der Live-Wiedergabe
   * /
  startTracking() {
    wenn (this.isTracking ()) {
      rückkehr;
    }

    //Wenn wir kein Timeupdate gesehen haben, müssen wir überprüfen, ob die Wiedergabe erfolgt
    //begann, bevor diese Komponente mit dem Tracking begann. Das kann häufig passieren
    //wenn Autoplay verwendet wird.
    if (!this.timeupdateSeen_) {
      this.timeUpdateSeen_ = this.player_.hasStarted ();
    }

    this.trackingInterval_ = this.setInterval (this.trackLiveHandler_, fn.update_refresh_interval);
    this.trackLive_();

    this.on (this.player_, ['play', 'pause'], this.trackLiveHandler_);

    if (!this.timeupdateSeen_) {
      this.one (this.player_, 'play', this.handlePlay_);
      this.one (this.player_, 'timeupdate', this.handleFirstTimeUpdate_);
    } sonst {
      this.on(this.player_, 'seeked', this.handleSeeked_);
    }
  }

  /**
   * kümmere dich um das erste Update auf dem Player, falls es nicht schon gespielt wurde
   * als der Live-Tracker mit dem Tracking begann.
   * /
  handleFirstTimeUpdate () {
    this.timeUpdateSeen_ = wahr;
    this.on(this.player_, 'seeked', this.handleSeeked_);
  }

  /**
   * Behalte im Auge, wann eine Suche beginnt, und höre auf Gesuchte
   * um herauszufinden, wo eine Suche endet.
   * /
  handleSeeked () {
    const timeDiff = Math.ABS (this.liveCurrentTime () - this.player_.currentTime ());

    this.seekedBehindLive_ = this.NextSeekedFromUser_ & TimeDiff > 2;
    this.nextSeekedFromUser_ = false;
    this.trackLive_();
  }

  /**
   * das erste Spiel mit dem Spieler abwickeln und sicherstellen, dass wir danach suchen
   * direkt zum Live-Edge.
   * /
  Handle Play () {
    this.one (this.player_, 'timeupdate', this.seekToLiveEdge_);
  }

  /**
   * Stoppen Sie das Tracking und setzen Sie alle internen Variablen auf
   * ihr Anfangswert.
   * /
  zurücksetzen_ () {
    this.LastTime_ = -1;
    this.pastSeekEnd_ = 0;
    this.lastSeekEnd_ = -1;
    this.BehindLiveEdge_ = wahr;
    this.timeUpdateSeen_ = falsch;
    this.seekedBehindLive_ = false;
    this.nextSeekedFromUser_ = false;

    this.clearInterval (this.trackingInterval_);
    this.trackingInterval_ = null;

    this.off (this.player_, ['play', 'pause'], this.trackLiveHandler_);
    this.off (this.player_, 'gesucht', this.handleSeeked_);
    this.off (this.player_, 'play', this.handlePlay_);
    this.off (this.player_, 'timeupdate', this.handleFirstTimeUpdate_);
    this.off (this.player_, 'timeupdate', this.seekToLiveEdge_);
  }

  /**
   * Das nächste gesuchte Ereignis stammt vom Benutzer. Das bedeutet, dass jede Suche
   * > 2 Sekunden hinter dem Live-Spiel werden als real hinter dem Live-Rückstand gewertet und
   * LiveTolerance wird ignoriert.
   * /
  NextSeekedFromUser () {
    this.nextSeekedFromUser_ = wahr;
  }

  /**
   * Stoppen Sie die Live-Wiedergabe
   * /
  stopTracking() {
    wenn (! this.isTracking ()) {
      rückkehr;
    }
    this.reset_();
    this.trigger('liveedgechange');
  }

  /**
   * Ein Helfer, der dem Spieler ein suchbares Ende bereitet
   * damit wir nicht überall eine Nullprüfung durchführen müssen
   *
   * @return {number}
   * Das am weitesten gesuchte Ende oder Unendlichkeit.
   * /
  suchbares Ende () {
    const seekable = this.player_.seekable();
    const seekableEnds = [];
    let i = seekable ? seekable.length : 0;

    while (i--) {
      seekableEnds.push (seekable.end (i));
    }

    //schnapp dir nach dem Sortieren das am weitesten durchsuchbare Ende, oder falls es keins gibt
    //Standard ist Infinity
    seekableEnds.length zurückgeben? seekableEnds.sort () [seekableEnds.Länge - 1]: Unendlichkeit;
  }

  /**
   * Ein Helfer, der dem Spieler einen suchbaren Start ermöglicht
   * damit wir nicht überall eine Nullprüfung durchführen müssen
   *
   * @return {number}
   * Der früheste suchbare Start oder 0.
   * /
  seekableStart () {
    const seekable = this.player_.seekable();
    const seekableStarts = [];
    let i = seekable ? seekable.length : 0;

    while (i--) {
      seekableStarts.push (seekable.start (i));
    }

    //schnapp dir den ersten suchbaren Start nach der Sortierung, oder falls es keine gibt
    //Standard ist 0
    seekableStarts.length zurückgeben? seekableStarts.sort () [0]: 0;
  }

  /**
   * Holen Sie sich das Live-Zeitfenster aka
   * die Zeitspanne zwischen dem Start von seekable und
   * aktuelle Live-Zeit.
   *
   * @return {number}
   * Die Anzahl der Sekunden, in denen gesucht werden kann
   * das Live-Video.
   * /
  Live-Fenster () {
    const liveCurrentTime = this.liveCurrentTime();

    //wenn liveCurrenTime Infinity ist, haben wir überhaupt kein LiveWindow
    if (LiveCurrentTime === Unendlich) {
      0 zurückgeben;
    }

    gib liveCurrentTime zurück - this.seekableStart ();
  }

  /**
   * Stellt fest, ob der Spieler live ist, prüft nur, ob diese Komponente
   * verfolgt die Live-Wiedergabe oder nicht
   *
   * @return {boolean}
   * Ob LiveTracker verfolgt
   * /
  ist live () {
    gib this.isTracking () zurück;
  }

  /**
   * Stellt fest, ob CurrentTime am Live-Edge ist und nicht ins Hintertreffen gerät
   * bei jeder suchbaren Endänderung
   *
   * @return {boolean}
   * Ob die Wiedergabe am Live-Rand erfolgt
   * /
  bei LiveEdge () {
    kehre zurück! Das.hinter LiveEdge ();
  }

  /**
   * Holen Sie sich die von uns erwartete aktuelle Live-Zeit
   *
   * @return {number}
   * Die erwartete aktuelle Live-Zeit
   * /
  LiveAktuelle Uhrzeit () {
    gib this.pastSeekend () + this.seekableEnd (); zurück
  }

  /**
   * Die Anzahl der Sekunden, die nach dem Ende von Seekable vergangen sind
   * geändert. Dies wird auf 0 zurückgesetzt, sobald sich das suchbare Ende ändert.
   *
   * @return {number}
   * Sekunden nach dem aktuellen suchbaren Ende
   * /
  vergangenes Wochenende () {
    const seekableEnd = this.seekableEnd ();

    wenn (this.lastSeekend_! = -1 & SeekableEnd! == Das.LastSeekend_) {
      this.pastSeekEnd_ = 0;
    }
    this.lastSeekEnd_ = Suchbares Ende;
    gib this.pastSeekend_ zurück;
  }

  /**
   * Wenn wir uns gerade hinter dem Live-Edge befinden, wird auch CurrentTime genannt
   * hinter einer absehbaren Endänderung
   *
   * @return {boolean}
   * Wenn wir hinter dem Live-Rand sind
   * /
  Hinter LiveEdge () {
    gib this.BehindLiveEdge_ zurück;
  }

  /**
   * Ob der Live-Tracker gerade verfolgt oder nicht.
   * /
  Ist nachverfolgbar () {
    return typeofthis.trackingInterval_ === 'Nummer';
  }

  /**
   * Suche nach dem Live-Edge, wenn wir uns hinter dem Live-Edge befinden
   * /
  SeektoLiveEdge () {
    this.seekedBehindLive_ = false;
    wenn (this.atLiveEdge ()) {
      rückkehr;
    }
    this.nextSeekedFromUser_ = false;
    this.player_.currentTime (this.liveCurrentTime ());

  }

  /**
   * LiveTracker entsorgen
   * /
  dispose() {
    this.off (document, 'visibilitychange', this.handleVisibilityChange_);
    this.stopTracking();
    super.dispose();
  }
}

component.registerComponent ('LiveTracker', LiveTracker);
Exportieren Sie den Standard-LiveTracker;