Called proxy with URL http://192.168.xx.xx:8080/3hyw7hwoajn21/HLSPlaylist.m3u8 Called proxy with URL http://192.168.xx.xx:8080/3hyw7hwoajn21/HLS_540_v4.m3u8 Called proxy with URL http://192.168.xx.xx:8080/3hyw7hwoajn21/HLS_AUDIO_160_K_v4.m3u8 Called proxy with URL http://192.168.xx.xx:8080/3hyw7hwoajn21/HLS_224_v4.m3u8
Here's an example Reddit video: https://www.reddit.com/r/me_irl/comments/b3vrs4/me_irl
Looking through the JSON, it has a few options for video sources:
"reddit_video": {
"dash_url": "https://v.redd.it/3hyw7hwoajn21/DASHPlaylist.mpd",
"duration": 76,
"fallback_url": "https://v.redd.it/3hyw7hwoajn21/DASH_720?source=fallback",
"height": 720,
"hls_url": "https://v.redd.it/3hyw7hwoajn21/HLSPlaylist.m3u8",
"is_gif": false,
"scrubber_media_url": "https://v.redd.it/3hyw7hwoajn21/DASH_240",
"transcoding_status": "completed",
"width": 1280
}
While I seemingly can get other HLS/m3u8 videos to work with the Chromecast SDK (for example Google's own example HLS video), I cannot seem to get any of these sources to work.
I've tried https://v.redd.it/3hyw7hwoajn21/HLSPlaylist.m3u8 with the stream type set to both "live" or "buffered", I've tried the content type as "application/x-mpegURL", and I've tried the same for the dash URL https://v.redd.it/3hyw7hwoajn21/DASHPlaylist.mpd with content type "application/dash+xml" also to no avail. I found this question that seems to indicate some possibility?
I've also noticed with the DASH file there's a separate video and audio stream (https://v.redd.it/3hyw7hwoajn21/DASH_720 and https://v.redd.it/3hyw7hwoajn21/audio) worst case scenario is there a way to play the video stream with the separate audio stream playing too on the Chromecast?
Is it not possible for the Chromecast to play these video types?
UPDATE
Jesse and aergistal suggested that it has to do with the lack of CORS headers. I built a custom receiver app to be able to get better debugging logs, and this was indeed (the first) issue; Chromecast complains about CORS.
Using nginx on I built a local reverse proxy that adds all the CORS headers, then I give Chromecast that proxy URL instead and this CORS error went away.
However, using the HLS/m3u8 link it still wouldn't stream. Now it complains of the following:
[cast.player.hls.PackedAudioParser] Neither ID3 nor ADTS header was found at 0
and
[cast.player.api.Host] error: cast.player.api.ErrorCode.NETWORK/315
and
[cast.receiver.MediaManager] Load metadata error: Error
Full log:
Which causes it to still not play. Any ideas?
Adding the CORS issue allows the DASHPlaylist.mpd variant to load (it wouldn't before), which is great, but not so great at the same time because the reverse proxy requires you to download the entire response first, and where the DASH URL is just an entire MP4 (whereas the HLS is byte ranges) it means the reverse proxy has to download the entire DASH video first before showing it, which takes ages compared to the HLS.
So it'd still be optimal to get the HLS working due to speed, but is it just doomed not to work due to a playback issue on the Chromecast?
Solution for HLS with separate audio tracks
Based on the information from the latest log there is a mismatch between the chosen segment format and actual format used in the stream. The stream uses
AAC
inMPEG-TS
whereas the Cast SDK tries to parse it as packed audio.A reply on the Cast issue tracker shows that the
HlsSegmentFormat
defaults toMPEG2_TS
if the stream is multiplexed andMPEG_AUDIO_ES
otherwise.The suggested solution for the CAF receiver is to intercept the load requests and override the segment format with
loadRequestData.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.TS
. A slightly modified example:Original source
Yet another example
Solution for CORS
The Google Cast reference gives you the solution:
The problem with the publicly available proxies is that they enforce a size limit due to bandwidth concerns, so make your own or use an open-source one. If the app runs on a mobile device you can also make it a local server.
The current streams are not protected by DRM. This will get more complicated or outright impossible later if they add CDN authentication or protect the streams with DRM.
Regarding the CORS headers you must make sure preflight requests are supported: the client might send an
OPTIONS
first to check CORS support (including allowed methods and headers).HTTP range requests must also be supported for your streams meaning the appropriate headers must be authorized and exposed.
Example preflight request configuration from https://enable-cors.org:
You will need to allow at least:
GET
,OPTIONS
, theContent-Type
andRange
headers, and exposeContent-Length
,Content-Range
. Remove duplicate headers if provided by the remote server.Conclusion
The most ethical answer is to work with Reddit to ensure they set the proper CORS headers. CORS headers are required in the Google documentation.
Simulating your issue
Using this tester:
https://developer.jwplayer.com/tools/stream-tester/
It simulates some of the same experience you were having in your code with the Chromecast SDK. The Google video played without the Playready DRM setting, but the reddit videos did not (in most browsers).
MS EDGE and jwplayer
If you select Playready and put anything for Playready url, even leaving it blank, it works for M3U8.
Internet Explorer and jwplayer
This indicates that perhaps CORS is not enabled on the reddit servers. More on that below.
Firefox and jwplayer
Nothing there seems to work with jwplayer.
Chrome and jwplayer
Doesn't work with jwplayer.
Safari and jwplayer player
You indicated it worked without needing to set any of the DRM settings.
iPhone/Apple TV
I tried it and the m3u8 videos are able to use AirPlay directly to cast from my phone to the Apple TV (4K).
Simulation Summary
All the M3U8 videos can already stream from iPhone to AppleTV just fine with Airplay. It seems to work it Edge, and also in Safari, so maybe it only works because Reddit has accepted Apple streaming via airplay as a service, but not Chromecast. Not quite sure there, but how else could it be explained? More clarification from someone would be great.
Root Cause Analysis
Notice the google link you shared includes this header:
and it is set to * (aka. all), meaning the server will share the requested resources with any domain on the Internet.
https://tools.geekflare.com/report/cors-test/https://commondatastorage.googleapis.com/gtv-videos-bucket/CastVideos/hls/DesigningForGoogleCast.m3u8
The reddit links don’t have that header, meaning CORS is not enabled to allow resource sharing, meaning it is not designed to work.
Description of the CORS headers https://www.codecademy.com/articles/what-is-cors
There are several resources indicating that CORS must be enabled from the server side:
https://stackoverflow.com/a/28360045/9105725
https://help.ooyala.com/video-platform/concepts/cors_enablement.html
Even Google says these headers need to be set: https://developers.google.com/cast/docs/chrome_sender/advanced