/**
 * @file html5.js
 * /
importiere Tech aus './tech.js';
import * as Dom from '../utils/dom.js';
import * as Url from '../utils/url.js';
import log from '../utils/log.js';
import * as browser from '../utils/browser.js';
dokument aus 'global/document' importieren;
import window from 'global/window';
importiere {assign} von '../utils/obj';
import mergeOptions from '../utils/merge-options.js';
importiere {toTitleCase} aus '../utils/string-cases.js';
importiere {NORMAL als TRACK_TYPES, REMOTE} aus '.. /tracks/track-Typen ';
importiere SetupSourceSet aus '. /setup-sourceset ';
importiere defineLazyProperty aus '.. /utils/define-lazy-property.js ';
importiere {silencePromise} von '../utils/promise';

/**
 * HTML5 Media Controller - Wrapper für die HTML5-Medien-API
 *
 * @mixes Tech~SourceHandlerAdditions
 * @extends Technik
 * /
Klasse Html5 erweitert Tech {

  /**
  * Erstellen Sie eine Instanz dieser Tech.
  *
  * @param {Object} [Optionen]
  *        Der Schlüssel/Wertspeicher der Playeroptionen.
  *
  * @param {Component~ReadyCallback} ready
  *        Callback-Funktion, die aufgerufen wird, wenn die "HTML5"-Technologie bereit ist.
  * /
  Konstruktor (Optionen, bereit) {
    super (Optionen, bereit);

    const source = options.source;
    sei crossOriginTracks = falsch;

    this.featuresVideoFrameCallback = this.featuresVideoFrameCallback && this.el_.tagName === 'VIDEO';

    //Setze die Quelle, falls eine angegeben ist
    //1) Überprüfe, ob die Quelle neu ist (falls nicht, wollen wir das Original behalten, damit die Wiedergabe nicht unterbrochen wird)
    //2) Überprüfe, ob der Netzwerkstatus des Tags bei der Initialisierung ausgefallen ist, und falls ja, setze die Quelle zurück
    //jedenfalls, damit der Fehler ausgelöst wird.
    if (source && (this.el_.currentSrc! == source.src | (options.tag & options.tag.initNetworkState_ === 3)) {
      this.setSource (Quelle);
    } sonst {
      this.handleLateInit_ (this.el_);
    }

    //Source-Set nach dem späten Sourceset/Init einrichten
    wenn (options.enableSourceSet) {
      this.setupSourceSetHandling_ ();
    }

    this.isScrubbing_ = falsch;

    wenn (this.el_.hasChildNodes ()) {

      const nodes = this.el_.childNodes;
      sei nodesLength = nodes.length;
      const removeNodes = [];

      während (nodesLength--) {
        const node = Knoten [NodesLength];
        const nodeName = node.nodeName.toLowerCase ();

        if (nodeName === 'track') {
          if (!this.featuresNativeTextTracks) {
            //Leere Video-Tag-Tracks, damit der eingebaute Player sie nicht auch verwendet.
            //Dies ist möglicherweise nicht schnell genug, um zu verhindern, dass HTML5-Browser die Tags lesen
            //also müssen wir alle Standard-Tracks ausschalten, wenn wir das manuell machen
            //Bildunterschriften und Untertitel. videoElement.TextTracks
            removeNodes.push (Knoten);
          } sonst {
            // HTMLTrackElement und TextTrack in entfernter Liste speichern
            this.remoteTextTrackels () .addTrackElement_ (Knoten);
            this.remoteTextTracks () .addTrack (node.track);
            this.textTracks () .addTrack (node.track);
            wenn (! CrossOrigin Tracks &
                ! this.el_.hasAttribute ('Crossorigin') &&
                URL.isCrossOrigin (node.src)) {
              crossOriginTracks = wahr;
            }
          }
        }
      }

      für (sei i = 0; i < removeNodes.length; i++) {
        this.el_.removeChild (removeNodes [i]);
      }
    }

    this.proxyNativeTracks_ ();
    wenn (this.featuresNativeTextTracks & crossOriginTracks) {
      log.warn ('Text-Tracks werden von einem anderen Ursprung geladen, aber das Cross-Origin-Attribut wird nicht verwendet. \ n' +
            'Dadurch können Texttracks möglicherweise nicht geladen werden. ');
    }

    //verhindert, dass iOS Safari Metadatentexttracks während der nativen Wiedergabe deaktiviert
    this.restoreMetadatataTracksInioNativePlayer_ ();

    //Lege fest, ob native Steuerelemente verwendet werden sollen
    //Unser Ziel sollte es sein, die benutzerdefinierten Steuerelemente überall auf Mobilgeräten verfügbar zu machen
    //damit wir das alles zusammen entfernen können. Im Moment wird das benutzerdefinierte blockiert
    //Steuerung auf berührungsfähigen Laptops wie dem Chrome Pixel
    if (browser.TOUCH_ENABLED || Browser.IS_iPhone |
        browser.is_native_Android) && options.nativeControlsForTouch === wahr) {
      this.setControls (wahr);
    }

    //unter iOS wollen wir `webkitbeginfullscreen` und `webkitendfullscreen` als Proxy verwenden
    //in ein `fullscreenchange`-Event
    this.proxyWebKitFullScreen_ ();

    this.triggerReady();
  }

  /**
   * Entsorgen Sie das `HTML5` -Medienelement und entfernen Sie alle Spuren.
   * /
  dispose() {
    wenn (this.el_ && this.el_.resetSourceSet_) {
      this.el_.resetSourceSet_ ();
    }
    html5.disposeMediaElement (this.el_);
    this.options_ = null;

    //Der Techniker kümmert sich um das Löschen der emulierten Titelliste
    super.dispose();
  }

  /**
   * Ändern Sie das Medienelement so, dass wir erkennen können, wann
   * Die Quelle wurde geändert. Löst `sourceset` unmittelbar nachdem sich die Quelle geändert hat
   * /
  setupSourceSetHandling_ () {
    setupSourceSet (dies);
  }

  /**
   * Wenn ein Untertitel-Track im iOS Safari Native Player aktiviert ist, werden alle anderen
   * Tracks sind deaktiviert (einschließlich Metadaten-Tracks), wodurch alle ihre Tracks auf Null gesetzt werden
   * zugehörige Cue-Points. Dadurch werden die Metadatenspuren im Vollbildmodus wiederhergestellt
   * geben Sie in diesen Fällen an, damit Cue-Points nicht unnötig verloren gehen.
   *
   * @privat
   * /
  Wiederherstellung von Metadatenspursen in iOSNativePlayer_ () {
    const textTracks = this.textTracks ();
    let metadataTracksPreFullScreenState;

    //erfasst eine Momentaufnahme des aktuellen Zustands jedes Metadatenspurses
    const takeMetaDataTrackSnapshot = () => {
      metadatatracksPreFullScreenState = [];

      für (sei i = 0; i < textTracks.length; i++) {
        const track = TextTracks [i];

        if (track.kind === 'Metadaten') {
          metadatatracksPreFullScreenState.push ({
            titel,
            Gespeichert: track.mode
          });
        }
      }
    };

    //Snapshot des Ausgangszustands jedes Metadaten-Tracks und aktualisiere den Snapshot
    //jedes Mal gibt es ein Track-Change-Event
    takeMetaDataTrackSnapshot ();
    textTracks.addEventListener('change', takeMetadataTrackSnapshot);

    this.on ('dispose', () => textTracks.removeEventListener ('ändern', takeMetadataTrackSnapshot));

    const restoreTrackMode = () => {
      für (sei i = 0; i < MetadataTracksPreFullScreenState.length; i++) {
        const storedTrack = metadataTracksPreFullScreenState [i];

        if (storedTrack.track.mode === 'deaktiviert' && StoredTrack.track.mode! == StoredTrack.storedMode) {
          storedTrack.track.mode = StoredTrack.StoredMode;
        }
      }
      //Wir wollen nur, dass dieser Handler beim ersten 'Change' Event ausgeführt wird
      textTracks.removeEventListener('change', restoreTrackMode);
    };

    //Wenn wir die Vollbildwiedergabe starten, beenden Sie die Aktualisierung des Snapshots und
    //setze alle Track-Modi in den Zustand vor dem Vollbildmodus zurück
    this.on ('webkitbeginfullscreen', () => {
      textTracks.removeEventListener('change', takeMetadataTrackSnapshot);

      // Entfernen Sie den Hörer, bevor Sie ihn hinzufügen, nur für den Fall, dass er vorher nicht entfernt wurde
      textTracks.removeEventListener('change', restoreTrackMode);
      textTracks.addEventListener ('ändern', restoreTrackMode);
    });

    //starte die Aktualisierung des Snapshots erneut, nachdem du den Vollbildmodus verlassen hast
    this.on ('webkitendfullscreen', () => {
      // Entfernen Sie den Hörer, bevor Sie ihn hinzufügen, nur für den Fall, dass er vorher nicht entfernt wurde
      textTracks.removeEventListener('change', takeMetadataTrackSnapshot);
      textTracks.addEventListener('change', takeMetadataTrackSnapshot);

      //entferne den RestoreTrackMode-Handler, falls er während der Vollbildwiedergabe nicht ausgelöst wurde
      textTracks.removeEventListener('change', restoreTrackMode);
    });
  }

  /**
   * Versuch, das Überschreiben von Tracks für den angegebenen Typ zu erzwingen
   *
   * @param {string} type — Der Titeltyp soll überschrieben werden, mögliche Werte beinhalten 'Audio',
   * „Video“ und „Text“.
   * @param {boolean} override — Wenn dieser Wert auf true gesetzt ist, wird natives Audio/Video überschrieben,
   * Andernfalls wird möglicherweise natives Audio/Video verwendet.
   * @privat
   * /
  overrideNative_ (Typ, überschreiben) {
    //Wenn es keine Verhaltensänderung gibt, füge keine Listener hinzu/entferne sie
    if (überschreiben! == diese [`featuresNative$ {type} Tracks`]) {
      rückkehr;
    }

    const lowerCaseType = type.toLowerCase ();

    wenn (dies [`$ {lowerCaseType} tracksListeners_`]) {
      object.keys (this [`$ {lowerCaseType} tracksListeners_`]) .forEach ((EventName) => {
        const elTracks = this.el () [`$ {lowerCaseType} Titel`];

        eltracks.removeEventListener (EventName, dieser [`$ {lowerCaseType} tracksListeners_`] [EventName]);
      });
    }

    this [`featuresNative$ {type} Tracks`] =! überschreiben;
    dieser [`$ {lowerCaseType} tracksListeners_`] = null;

    this.proxyNativeTracksForType_ (LowerCaseType);
  }

  /**
   * Versuch, die Überschreibung der nativen Audiospuren zu erzwingen.
   *
   * @param {boolean} override - Wenn auf true gesetzt, wird das native Audio außer Kraft gesetzt,
   * andernfalls wird möglicherweise natives Audio verwendet.
   * /
  OverrideNativeAudioTracks (überschreiben) {
    this.overrideNative_ ('Audio', überschreiben);
  }

  /**
   * Versuch, die Überschreibung der nativen Videospuren zu erzwingen.
   *
   * @param {boolean} override - Wenn auf true gesetzt, wird natives Video außer Kraft gesetzt,
   * andernfalls wird möglicherweise natives Video verwendet.
   * /
  OverrideNativeVideoTracks (überschreiben) {
    this.overrideNative_ ('Video', überschreiben);
  }

  /**
   * Proxy native Tracklist-Events für den angegebenen Typ an unseren Track
   * listet auf, ob der Browser, in dem wir spielen, diese Art von Titelliste unterstützt.
   *
   * @param {string} name — Titeltyp; zu den Werten gehören „Audio“, „Video“ und „Text“
   * @privat
   * /
  proxyNativeTracksForType_ (Name) {
    const props = TRACK_TYPES[name];
    const elTracks = this.el () [props.getterName];
    const techTracks = this [props.getterName] ();

    wenn (! diese [`featuresNative$ {props.capitalName} Tracks`] ||
        ! ELTracks |
        ! eltracks.addEventListener) {
      rückkehr;
    }
    konstante Zuhörer = {
      ändern: (e) => {
        konstANTES EREIGNIS = {
          Typ: 'ändern',
          Ziel: TechTracks,
          Aktuelles Ziel: TechTracks,
          ScrElement: TechTracks
        };

        techTracks.trigger (Ereignis);

        //Wenn wir ein Texttrack-Change-Event sind, sollten wir auch die benachrichtigen
        //Trackliste per Remote-Text. Dies kann möglicherweise zu einem falsch positiven Ergebnis führen
        //wenn wir ein Change-Event auf einer Strecke haben würden, die nicht aus der Ferne liegt und
        //wir haben das Event auf der Remote-Texttrackliste ausgelöst, was nicht der Fall ist
        //diesen Track enthalten. Bewährte Verfahren bedeuten jedoch, sich durch die
        //Liste der Tracks und Suche nach dem passenden Moduswert, also
        //das sollte kein Problem darstellen
        wenn (Name === 'Text') {
          this [remote.remoteText.getterName] () .trigger (Ereignis);
        }
      },
      Titel hinzufügen (e) {
        techtracks.addTrack (z. B. track);
      },
      Track entfernen (e) {
        techtracks.removeTrack (z. B. Track);
      }
    };
    const removeOldTracks = Funktion () {
      const removeTracks = [];

      für (sei i = 0; i < TechTracks.Length; i++) {
        gefunden lassen = falsch;

        für (sei j = 0; j < elTracks.Length; j++) {
          wenn (elTracks [j] === TechTracks [i]) {
            gefunden = wahr;
            pause;
          }
        }

        wenn (! gefunden) {
          removeTracks.push (TechTracks [i]);
        }
      }

      während (removeTracks.length) {
        techTracks.removeTrack (removeTracks.shift ());
      }
    };

    this [props.getterName + 'Listeners_'] = Zuhörer;

    Object.keys (Listener) .forEach ((EventName) => {
      const listener = Listener [EventName];

      eltracks.addEventListener (Ereignisname, Listener);
      this.on ('dispose', (e) => elTracks.removeEventListener (EventName, Listener));
    });

    //Entferne (native) Tracks, die nicht mehr verwendet werden
    this.on ('loadstart', entferne alte Tracks);
    this.on ('dispose', (e) => this.off ('loadstart', removeOldTracks));
  }

  /**
   * Proxy alle nativen Titellistenereignisse an unsere Titellisten, wenn der Browser, den wir spielen
   * in unterstützt diese Art von Titelliste.
   *
   * @privat
   * /
  Proxy Native Tracks _ () {
    TRACK_TYPES.names.forEach((name) => {
      this.proxyNativeTracksForType_ (Name);
    });
  }

  /**
   * Erstellen Sie das DOM-Element von `Html5` Tech.
   *
   * @return {Element}
   *         Das Element, das erstellt wird.
   * /
  createEl() {
    sei el = this.options_.tag;

    //Prüfe, ob dieser Browser das Verschieben des Elements in die Box unterstützt.
    //Auf dem iPhone geht das Video kaputt, wenn du das Element bewegst,
    //Also müssen wir ein brandneues Element erstellen.
    //Wenn wir das Player-Div aufgenommen haben, müssen wir das Medienelement nicht verschieben.
    wenn (! de |
        ! (this.options_.playerElingest ||
          this.movingMediaElementIndom)) {

      //Wenn das ursprüngliche Tag noch da ist, klone und entferne es.
      wenn (el) {
        const clone = el.cloneNode (wahr);

        if (el.parentNode) {
          el.parentNode.insertBefore (clone, el);
        }
        html5.disposeMediaElement (de);
        el = Klon;

      } sonst {
        el = document.createElement ('Video');

        //bestimmt, ob native Steuerelemente verwendet werden sollen
        const tagAttributes = this.options_.tag && dom.getAttributes (this.options_.tag);
        konstante Attribute = mergeOptions ({}, tagAttributes);

        wenn (! browser.TOUCH_ENABLED || this.options_.NativeControls for Touch! == wahr) {
          lösche attributes.controls;
        }

        dom.setAttributes (
          el,
          zuweisen (Attribute, {
            id: this.options_.techId,
            Klasse: 'vjs-tech'
          })
        );
      }

      el.playerId = this.options_.playerId;
    }

    if (type of this.options_.preload! == 'undefiniert') {
      dom.setAttribute (el, 'preload', this.options_.preload);
    }

    if (this.options_.disablePictureInPicture! == undefiniert) {
      el.disablePictureInPicture = this.options_.disablePictureInPicture;
    }

    //Aktualisiere bestimmte Tag-Einstellungen, falls sie überschrieben wurden
    //`autoplay` muss *letzt* sein, damit `muted` und `playsinline` vorhanden sind
    //wenn iOS/Safari oder andere Browser versuchen, automatisch abzuspielen.
    const settingSatTRS = ['Loop', 'stummgeschaltet', 'spielt online', 'Autoplay'];

    für (sei i = 0; i < settingsAttrs.length; i++) {
      const attr = EinstellungenAttrs [i];
      konstanter Wert = this.options_ [attr];

      if (typeof wert !== 'undefined') {
        wenn (Wert) {
          dom.setAttribute (el, attr, attr);
        } sonst {
          dom.removeAttribute (el, attr);
        }
        el [attr] = Wert;
      }
    }

    zurück el;
  }

  /**
   * Dies wird ausgelöst, wenn das Loadstart-Ereignis bereits ausgelöst wurde, bevor videojs
   * bereit. Zwei bekannte Beispiele dafür, wann dies passieren kann, sind:
   * 1. Wenn wir das Wiedergabeobjekt laden, nachdem es mit dem Laden begonnen hat
   * 2. Die Medien spielen dann schon das (oft mit Autoplay an)
   *
   * Diese Funktion löst einen weiteren Loadstart aus, damit videojs aufholen kann.
   *
   * @fires Technik #loadstart
   *
   * @return {undefined}
   * gibt nichts zurück.
   * /
  handleLateInit_ (de) {
    wenn (el.NetworkState === 0 || el.NetworkState === 3) {
      //Das Videoelement hat noch nicht begonnen, die Quelle zu laden
      //oder habe keine Quelle gefunden
      rückkehr;
    }

    wenn (el.ReadyState === 0) {
      //NetworkState wird synchron gesetzt ABER Loadstart wird auf den abgefeuert
      //Ende des aktuellen Stacks, normalerweise vor setInterval (fn, 0).
      //An diesem Punkt wissen wir also, dass Loadstart möglicherweise bereits ausgelöst wurde oder
      //kurz vor dem Abschuss, und so oder so hat der Spieler es noch nicht gesehen.
      //Wir wollen hier nicht vorzeitig den Loadstart starten und einen
      //doppelter Ladestart, also warten wir ab, ob es bis jetzt passiert
      //und die nächste Schleife, und falls nicht, feuere sie ab.
      //ABER wir wollen auch sicherstellen, dass es vor dem Laden der Metadaten ausgelöst wird
      //was auch bis zum nächsten Loop passieren könnte, also werden wir
      //achte auch darauf.
      sei loadStartFired = falsch;
      const setLoadStartFired = Funktion () {
        loadStartFired = wahr;
      };

      this.on ('loadstart', setLoadStartFired);

      const triggerLoadStart = Funktion () {
        //Wir haben den ursprünglichen Loadstart verpasst. Vergewissere dich, dass der Spieler
        //sieht den Ladestart vor dem Laden der Metadaten
        wenn (!loadstartFired) {
          this.trigger('loadstart');
        }
      };

      this.on ('geladene Metadaten', triggerLoadStart);

      this.ready(function() {
        this.off ('loadstart', setLoadStartFired);
        this.off ('geladene Metadaten', triggerLoadStart);

        wenn (!loadstartFired) {
          //Wir haben den ursprünglichen nativen Loadstart verpasst. Feuere es jetzt ab.
          this.trigger('loadstart');
        }
      });

      rückkehr;
    }

    //Ab jetzt wissen wir, dass Loadstart bereits ausgelöst wurde und wir ihn verpasst haben.
    //Die anderen ReadyState-Ereignisse sind kein so großes Problem, wenn wir das verdoppeln
    //sie, also werde ich mir nicht so viel Mühe machen wie Loadstart, um das zu verhindern
    //das, es sei denn, wir finden einen Grund dafür.
    const eventsToTrigger = ['loadstart'];

    //loadedmetadata: entspricht neu HAVE_METADATA (1) oder höher
    eventsToTrigger.push ('geladene Metadaten');

    //loadeddata: wurde neu auf HAVE_CURRENT_DATA (2) oder höher erhöht
    wenn (el.ReadyState >= 2) {
      eventsToTrigger.push ('geladene Daten');
    }

    //canplay: wurde neu auf HAVE_FUTURE_DATA (3) oder höher erhöht
    wenn (el.ReadyState >= 3) {
      eventsToTrigger.push ('canplay');
    }

    //canplaythrough: entspricht neu HAVE_ENOUGH_DATA (4)
    wenn (el.ReadyState >= 4) {
      EventsToTrigger.push ('canplaythrough');
    }

    //Wir müssen dem Spieler noch Zeit geben, Event-Listener hinzuzufügen
    this.ready(function() {
      eventsToTrigger.forEach (Funktion (Typ) {
        this.trigger (Typ);
      }, this);
    });
  }

  /**
   * Stellen Sie ein, ob wir schrubben oder nicht.
   * Dies wird verwendet, um zu entscheiden, ob wir `FastSeek` verwenden sollen oder nicht.
   * `FastSeek` wird verwendet, um Trickspiele in Safari-Browsern zu ermöglichen.
   *
   * @param {boolean} ist Scrubbing
   *                  - wahr, denn wir schrubben gerade
   *                  - falsch, denn wir schrubben nicht mehr
   * /
  setScrubbing (isScrubbing) {
    this.isScrubbing_ = IsScrubbing;
  }

  /**
   * Finden Sie heraus, ob wir schrubben oder nicht.
   *
   * @return {boolean} ist Scrubbing
   *                  - wahr, denn wir schrubben gerade
   *                  - falsch, denn wir schrubben nicht mehr
   * /
  schrubben () {
    gib this.isScrubbing_ zurück;
  }

  /**
   * Stellen Sie die aktuelle Uhrzeit für die `HTML5` Technologie ein.
   *
   * @param {Zahl} Sekunden
   * Stellen Sie die aktuelle Uhrzeit des Mediums darauf ein.
   * /
  setCurrentTime (Sekunden) {
    versuche {
      wenn (this.isScrubbing_ && this.el_.FastSeek && browser.is_any_Safari) {
        this.el_.fastSeek (Sekunden);
      } sonst {
        this.el_.CurrentTime = Sekunden;
      }
    } catch (e) {
      log (e), 'Video ist nicht bereit. (Video.js) ');
      //this.warning (videoJS.Warnings.VideoNotReady);
    }
  }

  /**
   * Ruft die aktuelle Dauer des HTML5-Medienelements ab.
   *
   * @return {number}
   * Die Dauer des Mediums oder 0, wenn es keine Dauer gibt.
   * /
  Dauer () {
    //Android Chrome gibt die Dauer bis danach als Infinity für VOD HLS an
    //Die Wiedergabe wurde gestartet, wodurch die Live-Anzeige fälschlicherweise ausgelöst wird.
    //Gib NaN zurück, falls die Wiedergabe noch nicht begonnen hat und löse einmal ein DurationUpdate aus
    //Die Dauer kann zuverlässig bekannt sein.
    wenn (
      this.el_.duration === Unendlich &
      Browser.is_Android &
      Browser.is_Chrome &&
      this.el_.CurrentTime === 0
    ) {
      //Warte auf das erste `timeupdate` mit currentTime > 0 - vielleicht gibt es
      //mehrere mit 0
      const checkProgress = () => {
        wenn (this.el_.currentTime > 0) {
          //Änderung der Triggerdauer für echtes Live-Video
          if (this.el_.duration === Unendlich) {
            this.trigger('Daueränderung');
          }
          this.off ('timeupdate', checkProgress);
        }
      };

      this.on ('timeupdate', checkProgress);
      gib NaN zurück;
    }
    gib this.el_.duration zurück || NaN;
  }

  /**
   * Ermittelt die aktuelle Breite des HTML5-Medienelements.
   *
   * @return {number}
   * Die Breite des HTML5-Medienelements.
   * /
  Breite () {
    gib this.el_.offsetWidth zurück;
  }

  /**
   * Ermittelt die aktuelle Höhe des HTML5-Medienelements.
   *
   * @return {number}
   * Die Höhe des HTML5-Medienelements.
   * /
  Höhe () {
    gib this.el_.offsetHeight zurück;
  }

  /**
   * Proxy für iOS `webkitbeginfullscreen` und `webkitendfullscreen` in
   * `fullscreenchange`-Ereignis.
   *
   * @privat
   * @fires Vollbildwechsel
   * @listens webkitend Vollbild
   * @listens webkitbeginfullscreen
   * @listens webkitbeginfullscreen
   * /
  ProxyWebKitFullScreen_ () {
    wenn (! ('WebKitDisplayingFullScreen' in this.el_)) {
      rückkehr;
    }

    const endFn = Funktion () {
      this.trigger ('fullscreenchange', {isFullScreen: falsch});
      //Safari stellt manchmal Steuerelemente für das Videoelement ein, wenn es im Vollbildmodus ist.
      wenn (this.el_.controls &&! this.options_.nativeControlsForTouch & this.controls () {
        this.el_.controls = falsch;
      }
    };

    const begininFn = Funktion () {
      if ('WebKitPresentationMode' in this.el_ && this.el_.webkitPresentationMode! == 'Bild-im-Bild') {
        this.one ('webkitendfullscreen', endFn);

        this.trigger ('fullscreenchange', {
          isFullScreen: wahr,
          //setze ein Flag für den Fall, dass eine andere Technologie den Vollbildwechsel auslöst
          Nativer iOS-Vollbildschirm: wahr
        });
      }
    };

    this.on ('webkitbeginfullscreen', beginnFN);
    this.on('dispose', () => {
      this.off ('webkitbeginfullscreen', beginnFN);
      this.off ('webkitendfullscreen', endFN);
    });
  }

  /**
   * Prüfen Sie, ob der Vollbildmodus auf dem aktuellen Wiedergabegerät unterstützt wird.
   *
   * @return {boolean}
   * - Stimmt, wenn der Vollbildmodus unterstützt wird.
   * - Falsch, wenn der Vollbildmodus nicht unterstützt wird.
   * /
  supportsFullScreen() {
    if (typeofthis.el_.webkitEnterFullScreen === 'Funktion') {
      const UserAgent = window.navigator & window.navigator.UserAgent || „;

      //Scheint in Chromium/Chrome & Safari in Leopard kaputt zu sein
      wenn (/Android/) .test (UserAgent) ||! (/Chrome|Mac OS X 10.5/) .test (UserAgent)) {
        true zurückgeben;
      }
    }
    return false;
  }

  /**
   * Fordern Sie den `HTML5` Tech auf, den Vollbildmodus aufzurufen.
   * /
  enterFullScreen () {
    const video = this.el_;

    if (video.pausiert && video.networkState <= video.HAVE_METADATA) {
      //versuche, das Videoelement für den programmatischen Zugriff vorzubereiten
      //das ist auf dem Desktop nicht notwendig, sollte aber nicht schaden
      SilencePromise (this.el_.play ());

      //synchron abspielen und pausieren während des Übergangs zum Vollbild
      //kann iOS ~6.1-Geräte in eine Play/Pause-Schleife bringen
      this.setTimeout(function() {
        video.pause ();
        versuche {
          video.webkitEnterFullScreen();
        } catch (e) {
          this.trigger('fullscreenerror', e);
        }
      }, 0);
    } sonst {
      versuche {
        video.webkitEnterFullScreen();
      } catch (e) {
        this.trigger('fullscreenerror', e);
      }
    }
  }

  /**
   * Fordere den `HTML5` Tech auf, den Vollbildmodus zu beenden.
   * /
  ExitFullScreen () {
    wenn (! this.el_.webkitDisplayingFullScreen) {
      this.trigger ('fullscreenerror', neuer Fehler ('Das Video ist kein Vollbild'));
      rückkehr;
    }

    this.el_.webkitExitFullScreen ();
  }

  /**
   * Erstellen Sie ein schwebendes Videofenster, das sich immer über anderen Fenstern befindet, so dass die Benutzer
   * weiterhin Medien konsumieren, während sie mit anderen Inhaltsseiten interagieren, oder
   * anwendungen auf ihrem Gerät.
   *
   * @see [Spec]{@link https://wicg.github.io/picture-in-picture}
   *
   * @return {Versprechen}
   *         Ein Versprechen mit einem Picture-in-Picture-Fenster.
   * /
  requestPictureInPicture() {
    gib this.el_.requestPictureInPicture () zurück;
  }

  /**
   * Nativer RequestVideoFrameCallback, falls vom Browser/Tech unterstützt, oder Fallback
   * Benutze rvCF nicht auf Safari, wenn DRM läuft, da es nicht ausgelöst wird
   * Muss später als der Konstruktor überprüft werden
   * Dies ist ein falsch positives Ergebnis für klare Quellen, die nach einer Fairplay-Quelle geladen wurden
   *
   * @param {function} cb Funktion zum Aufrufen
   * @return {number} ID der Anfrage
   * /
  requestVideoFrameCallback(cb) {
    if (this.featuresVideoFrameCallback && !this.el_.webkitKeys) {
      gib this.el_.requestVideoFrameCallback (cb) zurück;
    }
    gib super.requestVideoFrameCallback (cb) zurück;
  }

  /**
   * Nativer VideoFrameCallback oder Fallback-RequestVideoFrameCallback
   *
   * @param {number} id Anfrage-ID zum Stornieren
   * /
  cancelVideoFrameCallback(id) {
    if (this.featuresVideoFrameCallback && !this.el_.webkitKeys) {
      this.el_.cancelVideoFrameCallback (id);
    } sonst {
      super.cancelVideoFrameCallback (id);
    }
  }

  /**
   * Ein Getter/Setter für das Quellobjekt von `Html5` Tech.
   * > Anmerkung: Bitte verwenden Sie {@link Html5 #setSource}
   *
   * @param {tech~sourceObject} [src]
   * Das Quellobjekt, das Sie auf das `HTML5` techs-Element setzen möchten.
   *
   * @return {tech~sourceObject|undefiniert}
   * - Das aktuelle Quellobjekt, wenn keine Quelle übergeben wird.
   *         - undefiniert bei der Einstellung
   *
   * @veraltet Seit Version 5.
   * /
  src (src) {
    if (src === undefiniert) {
      gib this.el_.src zurück;
    }

    //Das Setzen von src durch `src` anstelle von `setSrc` ist veraltet
    this.setSrc (src);
  }

  /**
   * Setze die Technik zurück, indem du alle Quellen entfernst und dann anrufst
   * {@link html5.resetMediaElement}.
   * /
  reset() {
    html5.resetMediaElement (this.el_);
  }

  /**
   * Holen Sie sich die aktuelle Quelle auf der `HTML5` Tech. Fällt auf die Rückgabe der Quelle zurück von
   * das HTML5-Medienelement.
   *
   * @return {Tech~SourceObject}
   * Das aktuelle Quellobjekt aus der HTML5-Technologie. Mit einem Fallback auf die
   * Elementquelle.
   * /
  currentSrc() {
    if (this.currentSource_) {
      gib this.CurrentSource_.src zurück;
    }
    gib this.el_.CurrentSrc zurück;
  }

  /**
   * Stellen Sie das Steuerattribut für das HTML5-Medienelement ein.
   *
   * @param {string} val
   * Wert, auf den das Steuerelement-Attribut gesetzt werden soll
   * /
  setControls (val) {
    this.el_.controls =!! oval;
  }

  /**
   * Erstellt ein entferntes {@link TextTrack}-Objekt und gibt es zurück.
   *
   * @param {string} kind
   *        textTrack"-Typ (Untertitel, Untertitel, Beschreibungen, Kapitel oder Metadaten)
   *
   * @param {string} [label]
   *        Label zur Kennzeichnung der Textspur
   *
   * @param {string} [Sprache]
   *        Sprachabkürzung mit zwei Buchstaben
   *
   * @return {TextTrack}
   *         Die TextSpur, die erstellt wird.
   * /
  addTextTrack(kind, label, language) {
    if (!this.featuresNativeTextTracks) {
      gib super.addTextTrack zurück (Art, Bezeichnung, Sprache);
    }

    gib this.el_.addTextTrack zurück (Art, Bezeichnung, Sprache);
  }

  /**
   * Erzeugt entweder nativen TextTrack oder einen emulierten TextTrack, je nachdem
   * auf den Wert von `FeaturesNativeTextTracks`
   *
   * @param {Object} options
   *        Das Objekt sollte die Optionen enthalten, mit denen der TextTrack initialisiert werden soll.
   *
   * @param {string} [options.kind]
   *        textTrack"-Typ (Untertitel, Untertitel, Beschreibungen, Kapitel oder Metadaten).
   *
   * @param {string} [options.label]
   *        Label zur Kennzeichnung der Textspur
   *
   * @param {string} [options.language]
   *        Sprachabkürzung mit zwei Buchstaben.
   *
   * @param {boolean} [options.default]
   * Dieser Titel ist standardmäßig aktiviert.
   *
   * @param {string} [options.id]
   * Die interne ID, um diesen Titel zuzuweisen.
   *
   * @param {string} [options.src]
   * Eine Quell-URL für den Track.
   *
   * @return {HTMLTrackElement}
   *         Das Spurelement, das erstellt wird.
   * /
  createRemoteTextTrack(options) {
    if (!this.featuresNativeTextTracks) {
      gib super.createRemoteTextTrack zurück (Optionen);
    }
    const htmlTrackElement = document.createElement ('track');

    wenn (options.kind) {
      HtmlTrackElement.Kind = Optionen.kind;
    }
    if (options.label) {
      HtmlTrackElement.label = options.label;
    }
    wenn (options.language || options.srclang) {
      HtmlTrackElement.srclang = options.language || options.srclang;
    }
    wenn (options.default) {
      HtmlTrackElement.default = Optionen.default;
    }
    wenn (options.id) {
      HtmlTrackElement.id = options.id;
    }
    wenn (options.src) {
      HtmlTrackElement.src = Optionen.src;
    }

    return htmlTrackElement;
  }

  /**
   * Erzeugt ein entferntes Text-Track-Objekt und gibt ein HTML-Track-Element zurück.
   *
   * @param {Object} Optionen Das Objekt sollte Werte enthalten für
   * kind, language, label und src (Speicherort der WebVTT-Datei)
   * @param {boolean} [manualCleanup=true] wenn auf false gesetzt, wird der TextTrack
   * wird automatisch aus dem Videoelement entfernt, wenn sich die Quelle ändert
   * @return {htmlTrackElement} Ein HTML-Track-Element.
   * Dies kann ein emuliertes {@link HtmlTrackElement} oder ein natives sein.
   * @deprecated Der Standardwert des Parameters "manualCleanup" ist standardmäßig
   * in zukünftigen Versionen von Video.js auf „falsch“
   * /
  addRemoteTextTrack(options, manualCleanup) {
    const htmlTrackElement = super.addRemoteTextTrack (Optionen, ManualCleanup);

    if (this.featuresNativeTextTracks) {
      this.el () .appendChild (htmlTrackElement);
    }

    return htmlTrackElement;
  }

  /**
   * Entferne das entfernte `TextTrack` aus dem `TextTrackList`-Objekt
   *
   * @param {TextTrack} track
   * `TextTrack`-Objekt, das entfernt werden soll
   * /
  removeRemoteTextTrack(track) {
    super.removeRemoteTextTrack (track);

    if (this.featuresNativeTextTracks) {
      const tracks = this.$$ ('track');

      let i = tracks.length;

      while (i--) {
        if (track === tracks [i] || track === tracks [i] .track) {
          this.el () .removeChild (verfolgt [i]);
        }
      }
    }
  }

  /**
   * Ruft verfügbare Metriken zur Qualität der Medienwiedergabe ab, wie sie vom W3C's Media
   * Wiedergabequalität API.
   *
   * @see [Spec]{@link https://wicg.github.io/media-playback-quality}
   *
   * @return {Object}
   *         Ein Objekt mit unterstützten Qualitätsmetriken für die Medienwiedergabe
   * /
  getVideoPlaybackQuality() {
    if (typeof this.el () .getVideoPlaybackQuality === 'Funktion') {
      gib this.el () .getVideoPlaybackQuality () zurück;
    }

    const VideoPlaybackQuality = {};

    if (typeofthis.el () .webkitDroppedFrameCount! == 'undefiniert' &&
        type of this.el () .webkitDecodedFrameCount! == 'undefiniert') {
      videoPlaybackQuality.droppedVideoFrames = this.el () .webKitDroppedFrameCount;
      videoPlaybackQuality.totalVideoFrames = this.el () .webkitDecodedFrameCount;
    }

    if (window.performance && typeof window.performance.now === 'Funktion') {
      videoPlaybackQuality.creationTime = window.performance.now ();
    } sonst wenn (window.performance &&
               Fensterleistung.Timing &
               typeof window.performance.timing.navigationStart === 'Zahl') {
      VideoPlaybackQuality.creationTime =
        window.date.now () - window.performance.timing.navigationStart;
    }

    VideoPlaybackQuality zurückgeben;
  }
}

/* Testen der HTML5-Unterstützung ------------------------------------ */

