加载VTT文件时出现跨域错误

13

жҲ‘жҳҜHTML5дёӯaudioж Үзӯҫзҡ„ж–°жүӢпјҢжғіиҰҒе»әз«ӢдёҖдёӘж’ӯж”ҫеҷЁгҖӮжҲ‘жғіжөӢиҜ•дҪҝз”Ёtrackж Үзӯҫдёӯзҡ„VTTж–Ү件жқҘжҹҘзңӢеҰӮдҪ•е·ҘдҪңгҖӮ

иҝҷжҳҜжҲ‘зҡ„д»Јз Ғпјҡ

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

根据我所了解的,track应该既适用于音频也适用于视频,这在可访问性方面是有意义的。但是,我试图加载它时得到的错误信息就没有意义了:

"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."
当查找crossorigin属性时,我得到了许多关于CORS以及“anonymous”和“user-certificate”预期值的令人困惑的文章。尝试任何一个都会导致类似的错误。
有任何想法为什么这行不通?

我可以确认这个问题适用于Google Chrome 39以及通过file:///加载的所有文件。如果通过http://加载,它是可以正常工作的。 - alex
我在Chrome 42上遇到了同样的问题。但是Firefox 37.0.2没有任何问题。 - Alaa M.
我刚刚通过禁用安全性来运行Chrome解决了这个问题:chrome.exe --disable-web-security。在这里查看答案:https://dev59.com/QnA75IYBdhLWcg3wy8Ui - Alaa M.
经常发生在运行在Web服务器之外的情况下。 - jopasserat
8个回答

18

这篇文章有些旧,但在使用谷歌搜索 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. 时,它是我找到的第一个结果。

原帖作者似乎在本地遇到了这个问题,并可以通过上述方法禁用Chrome的Web安全来解决。但用户更常见的情况是从不同的域名访问文本轨迹。为了为所有用户在生产环境中修复此问题,您需要执行两项操作:

  1. 向托管VTT文件的站点添加正确的CORS标头。
  2. 向您网站的音频/视频元素添加 crossorigin="anonymous" 属性。

如果您无法访问托管视频文件的站点,则可能会陷入困境。但如果您可以访问,则应该添加头部 Access-Control-Allow-Origin:'*'。我在Node / Express服务器上处理如下:

   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()
    })

音频/视频元素很容易修复。在您网站的HTML页面中,添加以下crossorigin属性。

<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>

我希望这个回答能够帮助到某个人……这是一个令人烦恼的问题需要排除故障。


当我在localhost:3000上运行应用程序并从localhost提供vtt文件时,遇到了这个问题。只需添加 crossorigin="anonymous" 就可以解决此问题。为什么特别是对此的安全性要求如此严格? - Scribblemacher
如果我要猜的话,他们从一开始就加强了安全性,因为这是一个新功能。在已经推出多年的技术上实施此类安全修复要困难得多。 - TimHayes
在Javascript中,它是这样的:video.crossOrigin = "anonymous"; - Andreas Riedmüller

9
请参阅此处,了解本地支持WebVTT的浏览器的更新列表。如果您的浏览器不支持WebVTT作为本地CC,则必须在JavaScript中构建自己的解析器来显示它们(请注意,还有其他CC格式,如SRT和TTML / DFXP)。
您可以在这里这里找到关于track元素的可靠信息。请注意,字幕、标题和描述之间存在差异。
大多数浏览器在与音频标签一起使用track标记时不支持它-尽管从理论上讲应该支持-但实际上今天却不起作用。也许这与WebVTT表示Web视频文本轨道有关,这在这里有描述。
如果您想在音频标签旁边显示您的闭式字幕,则必须构建自己的解析器。我建议您查看mediaelementjs的源代码,以了解如何解决此问题。
仅当您请求与托管音频/视频标签的页面不在同一域中的CC文件时,才需要CORS。在您的情况下,这应该是不必要的。有关CORS的更多信息。
您的错误消息似乎表明您的系统中某处存在配置错误(也许您的vtt文件在NFS上?)。

5

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

为了允许从不同的域加载VTT文件,请在视频标签中添加crossorigin="anonymous"。

这是一个奇怪的问题,即使您的服务器上正确设置了CORS,您可能仍需要将HTML标签标记为匿名,以使CORS策略生效。


4
我一直在处理同样的问题:媒体播放器工作正常,但是关闭字幕文件遇到了跨域问题。一些浏览器会出现问题,而另一些则不会。一些浏览器需要特定的CORS策略,并且不接受允许来源中的通配符。这让我的生活变得很复杂。
我们可以将字幕文件存储在主要内容服务器上。但是我们更喜欢将视频和字幕文件保存在同一个位置(在我的情况下,是在Amazon Web Services S3 / CloudFront上)。为了解决CORS的问题,我们构建了一个小型的服务器端脚本,从CDN获取微小的字幕文件。这消除了所有跨域问题。

我知道这是一个旧帖子,但我在S3 / Cloudfront上遇到了完全相同的问题。下载VTT文件不会首先调用OPTIONS请求。因此,在使用Cloudfront时,GET请求会出现CORS错误。 我解决这个问题的方法是使用lambda@edge函数为“查看器响应”设置cors标头。 希望这能帮助到某些人。 - Mark Hayward

3

以下是我如何在基于lit-html的Web组件中使其正常工作的步骤。通过进行单独的HTTP调用来获取WebVTT,并将其内容注入到<track>元素的SRC属性中,每当字幕/元数据轨道更改或呈现时执行此操作:

<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();
  }

我的视频和音轨存储在同一个Firebase存储桶中,但是即使更改了CORS和crossorigin设置(这导致甚至无法加载视频),浏览器仍然拒绝加载音轨。


2

我遇到了很多错误,我在这里列出它们,以防对某些人有所帮助:

  1. 第一个错误与CORS相关,与提问者的问题完全相同。

来自“file://”的文本跟踪已被阻止加载:与文档不在同一起源,并且跟踪元素的父级没有“crossorigin”属性。因此,不允许访问原点“null”。

问题在于我直接从磁盘中的浏览器加载我的html文件,因此当它尝试访问vtt文件时,浏览器会感受到跨域请求的感觉,因此出现了错误。您可以通过在IIS中托管您的网页来轻松摆脱此错误。在IIS中创建一个网站只需要2分钟。或者,您可以在默认安装的“默认Web站点”中添加一个新应用程序。

一旦您开始像网站一样获取您的html页面,所有文件(如视频或*.vtt)都是相对的,因此CORS问题得到解决。

  1. 在CORS问题得到解决后,我开始收到以下*.vtt文件的错误:

无法加载资源:服务器响应状态为404(未找到)

现在,这个问题涉及到*.vtt是IIS的未知文件类型,您的IIS没有配置为提供任何扩展名为.vtt的资源。因此,您需要使用以下详细信息在IIS中为您的Web应用程序配置MIME类型:

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

这里输入图片描述

这解决了我的文件找不到错误。

  1. 现在开发者工具控制台选项卡中没有显示任何错误,但我的字幕仍然没有显示。最后的诀窍出现了。我忘记在我的轨道标签中提及default属性,如下所示。这是浏览器选择适当vtt文件的必要提示:

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

现在我的字幕终于正常工作了 :)

0
如果您遇到“404:未找到”错误,您可能需要在Web.config中添加以下行:
<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>

请注意,从头开始不支持.vtt格式,因此谷歌浏览器(等其他浏览器)出于安全考虑会阻止该内容的播放。

0
我使用 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
                  );
                })();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接