Question

I'm new to using the audio tag in HTML 5 and wanted to build a player. I wanted to test using a VTT file in a track tag to see how closed captioning could work.

Here is my code:

<audio controls>
    <source src="myaudio.mp3" type="audio/mpeg">
    <track kink="caption" src="myaudio.vtt" srclang="en" label="English">
</audio>

According to what I've read, track is supposed to work for both audio and video, which makes sense from an accessibility stand-point. What doesn't make sense is the error I get trying to load it:

"Text track from origin 'file://' has been blocked from loading: Not at same origin as the document, and parent of track element does not have a 'crossorigin' attribute. Origin 'null' is therefore not allowed access."

When looking up the crossorigin attribute, I get a lot of confusing articles about CORS and the expected values of "anonymous" and "user-certificate". Trying either results in a similar error.

Any ideas as to why this won't work?

Was it helpful?

Solution 2

See here for an update list of browser with native WebVTT support. If your browser does not support native CC as WebVTT you have to construct your own parser in JavaScript to display them (note there are other CC format like SRT and TTML/DFXP).

You can find reliable information about the track element here and here. Note that there is a difference between what is referred to as subtitles, captions and descriptions.

Most browsers won't support a track tag when used with an audio tag - though in theory they should - you will find practically it does not work as of today. Maybe it has something to do with WebVTT meaning Web Video Text Tracks. This is described here.

You have to build your own parser if you want to display your closed captions along an audio tag. I would suggest you take a look at the source of mediaelementjs to get an idea on how to tackle this.

CORS is only required when you are requesting CC files that are not on the same domain as the page hosting the audio/video tag. It should not be necessary in your case. More about CORS.

Your error message seems to indicate you have a misconfiguration somewhere in your system (maybe your vtt file is on NFS?).

OTHER TIPS

This is an old post, but the first I hit when Googling for Text track from origin 'SITE_HOSTING_TEXT_TRACK' has been blocked from loading: Not at same origin as the document, and parent of track element does not have a 'crossorigin' attribute. Origin 'SITE_HOSTING_PAGE' is therefore not allowed access.

The OP seems to be having this issue locally and he could fix that by disabling Chrome's web security as shown above. But users will more often see this when accessing their text tracks from a different domain. To fix it in a production environment for all users, you need to do two things:

  1. Add the right CORS headers to the site hosting the VTT file.
  2. Add the crossorigin="anonymous" attribute to your site's audio/video element.

If you do not have access to the site hosting the video file, you might be stuck. But if you do, you should add the header Access-Control-Allow-Origin:'*'. I'm handling it on a Node/Express server like this:

   var app = express()
    app.use(function (req, res, next) {
      res.header('Access-Control-Allow-Origin', '*')
      res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept')
      next()
    })

The audio/video element is an easier fix. In your site's HTML page, add the following crossorigin attribute.

<audio controls crossorigin="anonymous">
    <source src="myaudio.mp3" type="audio/mpeg">
    <track kind="caption" src="my_file_hosted_on_a_different_domain.vtt" srclang="en" label="English">
</audio>

I hope this answer helps someone... it was an annoying issue to troubleshoot.

I've been dealing with the same issue: the media player works fine, but the closed captioning file runs into cross-domain issues. Some browsers choke, others do not. Some browsers want a specific CORS policy and will not accept a wildcard in the allowed origin. And that makes my life complicated.

We could store the caption files on our primary content server. But we prefer to maintain the video and caption files in the same location (in my case, on Amazon Web Services S3/CloudFront). To get around the CORS complications, we built a small server-side script to grab the tiny caption files from the CDN. That eliminates all cross-domain issues.

https://github.com/videogular/videogular/issues/123

Add crossorigin="anonymous" to the video tag to allow load VTT files from different domains.

It is a strange issue, even if your CORS is set correctly on the server, you may need to have your HTML tag label itself as anonymous for the CORS policy to work.