/**
 * Element zum Testen der HTML5-Medienfunktionen von Browsern
 *
 * @type {Element}
 * @konstant
 * @privat
 * /
defineLazyProperty (Html5), 'TEST_VID', Funktion () {
  if (!Dom.isReal()) {
    rückkehr;
  }
  const video = document.createElement ('video');
  const track = document.createElement ('track');

  track.kind = 'Bildunterschriften';
  track.srclang = 'de';
  track.label = 'Englisch';
  video.appendChild (Titel);

  Video zurückgeben;
});

/**
 * Prüfen Sie, ob HTML5-Medien von diesem Browser/Gerät unterstützt werden.
 *
 * @return {boolean}
 * - Stimmt, wenn HTML5-Medien unterstützt werden.
 * - Falsch, wenn HTML5-Medien nicht unterstützt werden.
 * /
html5.isSupported = Funktion () {
  //IE ohne Media Player ist ein LÜGNER! (#984)
  versuche {
    Html5.test_vid.Volumen = 0,5;
  } catch (e) {
    return false;
  }

  kehre zurück!! (Html5.test_Vid & Html5.test_vid.canPlayType);
};

/**
 * Prüfen Sie, ob der Techniker den angegebenen Typ unterstützen kann
 *
 * @param {string} type
 *        Der zu prüfende Mimetyp
 * @return {string} 'wahrscheinlich', 'vielleicht', oder '' (leere Zeichenkette)
 * /
html5.canPlayType = Funktion (Typ) {
  return Html5.TEST_VID.canPlayType(type);
};

/**
 * Prüfen Sie, ob der Techniker die angegebene Quelle unterstützen kann
 *
 * @param {Object} srcObj
 *        Das Quellobjekt
 * @param {Object} options
 *        Die an die Technik übergebenen Optionen
 * @return {string} 'wahrscheinlich', 'vielleicht', oder '' (leere Zeichenkette)
 * /
html5.canPlaySource = Funktion (srcoBJ, Optionen) {
  gib html5.canPlayType (srcobj.Type) zurück;
};

/**
 * Prüfen Sie, ob die Lautstärke in diesem Browser/Gerät geändert werden kann.
 * Die Lautstärke kann auf vielen Mobilgeräten nicht geändert werden.
 * Insbesondere kann es unter iOS nicht von 1 geändert werden.
 *
 * @return {boolean}
 * - Stimmt, wenn die Lautstärke geregelt werden kann
 *         - Falsch sonst
 * /
html5.canControlVolume = Funktion () {
  // IE wird fehlschlagen, wenn Windows Media Player nicht installiert ist #3315
  versuche {
    const volume = Html5.test_vid.Volume;

    Html5.test_vid.Volume = (Band /2) + 0.1;

    const canControl = Lautstärke! == Html5.test_vid.Volume;

    //Mit der Einführung von iOS 15 gibt es Fälle, in denen der Band gelesen wird als
    //wurde geändert, kehrt aber zu Beginn des nächsten Ticks in den ursprünglichen Zustand zurück.
    //Um festzustellen, ob die Lautstärke unter iOS gesteuert werden kann,
    //ein Timeout wird gesetzt und die Lautstärke wird asynchron geprüft.
    //Da `features` derzeit nicht asynchron funktioniert, wird der Wert manuell gesetzt.
    wenn (canControl && Browser.is_iOS) {
      window.setTimeout(() => {
        wenn (Html5 && Html5.prototype) {
          html5.prototype.featuresVolumeControl = Lautstärke! == Html5.test_vid.Volume;
        }
      });

      //iOS ist standardmäßig auf false gesetzt, was im obigen Timeout aktualisiert wird.
      return false;
    }

    canControl zurückgeben;
  } catch (e) {
    return false;
  }
};

/**
 * Prüfen Sie, ob die Lautstärke in diesem Browser/Gerät stummgeschaltet werden kann.
 * Bei einigen Geräten, z. B. iOS, kann die Lautstärke nicht geändert werden
 * erlaubt aber das Stummschalten/Aufheben der Stummschaltung.
 *
 * @return {bolean}
 * - Stimmt, wenn die Lautstärke stummgeschaltet werden kann
 * - Andernfalls falsch
 * /
html5.canMuteVolume = Funktion () {
  versuche {
    const muted = Html5.test_vid.muted;

    //In einigen Versionen von iOS funktioniert die stummgeschaltete Eigenschaft nicht immer
    //funktioniert, also wollen wir sowohl Eigenschaft als auch Attribut setzen
    html5.test_vid.muted =! stummgeschaltet;
    wenn (html5.test_vid.Muted) {
      dom.setAttribute (html5.test_Vid, 'stummgeschaltet', 'stummgeschaltet');
    } sonst {
      dom.removeAttribute (html5.test_Vid, 'stummgeschaltet', 'stummgeschaltet');
    }
    Rückkehr stummgeschaltet! == Html5.test_vid.Stummgeschaltet;
  } catch (e) {
    return false;
  }
};

/**
 * Prüfen Sie, ob die Wiedergabegeschwindigkeit in diesem Browser/Gerät geändert werden kann.
 *
 * @return {boolean}
 * - Stimmt, wenn die Wiedergabegeschwindigkeit gesteuert werden kann
 *         - Falsch sonst
 * /
html5.canControlPlaybackRate = Funktion () {
  //Die Playback Rate API ist in Android Chrome implementiert, macht aber nichts
  //https://github.com/videojs/video.js/issues/3180
  wenn (browser.IS_Android && browser.IS_Chrome && browser.Chrome_Version < 58) {
    return false;
  }
  // IE wird fehlschlagen, wenn Windows Media Player nicht installiert ist #3315
  versuche {
    const playbackRate = html5.test_vid.PlaybackRate;

    html5.test_vid.PlaybackRate = (Wiedergaberate//2) + 0.1;
    gib die PlaybackRate zurück! == HTML5.test_vid.Wiedergaberate;
  } catch (e) {
    return false;
  }
};

/**
 * Prüfen Sie, ob wir die Attribute eines Video-/Audioelements überschreiben können, mit
 * Objekt. Eigenschaft definieren.
 *
 * @return {boolean}
 * - Wahr, wenn eingebaute Attribute überschrieben werden können
 *         - Falsch sonst
 * /
html5.canOverrideAttributes = Funktion () {
  //Wenn wir die src/innerHTML-Eigenschaft nicht überschreiben können, gibt es keine Unterstützung
  //iOS 7 Safari zum Beispiel kann das nicht.
  versuche {
    const noop = () => {};

    Object.defineProperty (document.createElement ('video'), 'src', {get: nein, set: nein});
    Object.defineProperty (document.createElement ('audio'), 'src', {get: noop, set: noop});
    Object.defineProperty (document.createElement ('video'), 'innerHTML', {get: nein, set: nein});
    Object.defineProperty (document.createElement ('audio'), 'innerHTML', {get: nein, set: nein});
  } catch (e) {
    return false;
  }

  true zurückgeben;
};

/**
 * Prüfen Sie, ob native `TextTrack`s von diesem Browser/Gerät unterstützt werden.
 *
 * @return {boolean}
 * - Wahr, wenn native `TextTrack`s unterstützt werden.
 *         - Falsch sonst
 * /
html5.supportsNativeTextTracks = Funktion () {
  gib browser.is_any_Safari || (browser.IS_iOS && browser.is_Chrome) zurück;
};

/**
 * Prüfen Sie, ob native `VideoTrack`s von diesem Browser/Gerät unterstützt werden
 *
 * @return {boolean}
 * - Wahr, wenn native `VideoTrack`s unterstützt werden.
 *        - Falsch sonst
 * /
html5.supportsNativeVideoTracks = Funktion () {
  kehre zurück!! (Html5.test_Vid & Html5.test_vid.videoTracks);
};

/**
 * Prüfen Sie, ob native `AudioTrack`s von diesem Browser/Gerät unterstützt werden
 *
 * @return {boolean}
 * - Wahr, wenn native `AudioTrack`s unterstützt werden.
 *        - Falsch sonst
 * /
html5.supportsNativeAudioTracks = Funktion () {
  kehre zurück!! (Html5.test_Vid & Html5.test_vid.AudioTracks);
};

/**
 * Eine Reihe von Veranstaltungen, die auf der Html5-Technologie verfügbar sind.
 *
 * @privat
 * @Typ {Array}
 * /
Html5.Ereignisse = [
  'Ladestart',
  aussetzen',
  abbruch",
  fehler",
  geleert",
  abgewürgt",
  'loadedmetadata',
  'Geladene Daten',
  'kann spielen',
  'kann durchspielen',
  'spielen',
  'warten',
  suchen",
  'gesucht',
  beendet",
  „Änderung der Dauer“,
  timeupdate',
  fortschritt",
  'spielen',
  pause",
  'Preisänderung',
  größe ändern",
  'Volumenänderung'
];

/**
 * Boolescher Wert, der angibt, ob das "Tech" die Lautstärkeregelung unterstützt.
 *
 * @Typ {boolean}
 * @default {@link html5.canControlVolume}
 * /
/**
 * Boolescher Wert, der angibt, ob das "Tech" die Stummschaltung der Lautstärke unterstützt.
 *
 * @Typ {bolean}
 * @default {@link Html5.canVolume stummschalten}
 * /

/**
 * Boolescher Wert, der angibt, ob der `Tech` das Ändern der Geschwindigkeit unterstützt, mit der das Medium
 * spielt. Beispiele:
 *   - Player so einstellen, dass er 2x (doppelt) so schnell spielt
 *   - Player so einstellen, dass er 0,5x (halb) so schnell spielt
 *
 * @Typ {boolean}
 * @default {@link html5.canControlPlaybackRate}
 * /

/**
 * Boolescher Wert, der angibt, ob das "Tech" das Ereignis "Sourceset" unterstützt.
 *
 * @Typ {boolean}
 * @default
 * /
/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie derzeit native `TextTrack`s unterstützt.
 *
 * @Typ {boolean}
 * @default {@link HTML5. unterstützt native TextTracks}
 * /
/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie derzeit native `VideoTrack`s unterstützt.
 *
 * @Typ {boolean}
 * @default {@link HTML5. unterstützt NativeVideoTracks}
 * /
/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie derzeit native `AudioTrack`s unterstützt.
 *
 * @Typ {boolean}
 * @default {@link Html5. unterstützt native Audiotracks}
 * /
[
  ['featuresMuteControl', 'canMuteVolume'],
  ['featurePlaybackRate', 'canControlPlaybackRate'],
  ['FeatureResourceSet', 'canOverrideAttributes'],
  ['featureNativeTextTracks', 'unterstützt native TextTracks'],
  ['bietet native Videotracks', 'unterstützt native Videotracks'],
  ['bietet native Audiotracks', 'unterstützt native Audiotracks']
] .forEach (Funktion ([Taste, Fn]) {
  defineLazyProperty (Html5.prototype, Schlüssel, () => Html5 [fn] (), wahr);
});

html5.prototype.featuresVolumeControl = html5.canControlVolume ();

/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie das Medienelement derzeit unterstützt
 * Verschieben des DOM. iOS wird unterbrochen, wenn Sie das Medienelement verschieben, also wird dies auf gesetzt
 * dort falsch. Überall sonst sollte das stimmen.
 *
 * @Typ {boolean}
 * @default
 * /
Html5.prototype.movingMediaElementIndom =! Browser.is_iOS;

// TODO: Vorheriger Kommentar: Scheint nicht mehr verwendet zu werden. Kann wahrscheinlich entfernt werden.
//Stimmt das?
/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie derzeit die automatische Größenänderung von Medien unterstützt
 * wenn Sie in den Vollbildmodus wechseln.
 *
 * @Typ {boolean}
 * @default
 * /
html5.prototype.featuresFullScreenResize = wahr;

/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie das Fortschrittsereignis derzeit unterstützt.
 * Wenn dies falsch ist, werden stattdessen manuelle `Fortschritts` ausgelöst.
 *
 * @Typ {boolean}
 * @default
 * /
html5.prototype.featureProgressEvents = wahr;

/**
 * Boolescher Wert, der angibt, ob die `HTML5`-Technologie derzeit das Timeupdate-Ereignis unterstützt.
 * Wenn dies falsch ist, werden stattdessen manuelle `timeupdate`-Ereignisse ausgelöst.
 *
 * @default
 * /
html5.prototype.featuresTimeUpdateEvents = wahr;

/**
 * Ob das HTML5-El `RequestVideoFrameCallback` unterstützt
 *
 * @Typ {boolean}
 * /
html5.prototype.featuresVideoFrameCallback =!! (Html5.test_Vid & Html5.test_vid.RequestVideoFrameCallback);

//Erkennung von HTML5-Funktionen und Gerätekorrekturen ---------------------------------//
lass CanPlayType;

html5.patchCanPlayType = Funktion () {

  //Android 4.0 und höher können HLS bis zu einem gewissen Grad abspielen, es wird jedoch gemeldet, dass dies nicht möglich ist
  //Firefox und Chrome melden sich korrekt
  wenn (browser.android_Version >= 4.0 &&! Browser.is_Firefox &&! Browser.is_Chrome) {
    canPlayType = Html5.test_Vid & Html5.test_vid.constructor.prototype.canPlayType;
    html5.test_vid.constructor.prototype.canPlayType = Funktion (Typ) {
      const mpegUrlRe = /^Anwendung\/(? :x-|vnd\ .apple\.) mpegurl/i;

      if (type && mpegUrle.test (type)) {
        gib 'vielleicht' zurück;
      }
      return canPlayType.call (this, type);
    };
  }
};

html5.unpatchCanPlayType = Funktion () {
  const r = html5.test_vid.constructor.prototype.canPlayType;

  wenn (canPlayType) {
    html5.test_vid.constructor.prototype.canPlayType = CanPlayType;
  }
  gib r zurück;
};

//patche standardmäßig das Medienelement
html5.patchCanPlayType ();

html5.disposeMediaElement = Funktion (de) {
  if (!el) {
    rückkehr;
  }

  if (el.parentNode) {
    el.parentNode.removeChild (de);
  }

  //entferne alle untergeordneten Track- oder Quellknoten, um zu verhindern, dass sie geladen werden
  while (el.hasChildNodes ()) {
    el.removeChild(el.firstChild);
  }

  //Entferne jede SRC-Referenz. Setze `src="` nicht, weil das eine Warnung auslöst
  //in Firefox
  el.removeAttribute('src');

  //erzwingen Sie das Medienelement, seinen Ladezustand zu aktualisieren, indem Sie load () aufrufen
  //IE unter Windows 7N hat jedoch einen Fehler, der einen Fehler auslöst, also brauche ich einen Try/Catch (#793)
  if (typeof el.load === 'function') {
    // Einpacken in ein iife, damit es nicht deoptimiert wird (#1060#diskussion_r10324473)
    (function() {
      versuche {
        el.load();
      } catch (e) {
        //nicht unterstützt
      }
    }());
  }
};

html5.resetMediaElement = Funktion (de) {
  if (!el) {
    rückkehr;
  }

  const sources = el.querySelectorAll ('Quelle');
  sei i = sources.length;

  while (i--) {
    el.removeChild (Quellen [i]);
  }

  //entferne jede src-Referenz.
  //`src="` nicht setzen, weil das einen Fehler auslöst
  el.removeAttribute('src');

  if (typeof el.load === 'function') {
    // Einpacken in ein iife, damit es nicht deoptimiert wird (#1060#diskussion_r10324473)
    (function() {
      versuche {
        el.load();
      } catch (e) {
        //Linter zufrieden stellen
      }
    }());
  }
};

/* Eigenschaftsumbruch für native HTML5-Elemente ----------------------------------- */
//Umschließen Sie native boolesche Attribute mit Gettern, die sowohl die Eigenschaft als auch das Attribut überprüfen
// Die Liste sieht wie folgt aus:
//stummgeschaltet, DefaultStummgeschaltet, Autoplay, Steuerung, Loop, spielt Inline
[
  /**
   * Ruft den Wert von `muted` aus dem Medienelement ab. `stummgeschalt` zeigt an
   * dass die Lautstärke für die Medien auf lautlos gestellt werden sollte. Das ändert sich eigentlich nicht
   * das `volume`-Attribut.
   *
   * @method Html5 #muted
   * @return {boolean}
   * - Wahr, wenn der Wert von `volume` ignoriert und das Audio auf stumm gestellt werden soll.
   * - Falsch, wenn der Wert von `volume` verwendet werden soll.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
   * /
  stumm",

  /**
   * Ruft den Wert von `defaultMuted` aus dem Medienelement ab. `defaultMuted` gibt an
   * ob die Medien stummgeschaltet werden sollen oder nicht. Ändert nur den Standardstatus des
   * Medien. `muted` und `defaultMuted` können unterschiedliche Werte haben. {@link Html5 #muted} gibt an
   * aktueller Stand.
   *
   * @method Html5 #defaultMuted
   * @return {boolean}
   * - Der Wert von `defaultMuted` aus dem Medienelement.
   * - Wahr bedeutet, dass das Medium stummgeschaltet werden soll.
   * - Falsch bedeutet, dass das Medium nicht stummgeschaltet werden soll
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
   * /
  'defaultMuted',

  /**
   * Ruft den Wert von `autoplay` aus dem Medienelement ab. `Autoplay` zeigt an
   * dass die Medien abgespielt werden sollen, sobald die Seite fertig ist.
   *
   * @method Html5 #autoplay
   * @return {boolean}
   * - Der Wert von `autoplay` aus dem Medienelement.
   *         - True gibt an, dass die Medien gestartet werden sollen, sobald die Seite geladen ist.
   *         - False bedeutet, dass die Medien nicht sofort nach dem Laden der Seite gestartet werden sollen.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
   * /
  'Autoplay',

  /**
   * Ruft den Wert von `controls` aus dem Medienelement ab. `Controls` zeigt an
   * ob die nativen Mediensteuerungen ein- oder ausgeblendet werden sollen.
   *
   * @method Html5 #controls
   * @return {boolean}
   * - Der Wert von `controls` aus dem Medienelement.
   * - Wahr gibt an, dass native Steuerelemente angezeigt werden sollen.
   * - Falsch bedeutet, dass native Steuerelemente ausgeblendet werden sollen.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-controls}
   * /
  'Steuerungen',

  /**
   * Ruft den Wert von `loop` aus dem Medienelement ab. `Loop` zeigt an
   * dass das Medium zum Anfang des Mediums zurückkehren und die Wiedergabe fortsetzen soll, sobald
   * er das Ende erreicht.
   *
   * @method Html5 #loop
   * @return {boolean}
   * - Der Wert von `loop` aus dem Medienelement.
   *         - True zeigt an, dass die Wiedergabe zum Start zurückkehren soll, sobald
   *           das Ende eines Mediums erreicht ist.
   *         - False zeigt an, dass die Wiedergabe nicht zum Anfang zurückkehren soll, wenn die
   *           das Ende des Mediums erreicht ist.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
   * /
  'Schleife',

  /**
   * Ruft den Wert von `playsinline` aus dem Medienelement ab. `playsinline` gibt an
   * dem Browser mitzuteilen, dass die Nicht-Vollbild-Wiedergabe bevorzugt wird, wenn der Vollbildmodus
   * die Wiedergabe ist der native Standard, wie z. B. in iOS Safari.
   *
   * @method Html5 #playsinline
   * @return {boolean}
   * - Der Wert von `playsinline` aus dem Medienelement.
   *         - True zeigt an, dass die Medien inline abgespielt werden sollen.
   *         - False bedeutet, dass die Medien nicht inline abgespielt werden sollen.
   *
   * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
   * /
  playsinline'
].forEach(function(prop) {
  Html5.prototype[prop] = function() {
    gib this.el_ [prop] || this.el_.hasAttribute (prop);
  };
});

//Umschließen Sie native boolesche Attribute mit Settern, die sowohl die Eigenschaft als auch das Attribut festlegen
// Die Liste sieht wie folgt aus:
//setMute, setDefaultMute, setAutoplay, setLoop, setPlaysInline
//SetControls ist oben ein Sonderfall
[
  /**
   * Stellen Sie den Wert von `muted` für das Medienelement ein. `muted` zeigt an, dass der Strom
   * Der Audiopegel sollte leise sein.
   *
   * @method Html5 #setMuted
   * @param {boolean} stummgeschaltet
   *        - True, wenn der Ton auf stumm gestellt werden soll
   *        - Falsch sonst
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-muted}
   * /
  stumm",

  /**
   * Stellen Sie den Wert von `defaultMuted` für das Medienelement ein. `defaultMuted` gibt an, dass der aktuelle
   * Der Audiopegel sollte leise sein, wirkt sich aber nur auf den stummgeschalteten Pegel bei der ersten Wiedergabe aus.
   *
   * @method html5.prototype.setDefaultMuted
   * @param {boolean} defaultStummgeschaltet
   *        - True, wenn der Ton auf stumm gestellt werden soll
   *        - Falsch sonst
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultmuted}
   * /
  'defaultMuted',

  /**
   * Stellen Sie den Wert von `Autoplay` für das Medienelement ein. `Autoplay` zeigt an
   * dass die Medien abgespielt werden sollen, sobald die Seite fertig ist.
   *
   * @method Html5 #setAutoplay
   * @param {boolean} automatische Wiedergabe
   *         - True gibt an, dass die Medien gestartet werden sollen, sobald die Seite geladen ist.
   *         - False bedeutet, dass die Medien nicht sofort nach dem Laden der Seite gestartet werden sollen.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-autoplay}
   * /
  'Autoplay',

  /**
   * Stellen Sie den Wert von `loop` für das Medienelement ein. `Loop` zeigt an
   * dass das Medium zum Anfang des Mediums zurückkehren und die Wiedergabe fortsetzen soll, sobald
   * er das Ende erreicht.
   *
   * @method Html5 #setLoop
   * @param {boolean} -Schleife
   *         - True zeigt an, dass die Wiedergabe zum Start zurückkehren soll, sobald
   *           das Ende eines Mediums erreicht ist.
   *         - False zeigt an, dass die Wiedergabe nicht zum Anfang zurückkehren soll, wenn die
   *           das Ende des Mediums erreicht ist.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-loop}
   * /
  'Schleife',

  /**
   * Stellen Sie den Wert von `playsinline` aus dem Medienelement ein. `playsinline` gibt an
   * dem Browser mitzuteilen, dass die Nicht-Vollbild-Wiedergabe bevorzugt wird, wenn der Vollbildmodus
   * die Wiedergabe ist der native Standard, wie z. B. in iOS Safari.
   *
   * @method Html5 #setPlaysinline
   * @param {boolean} spielt online
   *         - True zeigt an, dass die Medien inline abgespielt werden sollen.
   *         - False bedeutet, dass die Medien nicht inline abgespielt werden sollen.
   *
   * @see [Spec]{@link https://html.spec.whatwg.org/#attr-video-playsinline}
   * /
  playsinline'
].forEach(function(prop) {
  Html5.prototype['set' + toTitleCase(prop)] = function(v) {
    this.el_[prop] = v;

    wenn (v) {
      this.el_.setAttribute (Requisite, Requisite);
    } sonst {
      this.el_.removeAttribute (Requisite);
    }
  };
});

//Umwickle native Eigenschaften mit einem Getter
//Die Liste ist wie folgt
//angehalten, CurrentTime, Buffered, Volume, Poster, Preload, Fehler, Suche
//suchbar, beendet, PlaybackRate, defaultPlaybackRate, DisablePictureInPicture
//gespielt, NetworkState, ReadyState, VideoWidth, VideoHeight, CrossOrigin
[
  /**
   * Ruft den Wert von `paused` aus dem Medienelement ab. `angehalten` gibt an, ob das Medienelement
   * ist derzeit pausiert oder nicht.
   *
   * @method Html5 #paused
   * @return {boolean}
   * Der Wert von `paused` aus dem Medienelement.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-paused}
   * /
  'angehalten',

  /**
   * Ruft den Wert von `CurrentTime` aus dem Medienelement ab. `currentTime` gibt an
   * die aktuelle Sekunde, in der sich das Medium bei der Wiedergabe befindet.
   *
   * @method Html5 #currentTime
   * @return {number}
   * Der Wert von `currentTime` aus dem Medienelement.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-currenttime}
   * /
  'Aktuelle Uhrzeit',

  /**
   * Ruft den Wert von `buffered` aus dem Medienelement ab. `buffered` ist ein `TimeRange`
   * Objekt, das die Teile des Mediums darstellt, die bereits heruntergeladen wurden, und
   * zur Wiedergabe verfügbar.
   *
   * @method Html5 #buffered
   * @return {TimeRange}
   * Der Wert von `buffered` aus dem Medienelement.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-buffered}
   * /
  'gepuffert',

  /**
   * Ruft den Wert von `volume` aus dem Medienelement ab. `Volumen` gibt an
   * die aktuelle Lautstärke der Audiowiedergabe für ein Medium. `volume` wird ein Wert von 0 sein
   * (leise) auf 1 (am lautesten und standardmäßig).
   *
   * @method Html5 #volume
   * @return {number}
   * Der Wert von `volume` aus dem Medienelement. Der Wert liegt zwischen 0 und 1.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume}
   * /
  volumen",

  /**
   * Ruft den Wert von `poster` aus dem Medienelement ab. `Poster` zeigt an
   * dass die URL einer Bilddatei, die angezeigt werden kann/wird, wenn keine Mediendaten verfügbar sind.
   *
   * @method Html5 #poster
   * @return {string}
   * Der Wert von `Poster` aus dem Medienelement. Der Wert wird eine URL zu einem sein
   * Bild.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-video-poster}
   * /
  poster",

  /**
   * Ruft den Wert von `preload` aus dem Medienelement ab. `preload` gibt an
   * was heruntergeladen werden sollte, bevor mit den Medien interagiert wird. Sie kann folgende Merkmale aufweisen
   * werte:
   * - keine: es soll nichts heruntergeladen werden
   * - Metadaten: Poster und die ersten Bilder des Mediums können heruntergeladen werden, um die
   *   medienabmessungen und andere Metadaten
   * - auto: die Medien und Metadaten für die Medien werden vor dem
   *    interaktion
   *
   * @method Html5 #preload
   * @return {string}
   * Der Wert von `preload` aus dem Medienelement. Wird 'none', 'metadata' sein,
   *         oder 'auto'.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload}
   * /
  'Vorladung',

  /**
   * Ruft den Wert des `Fehler` aus dem Medienelement ab. `Error` gibt an, dass
   * MediaError, der möglicherweise während der Wiedergabe aufgetreten ist. Wenn der Fehler Null zurückgibt, gibt es keine
   * aktueller Fehler.
   *
   * @method Html5 #error
   * @return {MediaError|null}
   * Der Wert von `error` aus dem Medienelement. Wird `MediaError` sein, wenn da
   * ist ein aktueller Fehler und andernfalls null.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-error}
   * /
  fehler",

  /**
   * Ruft den Wert von `seeking` aus dem Medienelement ab. `Seeking` gibt an, ob
   * Die Medien suchen derzeit nach einer neuen Position oder nicht.
   *
   * @method Html5 #seeking
   * @return {boolean}
   * - Der Wert von `seeking` aus dem Medienelement.
   * - Wahr bedeutet, dass die Medien derzeit nach einer neuen Position suchen.
   * - Falsch bedeutet, dass die Medien derzeit keine neue Position anstreben.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seeking}
   * /
  suchen",

  /**
   * Ruft den Wert von `seekable` aus dem Medienelement ab. `seekable` gibt einen zurück
   * `TimeRange`-Objekt, das Zeitbereiche angibt, nach denen aktuell gesucht werden kann.
   *
   * @method Html5 #seekable
   * @return {TimeRange}
   * Der Wert von `seekable` aus dem Medienelement. Ein `TimeRange`-Objekt
   * gibt die aktuellen Zeitbereiche an, nach denen gesucht werden kann.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-seekable}
   * /
  suchbar',

  /**
   * Ruft den Wert von `ended` aus dem Medienelement ab. `beendet` gibt an, ob
   * Die Medien haben das Ende erreicht oder nicht.
   *
   * @method Html5 #ended
   * @return {boolean}
   * - Der Wert von `ended` aus dem Medienelement.
   * - Wahr bedeutet, dass die Medienwiedergabe beendet wurde.
   * - Falsch bedeutet, dass das Medium noch nicht beendet wurde.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-ended}
   * /
  beendet",

  /**
   * Ruft den Wert von `PlaybackRate` aus dem Medienelement ab. `PlaybackRate` gibt an
   * die Geschwindigkeit, mit der das Medium gerade wiedergegeben wird. Beispiele:
   *   - Wenn playbackRate auf 2 gesetzt ist, werden die Medien doppelt so schnell abgespielt.
   *   - Wenn playbackRate auf 0,5 gesetzt ist, werden die Medien nur halb so schnell abgespielt.
   *
   * @method Html5 #playbackRate
   * @return {number}
   *         Der Wert von "PlaybackRate" aus dem Medienelement. Eine Zahl, die angibt
   *         die aktuelle Wiedergabegeschwindigkeit des Mediums, wobei 1 die normale Geschwindigkeit ist.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
   * /
  playbackRate',

  /**
   * Ruft den Wert von `defaultPlaybackRate` aus dem Medienelement ab. `defaultPlaybackRate` gibt an
   * die Geschwindigkeit, mit der das Medium gerade wiedergegeben wird. Dieser Wert gibt nicht den aktuellen Wert an
   * `PlaybackRate` nachdem die Wiedergabe gestartet wurde, verwende dafür {@link Html5 #playbackRate}.
   *
   * Beispiele:
   * - Wenn DefaultPlaybackRate auf 2 gesetzt ist, werden Medien doppelt so schnell abgespielt.
   * - Wenn DefaultPlaybackRate auf 0,5 gesetzt ist, werden Medien halb so schnell abgespielt.
   *
   * @method html5.prototype.defaultPlaybackRate
   * @return {number}
   *         Der Wert von `defaultPlaybackRate` aus dem Medienelement. Eine Zahl, die angibt
   *         die aktuelle Wiedergabegeschwindigkeit des Mediums, wobei 1 die normale Geschwindigkeit ist.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
   * /
  'defaultPlaybackRate',

  /**
   * Ruft den Wert von 'disablePictureInPicture' aus dem Videoelement ab.
   *
   * @method Html5 #disablePictureInPicture
   * @return {boolean} -Wert
   * - Der Wert von `disablePictureInPicture` aus dem Videoelement.
   * - True bedeutet, dass das Video im Picture-In-Picture-Modus nicht abgespielt werden kann
   * - Falsch bedeutet, dass das Video im Picture-In-Picture-Modus abgespielt werden kann
   *
   * @see [Spec]{@link https://w3c.github.io/picture-in-picture/#disable-pip}
   * /
  disablePictureInPicture',

  /**
   * Ruft den Wert von `played` aus dem Medienelement ab. `played` gibt einen `TimeRange` zurück
   * Objekt, das Punkte in der Medien-Timeline darstellt, die abgespielt wurden.
   *
   * @method Html5 #played
   * @return {TimeRange}
   * Der Wert von `played` aus dem Medienelement. Ein `TimeRange`-Objekt, das angibt
   * die Zeiträume, die gespielt wurden.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-played}
   * /
  'gespielt',

  /**
   * Ruft den Wert von `NetworkState` aus dem Medienelement ab. `NetworkState` gibt an
   * der aktuelle Netzwerkstatus. Es gibt eine Aufzählung aus der folgenden Liste zurück:
   * - 0: NETWORK_EMPTY
   * - 1: NETWORK_IDLE
   * - 2: NETWORK_LOADING
   * - 3: NETWORK_NO_SOURCE
   *
   * @method Html5 #networkState
   * @return {number}
   * Der Wert von `NetworkState` aus dem Medienelement. Dies wird eine Nummer sein
   *         aus der Liste in der Beschreibung.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-networkstate}
   * /
  netzwerk-Status",

  /**
   * Ruft den Wert von `ReadyState` aus dem Medienelement ab. `ReadyState` gibt an
   * der aktuelle Status des Medienelements. Es gibt eine Aufzählung aus dem
   * folgende Liste:
   * - 0: HABEN_NICHTS
   * - 1: HABEN_METADATEN
   * - 2: HAVE_CURRENT_DATA
   * - 3: HAVE_FUTURE_DATA
   * - 4: HAVE_ENOUGH_DATA
   *
   * @method Html5 #readyState
   * @return {number}
   * Der Wert von `ReadyState` aus dem Medienelement. Dies wird eine Nummer sein
   *         aus der Liste in der Beschreibung.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#ready-states}
   * /
  'Bereitschaft',

  /**
   * Ruft den Wert von `videoWidth` aus dem Videoelement ab. `videoWidth` gibt an
   * die aktuelle Breite des Videos in CSS-Pixeln.
   *
   * @method Html5 #videoWidth
   * @return {number}
   * Der Wert von `videoWidth` aus dem Videoelement. Dies wird eine Nummer sein
   *         in css-Pixel.
   *
   * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth}
   * /
  'VideoBreite',

  /**
   * Ruft den Wert von `VideoHeight` aus dem Videoelement ab. `VideoHeight` gibt an
   * die aktuelle Höhe des Videos in CSS-Pixeln.
   *
   * @method Html5 #videoHeight
   * @return {number}
   * Der Wert von `VideoHeight` aus dem Videoelement. Dies wird eine Nummer sein
   *         in css-Pixel.
   *
   * @see [Spec] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-video-videowidth}
   * /
  'Videohöhe',

  /**
   * Ruft den Wert von `crossOrigin` aus dem Medienelement ab. `CrossOrigin` gibt an
   * an den Browser, der die Cookies zusammen mit den Anfragen für die Website senden sollte
   * verschiedene Assets/Wiedergabelisten
   *
   * @method Html5 #crossOrigin
   * @return {string}
   *         - anonymous zeigt an, dass die Medien keine Cookies senden sollen.
   *         - use-credentials gibt an, dass die Medien Cookies an die Anfragen senden sollen.
   *
   * @see [Spec]{@link https://html.spec.whatwg.org/#attr-media-crossorigin}
   * /
  'crossOrigin'
].forEach(function(prop) {
  Html5.prototype[prop] = function() {
    gib this.el_ [prop] zurück;
  };
});

//Umwickeln Sie native Eigenschaften mit einem Setter in diesem Format:
//setze + toTitleCase (Name)
// Die Liste sieht folgendermaßen aus:
//setVolume, setSrc, setPoster, setPreload, setPlaybackRate, setDefaultPlaybackRate,
//setDisablePictureInPicture, setCrossOrigin
[
  /**
   * Stellen Sie den Wert von `Volume` für das Medienelement ein. `Volume` gibt den Strom an
   * Audiopegel als Prozentsatz in Dezimalform. Das bedeutet, dass 1 für 100% steht, 0,5 für 50% steht und
   * so weiter.
   *
   * @method Html5 #setVolume
   * @param {Zahl} Prozentsätze als Dezimalzahl
   * Die prozentuale Lautstärke als Dezimalzahl. Der gültige Bereich liegt zwischen 0 und 1.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-a-volume}
   * /
  volumen",

  /**
   * Stellen Sie den Wert von `src` für das Medienelement ein. `src` zeigt den aktuellen
   * {@link tech~sourceObject} für die Medien.
   *
   * @method Html5 #setSrc
   * @param {Tech~SourceObject} src
   * Das Quellobjekt, das als aktuelle Quelle festgelegt werden soll.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-src}
   * /
  'src',

  /**
   * Stellen Sie den Wert von `Poster` für das Medienelement ein. `Poster` ist die URL zu
   * eine Bilddatei, die angezeigt werden kann/wird, wenn keine Mediendaten verfügbar sind.
   *
   * @method Html5 #setPoster
   * @param {string} plakat
   * Die URL zu einem Bild, das als `Poster` für die Medien verwendet werden soll
   *        element.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-poster}
   * /
  poster",

  /**
   * Stellen Sie den Wert von `preload` für das Medienelement ein. `preload` gibt an
   * was heruntergeladen werden sollte, bevor mit den Medien interagiert wird. Sie kann folgende Merkmale aufweisen
   * werte:
   * - keine: es soll nichts heruntergeladen werden
   * - Metadaten: Poster und die ersten Bilder des Mediums können heruntergeladen werden, um die
   *   medienabmessungen und andere Metadaten
   * - auto: die Medien und Metadaten für die Medien werden vor dem
   *    interaktion
   *
   * @method Html5 #setPreload
   * @param {string} vorladen
   * Der Wert von `preload`, der auf das Medienelement gesetzt werden soll. Muss 'none', 'metadata' sein,
   *         oder 'auto'.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#attr-media-preload}
   * /
  'Vorladung',

  /**
   * Stellen Sie den Wert von `PlaybackRate` für das Medienelement ein. `PlaybackRate` gibt an
   * die Geschwindigkeit, mit der die Medien wiedergegeben werden sollen. Beispiele:
   *   - Wenn playbackRate auf 2 gesetzt ist, werden die Medien doppelt so schnell abgespielt.
   *   - Wenn playbackRate auf 0,5 gesetzt ist, werden die Medien nur halb so schnell abgespielt.
   *
   * @method Html5 #setPlaybackRate
   * @return {number}
   *         Der Wert von "PlaybackRate" aus dem Medienelement. Eine Zahl, die angibt
   *         die aktuelle Wiedergabegeschwindigkeit des Mediums, wobei 1 die normale Geschwindigkeit ist.
   *
   * @see [Spec]{@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-playbackrate}
   * /
  playbackRate',

  /**
   * Stellen Sie den Wert von `defaultPlaybackRate` für das Medienelement ein. `defaultPlaybackRate` gibt an
   * die Geschwindigkeit, mit der das Medium beim ersten Start wiedergegeben werden soll. Diesen Wert ändern
   * nachdem ein Video gestartet wurde, wird nichts getan. Stattdessen solltest du {@link Html5 #setPlaybackRate} verwenden.
   *
   * Beispielwerte:
   *   - Wenn playbackRate auf 2 gesetzt ist, werden die Medien doppelt so schnell abgespielt.
   *   - Wenn playbackRate auf 0,5 gesetzt ist, werden die Medien nur halb so schnell abgespielt.
   *
   * @method html5.prototype.setDefaultPlaybackRate
   * @return {number}
   *         Der Wert von `defaultPlaybackRate` aus dem Medienelement. Eine Zahl, die angibt
   *         die aktuelle Wiedergabegeschwindigkeit des Mediums, wobei 1 die normale Geschwindigkeit ist.
   *
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-defaultplaybackrate}
   * /
  'defaultPlaybackRate',

  /**
   * Verhindert, dass der Browser ein Bild-im-Bild-Kontextmenü vorschlägt
   * oder um in einigen Fällen automatisch Bild-im-Bild anzufordern.
   *
   * @method Html5 #setDisablePictureInPicture
   * @param {boolean} value
   * Der wahre Wert deaktiviert den Bild-im-Bild-Modus.
   *
   * @see [Spec]{@link https://w3c.github.io/picture-in-picture/#disable-pip}
   * /
  disablePictureInPicture',

  /**
   * Stellen Sie den Wert von `crossOrigin` aus dem Medienelement ein. `CrossOrigin` gibt an
   * an den Browser, der die Cookies zusammen mit den Anfragen für die Website senden sollte
   * verschiedene Assets/Wiedergabelisten
   *
   * @method Html5 #setCrossOrigin
   * @param {string} CrossOrigin
   *         - anonymous zeigt an, dass die Medien keine Cookies senden sollen.
   *         - use-credentials gibt an, dass die Medien Cookies an die Anfragen senden sollen.
   *
   * @see [Spec]{@link https://html.spec.whatwg.org/#attr-media-crossorigin}
   * /
  'crossOrigin'
].forEach(function(prop) {
  Html5.prototype['set' + toTitleCase(prop)] = function(v) {
    this.el_[prop] = v;
  };
});

//native Funktionen mit einer Funktion umwickeln
// Die Liste sieht folgendermaßen aus:
//Pause, Laden, Abspielen
[
  /**
   * Ein Wrapper rund um die `pause`-Funktion der Medienelemente. Dadurch wird das `HTML5` aufgerufen
   * Funktion `Pause` für Medienelemente.
   *
   * @method Html5 #pause
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-pause}
   * /
  pause",

  /**
   * Ein Wrapper rund um die `load`-Funktion der Medienelemente. Dies ruft die `HTML5`s
   * Funktion „Laden“ des Medienelements.
   *
   * @method Html5 #load
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-load}
   * /
  'laden',

  /**
   * Ein Wrapper rund um die `Play`-Funktion der Medienelemente. Dies ruft die `HTML5`s
   * Funktion „Abspielen“ des Medienelements.
   *
   * @method Html5 #play
   * @see [Spezifikation] {@link https://www.w3.org/TR/html5/embedded-content-0.html#dom-media-play}
   * /
  'spielen'
].forEach(function(prop) {
  Html5.prototype[prop] = function() {
    gib this.el_ [prop] ();
  };
});

tech.withSourceHandlers (Html5);

/**
 * Nativer Quellhandler für Html5, übergibt einfach die Quelle an das Medienelement.
 *
 * @property {tech~sourceObject} Quelle
 *        Das Quellobjekt
 *
 * @property {Html5} technik
 * Die Instanz der HTML5-Technologie.
 * /
html5.nativeSourceHandler = {};

/**
 * Prüfe, ob das Medienelement den angegebenen MIME-Typ abspielen kann.
 *
 * @param {string} type
 *        Der zu prüfende Mimetyp
 *
 * @return {string}
 *         'wahrscheinlich', 'vielleicht', oder '' (leere Zeichenfolge)
 * /
html5.nativeSourceHandler.canPlayType = Funktion (Typ) {
  //IE ohne MediaPlayer gibt einen Fehler aus (#519)
  versuche {
    return Html5.TEST_VID.canPlayType(type);
  } catch (e) {
    zurückgeben '';
  }
};

/**
 * Prüfen Sie, ob das Medienelement eine Quelle nativ verarbeiten kann.
 *
 * @param {Tech~SourceObject} source
 * Das Quellobjekt
 *
 * @param {Object} [Optionen]
 * Optionen, die an den Techniker weitergegeben werden müssen.
 *
 * @return {string}
 * 'wahrscheinlich', 'vielleicht' oder "(leere Zeichenfolge).
 * /
html5.nativeSourceHandler.canHandleSource = Funktion (Quelle, Optionen) {

  //Wenn ein Typ angegeben wurde, sollten wir uns darauf verlassen
  if (source.type) {
    gib html5.nativeSourceHandler.canPlayType (source.type) zurück;

  //Wenn kein Typ, greifen Sie auf das Häkchen bei 'video/ [EXTENSION] 'zurück
  } sonst wenn (source.src) {
    const ext = URL.getFileExtension (source.src);

    gib html5.nativeSourceHandler.canPlayType (`video/$ {ext} `) zurück;
  }

  zurückgeben '';
};

/**
 * Übergeben Sie die Quelle an das native Medienelement.
 *
 * @param {Tech~SourceObject} source
 *        Das Quellobjekt
 *
 * @param {Html5} tech
 * Die Instanz der Html5-Technologie
 *
 * @param {Object} [Optionen]
 * Die Optionen zur Weitergabe an die Quelle
 * /
html5.nativeSourceHandler.handleSource = Funktion (Quelle, Technik, Optionen) {
  tech.setSrc (Quelle.src);
};

/**
 * Ein Noop für die native Dispose-Funktion, da keine Bereinigung erforderlich ist.
 * /
html5.nativeSourceHandler.dispose = funktion () {};

//Registriere den nativen Quell-Handler
html5.registerSourceHandler (html5.nativeSourceHandler);

tech.registerTech ('Html5', Html5);
exportiert Standard-Html5;