Chromecast是否支持从Reddit投射视频?(HLS和Dash视频)

Dou*_*ith 5 http-live-streaming google-cast chromecast mpeg-dash google-cast-sdk

与URL称为代理//192.168.xx.xx:8080 / 3hyw7hwoajn21 / HLSPlaylist.m3u8 HTTP 调用代理与URL 的http://192.168.xx.xx:8080 / 3hyw7hwoajn21 / HLS_540_v4.m3u8 调用与URL代理HTTP:// 192.168.xx.xx:8080 / 3hyw7hwoajn21 / HLS_AUDIO_160_K_v4.m3u8 称为URL的代理http://192.168.xx.xx:8080 / 3hyw7hwoajn21 / HLS_224_v4.m3u8

这是Reddit视频的示例:https : //www.reddit.com/r/me_irl/comments/b3vrs4/me_irl

查看JSON,它有一些视频源选项:

"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
}
Run Code Online (Sandbox Code Playgroud)

虽然我似乎可以使其他HLS / m3u8视频与Chromecast SDK配合使用(例如Google自己的示例HLS视频),但似乎无法使所有这些资源都可以使用。

我尝试将流类型设置为“实时”或“缓冲”的https://v.redd.it/3hyw7hwoajn21/HLSPlaylist.m3u8,我尝试将内容类型设置为“ application / x-mpegURL”,并且我对内容URL 为“ application / dash + xml” 的破折号网址https://v.redd.it/3hyw7hwoajn21/DASHPlaylist.mpd尝试了相同的操作,但也无济于事。我发现这个问题似乎暗示了某种可能性?