Here's how I get this working in my web-component (lit-html based) by fetching the webVTT via a seperate HTTP call and injecting the content into the SRC property of the <track> element whenever the subtitle/metadata track changes or is rendered:

<video class="video__player" @click=${e=> this._onVideoPress(e)}
          poster=${this.poster}
          preload="auto"
        >
          <source src=${this.URL} type="video/webm" />
          <source src=${this.URL2} type="video/mp4" />

          <track
            default
            kind="metadata"
            type="text/vtt"
            @cuechange=${e => this._doSomething(e)}
            src=${this.metadata}
          />
        </video>

  updated(changedProperties) {
    if (changedProperties.has('metadata')) {
      const tracks = this.shadowRoot.querySelectorAll('track');
      tracks.forEach(track => this.loadTrackWithAjax(track))
      }
    }
  

  // eslint-disable-next-line class-methods-use-this
  loadTrackWithAjax(track) {
    const 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.
        const blob = new Blob([this.responseText], { type: 'text/vtt' });
        track.setAttribute('src', URL.createObjectURL(blob));
      }
    };
    xhttp.open('GET', track.src, true);
    xhttp.send();
  }

My videos and tracks are stored in the same firebase storage bucket but the browser refused to load the tracks even when changing the CORS and crossorigin settings (which stopped even the videos from loading).

I faced a multitude of error and I'm listing all of them here just in case if it helps someone:

  1. First error related to CORS exactly same OP as mentioned in his question.

Text track from origin 'file://' has been blocked from loading: Not at same origin as the document, and parent of track element does not have a 'crossorigin' attribute. Origin 'null' is therefore not allowed access.

The problem was that I was loading my html file in browser directly from disk so when it tries to access the vtt file then browser gets a feeling of cross origin request and hence the error. You can get rid of this error simply by hosting your web page inside a web server like IIS. It is a 2-minute job to create a website in IIS. Or you can simply add a new application inside the existing "Default Web site" which comes with default installation of IIS.

The moment you start fetching your html page like a website all the files like video, or *.vtt are all relative so issue of CORS gets resolved.

  1. After CORS issue got resolved I started getting below error for *.vtt file:

Failed to load resource: the server responded with a status of 404 (Not Found)

Now this issue relates to the fact that *.vtt is an unknown file type for IIS and your IIS is not configured to server any resource with extension .vtt. For this you need to configure the MIME type for your web application in IIS with below details:

File Name Extension: .vtt
MIME type: text/vtt

enter image description here

This resolved my file not found error.

  1. Now no errors were being shown in the developer tools console tab but my subtitles were still not getting shown. Then came the final trick. I had forgotten to mention default attribute in my track tag as shown below. It is a mandatory hint for the browser to pick up the appropriate vtt file:

<track label="English" kind="subtitles" srclang="en" src="./data/abc.vtt" default />

Now my subtitles finally worked :)

You might want to add the following lines in your Web.config if you get a "404: not found" error:

<system.webServer>
    <staticContent>
        <remove fileExtension=".vtt" /> <!--REMOVES SERVER .vtt extention if it exists-->
        <mimeMap fileExtension=".vtt" mimeType="text/vtt" /> <!--ads it again (needed when debuging)-->
    </staticContent>
</system.webServer>
</configuration>

Note that .vtt is not supported from scratch, and thus Chrome (among others) blocks the content for security reasons.

i solve this problem using Blob !

(async () => {
                  const result = await axios({
                    url: `http://ROUTE_TO_YOUR_VTT_FILE`,
                    method: "get",
                    responseType: "blob",
                  });
                  playerRef?.addRemoteTextTrack(
                    {
                      src: URL.createObjectURL(result as Blob),
                      mode: "showing",
                      id: subtitle.languageId,
                      language: subtitle.languageName,
                      kind: "subtitles",
                      default: true,
                      label: subtitle.languageName,
                      srclang: subtitle.languageName,
                    },
                    true
                  );
                })();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top