2

so I'm encountering some unexpected behavior with subtitles on an HTML5 video.

I am storing my video + subtitles files on Google Cloud Storage and I have a web interface to watch the movies.

My server generates signed URLs for the movie and subtitle files. The movies play fine, and I can view the subtitle text content using the URL. However, using the <track> does not work:

<track label="my_subtitle_file" src="my_signed_url" srclang="en" kind="subtitles">

In Firefox I get an error:

Security Error: Content at <my site> may not load data from <signed GCS url> 

In Chrome I get a slightly different error, but I imagine it's the same problem:

Unsafe attempt to load URL <signed GCS URL> from frame with URL <my site>.
Domains, protocols and ports must match.

I suppose I could make a wrapper endpoint on my backend, which fetches the content of the file and serves it. But I am wondering, is there another way? And why do <track> nodes have this severe restriction?

edit

I added a CORS policy to the GCS bucket:

[
  {
    "origin": ["https://my-domain.com"],
    "responseHeader": ["Content-Type"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]

On the GCS Console I also tried removing the "prevent public access setting". I didn't make the files public though (I still want to require presigned URLs), but it seems GCS is kinda wierd in that you can turn of "prevent public access" without actually making it public.

max pleaner
  • 26,189
  • 9
  • 66
  • 118
  • Can you set a CORS header on the google storage (so it's added to responses)? I think if that allowed your origin, it would probably work. – Gabor Lengyel Jun 30 '22 at 13:58
  • I added CORS to the GCS bucket. but still getting the same error. The error in the network tab says "blocked" with "not same origin" but I don't see any OPTIONS request or response code so I can't tell if the browser is the one blocking the request or not – max pleaner Jun 30 '22 at 15:56
  • Can you do a `fetch()` on the VTT file? Once loaded into ArrayBuffer, you can dynamically load it (as Blob) using `createObjectURL()`... – VC.One Jun 30 '22 at 16:35
  • Your problem is caused by an incorrect or lack of CORS configuration on the Cloud Storage object. Edit your question with details on how Cloud Storage is set up and the returned headers. Use the CLI **curl** command to check which headers are returned. – John Hanley Jun 30 '22 at 19:50
  • You may check a few documents for help :https://cloud.google.com/storage/docs/configuring-cors https://cloud.google.com/storage/docs/access-control/signing-urls-manually#algorithm – Vaidehi Jamankar Jul 04 '22 at 10:26
  • This seems to be an issue related to browser side security limitations.[Refer](https://wordpress.org/support/topic/unsafe-attempt-to-load-url-from-frame-with-url-domains-protocols-and-ports-mus/) Check for CORS config [here](https://cloud.google.com/storage/docs/configuring-cors#troubleshooting:~:text=storage.cloud.google.com) – Vaidehi Jamankar Jul 05 '22 at 09:59
  • Hi guys, I'm sorry to leave this question hanging. I ended up just using the workaround which is to make a wrapper endpoint on the server side so I don't have to deal with the CORS stuff. – max pleaner Jul 07 '22 at 15:25

1 Answers1

0

Setting up CORS for this use case is not enough because some browsers are not even trying to make HTTP request to load subtitles.

So to load subtitles from the external domain you need to:

  1. Configure CORS policy to allow that (e.g. Access-Control-Allow-Origin: *)
  2. Add crossorigin="anonymous" attribute to your <video> tag.
Inferpse
  • 4,135
  • 1
  • 31
  • 39