How to enable CORS for html5 video loading vtt file?
Asked Answered
G

2

10

My Need

html5 video element loads both a video and a vtt file saved in a different domain.

The problem

vtt is not loaded and error Text track from origin has been blocked from loading: Not at same origin as the document, and parent of track element does not have a 'crossorigin' attribute.

My investigation

I am aware that CORS needs to be used so vtt can be loaded in html5 successfully.

I have enabled CORS on server side for requests from any domain.

Some articles say adding crossorigin or crossorigin="anonymous" into ` element can do the job, but it doesn't work. Either the video is not loaded at all or different errors appear

I have put my code here below

<body>
  <div class="container">
    <video id="myvideo" controls preload="auto" width="640" height="264" autoplay>
      <source src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.mp4 type="video/mp4"></source>
      <track kind="captions" label="English" srclang="en" src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.vtt default>
    </video>
</body>
Gnathic answered 27/8, 2017 at 6:32 Comment(0)
B
8

Hopefully this helps the next person to stumble upon this SO question. I discovered that IE (10 and 11) does not support loading a cross-origin VTT file for a <track>, even if CORS is enabled. In order to add IE support for captions, I had to use a script like the one below.

This script downloads each VTT file via AJAX, creates a blob URL, and replaces each <track> src with its respective blob URL.

window.addEventListener("load", function() {
  if (window.navigator.userAgent.indexOf("MSIE ") < 0 && window.navigator.userAgent.indexOf("Trident/") < 0) {
    // Not IE, do nothing.
    return;
  }

  var tracks = document.querySelectorAll("track")

  for (var i = 0; i < tracks.length; i++) {
    loadTrackWithAjax(tracks[i]);
  }
});

function loadTrackWithAjax(track) {
  var xhttp = new XMLHttpRequest();

  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200 && this.responseText) {
      // If VTT fetch succeeded, replace the src with a BLOB URL.
      var blob = new Blob([this.responseText], { type: 'text/vtt' });
      track.setAttribute("src", URL.createObjectURL(blob));
    }
  };
  xhttp.open("GET", track.src, true);
  xhttp.send();
}
<video controls preload width="600" height="337.5" autoplay crossorigin="anonymous">
      <source src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4" type="video/mp4"></source>
      <track kind="captions" label="English" srclang="en" src="https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt" default>
</video>
Borisborja answered 4/11, 2019 at 17:29 Comment(2)
I'm not sure if I would want to add this amount of code on my production for a vtt file but this is smart... Nice work.Tranquillize
Well, you can minify it :)Borisborja
Z
6

I can confirm that the crossorigin=anonymous attribute on the video element does indeed load the text track as expected.

Give this code a shot:

<video id="myvideo" controls preload="auto" width="640" height="264" autoplay crossorigin="anonymous">
      <source src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.mp4 type="video/mp4"></source>
      <track kind="captions" label="English" srclang="en" src=http://video.dublearn.net/-KqIgE-3roMSBbiHUmLI/video.vtt default>
</video>

Finally, remember, you must use a web server to serve this HTML snipped - this cannot be done locally (ie. file//).

If you're familiar with node - install http-server, run with --cors and use ngrok.

Zaffer answered 28/8, 2017 at 7:6 Comment(2)
Hello, when I put the code in jsfiddle for instance, it does not go. I also tried the same in a node server. Check here jsfiddle.net/zbg8b0bjGnathic
Worked for me on a CodePenApplesauce

© 2022 - 2024 — McMap. All rights reserved.