Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the Chromecast support casting videos from Reddit? (HLS and Dash videos)

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:

enter image description here

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?

like image 835
Doug Smith Avatar asked Mar 18 '19 15:03

Doug Smith


People also ask

Which video format is supported by Chromecast?

The default Chromecast video formats are MP4 and WebM. It also supports MPEG-DASH, Smooth Streaming, and HTTP Live Streaming (HLS) video files. All other video formats are unsupported.

How do I Chromecast All videos?

Mirror your Android phone or tablet screen to the TV See exactly what's on your Android device by casting your screen to the TV. From your Android phone or tablet, open the Google Home app. Tap the left hand navigation to open the menu. Tap Cast screen / audio and select your TV.

Can Chromecast play videos?

You can play movies and shows from another device on your TV with a Chromecast device.

Can Chromecast stream MP4?

It tells you how to stream local files to TV through Chromecast from PC, Mac, Android, or iPhone, iPad and more. Now the Google cast supported video formats are limited to MP4 and WebM. If you have the format incompatibility issue, just use Video Converterto convert your video to be supported by Chrome.


1 Answers

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 in MPEG-TS whereas the Cast SDK tries to parse it as packed audio.

A reply on the Cast issue tracker shows that the HlsSegmentFormat defaults to MPEG2_TS if the stream is multiplexed and MPEG_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:

<html>
<head>
</head>
<body>
  <cast-media-player id="player"></cast-media-player>
  <script type="text/javascript" src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js">
  </script>
  <script>
    const context = cast.framework.CastReceiverContext.getInstance();
    const playerManager = context.getPlayerManager();
    // intercept the LOAD request
    playerManager.setMessageInterceptor(
        cast.framework.messages.MessageType.LOAD, loadRequestData => {
            loadRequestData.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.TS;
            return loadRequestData;
        });
    context.start();
  </script>
</body>
</html>

Original source

Yet another example


Solution for CORS


The Google Cast reference gives you the solution:

If you're having problems playing streams on a Cast device, it may be an issue with CORS. Use a publicly available CORS proxy server to test your streams

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:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,OPTIONS
Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range
Access-Control-Expose-Headers: Content-Length,Content-Range


You will need to allow at least: GET, OPTIONS, the Content-Type and Range headers, and expose Content-Length,Content-Range. Remove duplicate headers if provided by the remote server.

like image 55
aergistal Avatar answered Sep 21 '22 20:09

aergistal