videojs player.textTracks() 在 safari 上返回错误类型的对象,无法捕获 TextTrackuechange 事件

S. *_*Imp 5 html javascript video metadata video.js

我正在尝试处理与视频相关的一些 TextTrack 信息。我从 Mux.com 嵌入了一个视频,其中包含包含节目数据时间 (PDT) 的元数据。大多数浏览器都会表现,但 videojs 似乎在 safari 中返回不同类型的对象,因此我无法附加事件侦听器来捕获uechange 事件并提取其 PDT 日期字符串。

在我测试的大多数浏览器(Firefox、Chrome、Edge 等)上,此代码将在 DIV#sneakyimp_pdt 中正确显示最新的 PDT,但在 Safari 中,videojs player.textTracks() 函数返回的对象是不同的类型。Safari 生成的metadataTrack 对象是一个TextTrack对象,而不是像大多数浏览器中那样是某种e类。即便如此,我似乎无法将任何事件侦听器附加到TextTrackuechange事件。

有人可以告诉我我在这里做错了什么吗?我添加了相当多的特殊情况代码来尝试将侦听器附加到这些文本轨道,但它仍然不起作用。

<div id="sneakyimp">
  <figure>
    <video class='mux-player video-js' width=1920 height=1080 poster='https://example.com/foo.thumb.jpg' controls preload='metadata'>
      <source src='https://stream.mux.com/VIDEO-ID-HERE.m3u8' type='application/x-mpegURL' />
    </video>
  </figure>
</div>
<div id="sneakyimp_pdt">PDT WILL LOAD HERE</div>
<div id="sneakyimp_ct">currentTime WILL LOAD HERE</div>
<script>
// the videojs player object
let player = null;
function myPlayerInit() {
    const metadataTrack = Array.prototype.find.call(player.textTracks(), track => track.label === 'segment-metadata');
    if (!metadataTrack) {
      console.log('metadataTrack NOT FOUND');
    } else {
      // in Safari, construct.name is TextTrack, on other browsers, it's just e
      console.log('metadataTrack located, constructor name is ' + (metadataTrack.constructor.name));
      console.log(metadataTrack);
    }
    if (!metadataTrack.on) {
      // THIS RUNS ON SAFARI
      console.log('metadataTrack has no on method, will try addEventListener');
      // THIS NEVER FIRES
      metadataTrack.addEventListener('cuechange', function () {
        console.log('event listener cuechange firing');
        let cues = metadataTrack.activeCues;
        console.log("cues found, type=" + (typeof cues)); 
        let pdt = metadataTrack.activeCues[0].value.dateTimeString;
        if (!pdt) {
          console.log('no pdt womp womp. pdt type=' + (typeof pdt));
        }
        console.log('pdt: ' + pdt);
        document.getElementById('sneakyimp_pdt').innerHTML = pdt;
      });
      console.log('metadataTrack.addEventListener added');
      console.log('also trying oncuechange');
      // THIS NEVER FIRES
      metadataTrack.oncuechange = function() {
        console.log('oncuechange running');
      }
    } else {
      // THIS RUNS ON FIREFOX, CHROME, EDGE, ETC
      console.log('adding metadataTrack.on listener');
      metadataTrack.on('cuechange', () => {
        let pdt = metadataTrack.activeCues[0].value.dateTimeString;
        document.getElementById('sneakyimp_pdt').innerHTML = pdt;
      });
    }
    // THIS WORKS ON ALL BROWSERS I'VE TESTED
    player.on('timeupdate', (evt) => {
      document.getElementById('sneakyimp_ct').innerHTML = player.currentTime();
    });
}
// sometimes loadedmetadata seems to fire loadeddata before
// DOMready so we have this
let loadedmetadata = false;
let myVideo = document.querySelector("#sneakyimp video");
if (myVideo) {
  window.addEventListener('loadedmetadata', function(ev) {
      console.log('directly added, pre-dom loadedmetadata fired');
      loadedmetadata = true;
  }, true);
}
// we wait for DOM to do most of this stuff
window.addEventListener('DOMContentLoaded', (event) => {
    let video = document.querySelector("#sneakyimp video");
    if (!video) {
        throw "no video found";
    }
    player = videojs(video.id, {
      html5: {
        nativeTextTracks: false,
        vhs: {
          overrideNative: true
        }
      }
    });

    window.player = player;
    if (loadedmetadata) {
      console.log('loadedmetadata fired before domready, firing myPlayerInit');
      myPlayerInit();
    } else {
      console.log('attaching loadeddata event to player');
      player.on('loadeddata', () => {
        console.log("== player loadeddata, firing myPlayerInit ==");
        myPlayerInit();
      });
    }
});
</script>
Run Code Online (Sandbox Code Playgroud)

正如我上面提到的,这段代码适用于大多数浏览器。在 Safari 中,它会报告一些内容:

  • 位于metadataTrack,构造函数名为TextTrack
  • metadataTrack 没有 on 方法,将尝试 addEventListener
  • 添加了metadataTrack.addEventListener
  • 也在尝试改变

但是,我添加的事件侦听器从未触发。