问题
I'm having trouble casting a self-hosted JW Player video. Here's the relevant reference in the Javascript API for configuring the player.
https://developer.jwplayer.com/jw-player/docs/developer-guide/customization/configuration-reference/#casting
Here are some details about my setup:
1) The video is in HLS streaming format. So the file that I'm passing to the JW Player Javascript API has .m3u8 extension.
2) The video is hosted on S3.
3) The video is served through CloudFront.
Here's the code that I use to load the video in JW Player:
<div id="jwplayer"></div>
var playerInstance = jwplayer('jwplayer');
playerInstance.setup({
file: <cloudfront-path-to-m3u8-file>,
androidhls: true,
cast: {},
});
When I use version 7.12.13 of the JW Player Javascript library, here's what I observe:
1) The video loads fine in the browser.
2) When I try to cast it, I see a spinner in the video in the browser, indicating that it's about to start playing via Chromecast.
3) The Chromecast looks like it's about to start playing the video on the TV. I see the Chromecast symbol with a spinner, then the video timeline bar.
4) Within a few seoncds, I see the Chromecast home screen. The video never plays on the TV.
5) At this point, the video start playing in the browser.
6) I see the following error message in the browser debug console:
provider.cast.js:1 Error: {code: "session_error", description:
"LOAD_FAILED", details: {…}}code: "session_error"description:
"LOAD_FAILED"details: {type: "LOAD_FAILED"}__proto__: Object
d.error @ provider.cast.js:1
(anonymous) @ cast_sender.js:70
U.onMessage @ cast_sender.js:76
M.i @ cast_sender.js:56
When I use version 8.6.3 of the JW Player Javascript library, here's what I observe:
1) The video loads fine in the browser.
2) When I try to cast it, I see a spinner in the video in the browser, indicating that it's about to start playing via Chromecast.
3) The Chromecast looks like it's about to start playing the video on the TV. I see the Chromecast symbol with a spinner, then the video timeline bar.
4) After a few seconds, I only see the Chromecast symbol on the TV.
5) The spinner in the video player in the browser spins indefinitely.
6) I see the following error message in the browser debug console:
provider.cast.js:10 Uncaught TypeError: Cannot read property 'trigger' of undefined
at c.<anonymous> (provider.cast.js:10)
at s (application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3)
at c.a [as trigger] (application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3)
at t.error (provider.cast.js:10)
at cast_sender.js:70
at U.onMessage (cast_sender.js:76)
at M.i (cast_sender.js:56)
(anonymous) @ provider.cast.js:10
s @ application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3
a @ application-0a118d5fa8c4bb8de5f5da2cc04ef8c3a0cc5bf84da710890d3a90e9c79a04ee.js:3
t.error @ provider.cast.js:10
(anonymous) @ cast_sender.js:70
U.onMessage @ cast_sender.js:76
M.i @ cast_sender.js:56
Any ideas about what these errors mean or how to go about debugging this issue?
Note that I ran the above tests in Chrome (version 71.0.3578.98 64-bit) on Ubuntu 14.04. I also tried casting these pages from an Android device, but got the same results.
A few things I've tried:
- Configured CORS in S3 bucket to allow access from these domains.
- Added crossdomain.xml to S3 bucket to allow access from these domains.
- Invalidating cached objects in CloudFront edges.
- Clearing browser cache.
In trying to isolate the problem, I also tried the following:
- Replace m3u8 file with webm file. I can successfully cast with this setup.
- Replace m3u8 file with mp4 file. I can successfully cast with this setup.
- Replace CloudFront path with direct S3 path. I observe the same problematic behavior I described above (i.e., cannot cast and see errors in the console).
I discovered that changing the CORS configuration for the S3 bucket to allow access from all origins fixes the problem:
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<ExposeHeader>ETag</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
However, this is certainly not ideal because it opens up the bucket to access from any domain. I tried to restrict access by explicitly specifying CORSRule
blocks for the domain that I use to serve the video player. I also tried adding http://*.jwpcdn.com
and https://*.jwpcdn.com
as allowed origins, since I believe that's where JWPlayer's Chromecast receiver is hosted.
https://support.jwplayer.com/articles/cross-domain-file-loading-reference
None of these combinations worked. The only way I could get JW Player to successfully cast the HLS video was to allow access from all origins.
Any idea how I can configure CORS to get the desired behavior without sacrificing the privacy of the bucket.
Thanks!
回答1:
It turns out I also needed to allow access from https://*.gstatic.com. This is in addition to http://*.jwpcdn.com and the domain on which the video player is being hosted. I can now successfully cast an HLS video from JW Player versions 7 and 8!
After these changes, here's what the CORS configuration looks like for my S3 bucket:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://my-domain-with-video-player.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>http://*.jwpcdn.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
<CORSRule>
<AllowedOrigin>https://*.gstatic.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
来源:https://stackoverflow.com/questions/53800705/cors-configuration-for-s3-hosted-hls-video-in-jw-player