我还注意到DASH文件中存在单独的视频和音频流(https://v.redd.it/3hyw7hwoajn21/DASH_720https://v.redd.it/3hyw7hwoajn21/audio)最坏的情况是一种在Chromecast上同时播放音频流和单独音频流的方法?

Chromecast无法播放这些视频类型吗?

更新

Jesse和aergistal建议这与缺少CORS标头有关。我构建了一个自定义的接收器应用程序,以便能够获得更好的调试日志,这确实是(第一个)问题。Chromecast抱怨CORS。

使用nginx时,我构建了一个本地反向代理,该代理添加了所有CORS标头,然后为Chromecast提供了该代理URL,而这个CORS错误就消失了。

但是,使用HLS / m3u8链接仍不会流式传输。现在,它抱怨以下内容:

[cast.player.hls.PackedAudioParser]找不到ID3或ADTS标头为0

[cast.player.api.Host]错误:cast.player.api.ErrorCode.NETWORK/315

[cast.receiver.MediaManager]加载元数据错误:错误

完整日志:

在此处输入图片说明

这导致它仍然无法播放。有任何想法吗?

添加CORS问题可以加载DASHPlaylist.mpd变体(以前不会),这很好,但同时又不那么好,因为反向代理要求您首先下载整个响应,以及DASH URL的位置只是整个MP4(而HLS是字节范围),这意味着反向代理必须先下载整个DASH视频,然后再显示它,这与HLS相比要花一些时间。

因此,由于速度的原因,使HLS正常运行仍然是最佳选择,但是由于Chromecast的播放问题而注定它不能正常工作吗?

小智 6

结论

最符合道德的答案是与Reddit一起使用,以确保它们设置正确的CORS标头。Google文档中需要CORS标头。

模拟您的问题

使用此测试仪:

https://developer.jwplayer.com/tools/stream-tester/

它模拟了您在使用Chromecast SDK的代码中获得的一些相同体验。Google视频在没有Playready DRM设置的情况下播放,但reddit视频没有播放(在大多数浏览器中)。

MS EDGE和jwplayer

如果您选择Playready并为Playready网址添加任何内容,即使将其保留为空白,则适用于M3U8。

Internet Explorer和jwplayer

错误,2011年,一个清单请求没有适当的跨域凭据。无法加载M3U8:跨域访问被拒绝。由于技术错误,该视频无法播放。

这表明在reddit服务器上可能未启用CORS。下面的更多内容。

Firefox和jwplayer

jwplayer似乎没有任何工作。

Chrome和jwplayer

不适用于jwplayer。

Safari和jwplayer播放器

您指出它可以工作,而无需设置任何DRM设置。

iPhone /苹果电视

我尝试过,m3u8视频可以直接使用AirPlay从手机投射到Apple TV(4K)。

仿真总结

使用Airplay可以很好地将所有M3U8视频从iPhone流传输到AppleTV。它在Edge以及Safari中似乎都可以使用,所以也许只能使用,因为Reddit接受了通过airplay作为服务而不是Chromecast的Apple流媒体服务。那里不是很确定,但是还有什么可以解释的呢?有人提供更多的说明会很棒。

根本原因分析

请注意,您共享的Google链接包含以下标头:

Access-Control-Allow-Origin
Run Code Online (Sandbox Code Playgroud)

并将其设置为*(也称为全部),这意味着服务器将与Internet上的任何域共享请求的资源。

https://tools.geekflare.com/report/cors-test/https://commondatastorage.googleapis.com/gtv-videos-bucket/CastVideos/hls/DesigningForGoogleCast.m3u8

reddit链接没有该标头,这意味着未启用CORS来允许资源共享,这意味着它不能正常工作。

CORS标头的说明 https://www.codecademy.com/articles/what-is-cors

Access-Control-Allow-Origin标头允许服务器指定如何与外部域共享其资源。当发出GET请求以访问服务器A上的资源时,服务器A将使用Access-Control-Allow-Origin标头的值进行响应。很多时候,该值为*,表示服务器A将与Internet上的任何域共享请求的资源。在其他时间,此标头的值可以设置为特定域(或域列表),这意味着服务器A将与该特定域(或域列表)共享其资源。Access-Control-Allow-Origin标头对于资源安全至关重要。

有几种资源指示必须从服务器端启用CORS:

/sf/answers/1985203181/

https://help.ooyala.com/video-platform/concepts/cors_enablement.html

甚至Google都说需要设置以下标头:https : //developers.google.com/cast/docs/chrome_sender/advanced

CORS要求对于自适应媒体流,Google Cast需要存在CORS标头,但即使简单的mp4媒体流包含Track,也需要CORS。如果要为任何媒体启用轨道,则必须为轨道流和媒体流都启用CORS。因此,如果您的服务器上没有适用于您的简单mp4媒体的CORS标头,然后添加了简单的字幕轨道,则除非您更新服务器以包含适当的CORS标头,否则将无法流式传输媒体。此外,您至少需要允许以下标头:Content-Type,Accept-Encoding和Range。请注意,最后两个标头是您以前可能不需要的其他标头。


aer*_*tal 6

具有独立音轨的 HLS 解决方案


根据最新日志中的信息,所选的段格式与流中使用的实际格式不匹配。流使用AACinMPEG-TS而 Cast SDK 尝试将其解析为打包音频。

一个答复的演员问题跟踪显示,HlsSegmentFormat默认为MPEG2_TS如果流复用和MPEG_AUDIO_ES其他。

CAF 接收器的建议解决方案是拦截加载请求并使用loadRequestData.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.TS. 一个稍微修改的例子:

<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>
Run Code Online (Sandbox Code Playgroud)

原始来源

又一个例子


CORS 解决方案


谷歌演员参考为您提供了解决方案:

如果您在 Cast 设备上播放流时遇到问题,则可能是 CORS 的问题。使用公开可用的CORS 代理服务器来测试您的流

公开可用的代理的问题在于,由于带宽问题,它们强制执行大小限制,因此请自行制作或使用开源代理。如果该应用程序在移动设备上运行,您还可以将其设为本地服务器。

当前流不受 DRM 保护。如果他们添加 CDN 身份验证或使用 DRM 保护流,这将变得更加复杂或完全不可能。


关于 CORS 标头,您必须确保支持预检请求:客户端可能会OPTIONS首先发送检查 CORS 支持(包括允许的方法和标头)。

您的流还必须支持 HTTP 范围请求,这意味着必须授权和公开相应的标头。

来自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
Run Code Online (Sandbox Code Playgroud)


您将需要至少允许:GET, OPTIONS, theContent-TypeRangeheaders,并暴露Content-Length, Content-Range。如果远程服务器提供,则删除重复的标头。

  • 哇你得到了一切 (2认同)