【问题标题】:Does the Chromecast support casting videos from Reddit? (HLS and Dash videos)Chromecast 是否支持从 Reddit 投射视频? (HLS 和 Dash 视频)
【发布时间】:2019-08-09 00:21:07
【问题描述】:

使用 URL http://192.168.xx.xx:8080/3hyw7hwoajn21/HLSPlaylist.m3u8 调用代理 使用 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

浏览the 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
}

虽然我似乎可以让其他 HLS/m3u8 视频与 Chromecast SDK 一起工作(例如 Google's own example HLS video),但我似乎无法让这些来源中的任何一个工作。

我尝试https://v.redd.it/3hyw7hwoajn21/HLSPlaylist.m3u8 将流类型设置为“live”或“buffered”,我尝试将内容类型设置为“application/x-mpegURL”,并且我尝试了相同的带有内容类型“application/dash+xml”的破折号 URL https://v.redd.it/3hyw7hwoajn21/DASHPlaylist.mpd 也无济于事。我发现this question 似乎暗示了某种可能性?

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

Chromecast 不能播放这些视频类型吗?

更新

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

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

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

[cast.player.hls.PackedAudioParser] 在 0 处找不到 ID3 和 ADTS 标头

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

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

完整日志:

这导致它仍然无法播放。有什么想法吗?

添加 CORS 问题允许加载 DASHPlaylist.mpd 变体(以前不会),这很好,但同时不是那么好,因为反向代理要求您首先下载整个响应,以及在哪里DASH URL 只是一个完整的 MP4(而 HLS 是字节范围),这意味着反向代理必须先下载整个 DASH 视频才能显示它,这与 HLS 相比需要很长时间。

因此,由于速度的原因,让 HLS 工作仍然是最佳选择,但由于 Chromecast 上的播放问题,它是否注定无法工作?

【问题讨论】:

  • @Jesse 你到底是什么意思?如上所述,在使用 DASH 流 URL 时,我尝试将“application/dash+xml”作为内容类型,我应该做一些不同的事情吗?
  • 嗯,看来您需要为仪表板构建一个接收器。这对灭霸来说似乎有很多工作,哈哈。
  • @Jesse 我有点想为 Reddit 构建一个视频应用程序,所以它基本上适用于整个 Reddit 视频平台,而不仅仅是这个 Thanos 视频。接收器应用程序是什么意思?这将如何改变事情?我认为即使使用接收器应用程序,您也不能同时拥有两个活动的媒体流,可以吗?
  • 嗯, 实际上就是它所说的,或者这就是屏幕截图的内容?它应该是一个真实的网址。

标签: chromecast google-cast http-live-streaming mpeg-dash google-cast-sdk


【解决方案1】:

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


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

Cast 问题跟踪器上的reply 显示,如果流被多路复用,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>

Original source

Yet another example


CORS 解决方案


Google Cast reference 为您提供解决方案:

如果您在 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


您至少需要允许:GETOPTIONSContent-TypeRange 标头,并公开Content-LengthContent-Range。如果远程服务器提供,则删除重复的标头。

【讨论】:

  • 代理可以工作,但如果你让 Reddit 上的每个人都可以使用它,你会不会用流量杀死某人的服务器和 Reddit 的服务器?似乎您在某个时候可能有 2 倍的机会被列入黑名单。如果 Reddit 有能力支持 Chromecast,他们就不能自己将标头添加到他们的服务器吗?
  • @aergistal 您能否在本地运行 CORS 代理而不需要托管服务器(它确实在移动设备上)?这似乎很棘手,因为这些 m3u8 文件只是链接到一堆不同的文件,所以你也必须代理这些文件。知道怎么做吗?我什至不知道如何在移动设备上启动代理
  • @Jesse 代理成为“客户端”,CDN 看到相同数量的流量。他们不喜欢它还有其他原因,这可能包含在法律协议中。
  • 哇,你得到了一切
  • 我很高兴它有效。事实证明@Jesse 是对的,官方修复确实 hacky。希望他们能在未来的 CAF 版本中改进 HLS 支持。
【解决方案2】:

结论

最合乎道德的答案是与 Reddit 合作,确保他们设置正确的 CORS 标头。 Google 文档中需要 CORS 标头。

模拟您的问题

使用此测试仪:

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

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

MS EDGE 和 jwplayer

如果您选择 Playready 并为 Playready url 输入任何内容,即使将其留空,它也适用于 M3U8。

Internet Explorer 和 jwplayer

错误,232011 在没有正确的跨域凭据的情况下发出了清单请求。无法加载 M3U8:跨域访问被拒绝。由于技术错误,无法播放此视频。

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

Firefox 和 jwplayer

jwplayer 似乎没有任何用处。

Chrome 和 jwplayer

不适用于 jwplayer。

Safari 和 jwplayer 播放器

您表示它无需设置任何 DRM 设置即可工作。

iPhone/Apple TV

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

模拟总结

所有 M3U8 视频都可以通过 Airplay 从 iPhone 流式传输到 AppleTV。它似乎可以在 Edge 和 Safari 中使用,所以它可能只是因为 Reddit 接受了 Apple 通过 airplay 流式传输的服务,而不是 Chromecast。不太确定那里,但还能如何解释呢?如果有人能提供更多的澄清,那就太好了。

根本原因分析

请注意,您共享的 google 链接包含此标头:

Access-Control-Allow-Origin

它被设置为 *(又名 all),这意味着服务器将与 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:

https://stackoverflow.com/a/28360045/9105725

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。请注意,最后两个标头是您以前可能不需要的附加标头。

【讨论】:

  • 我很困惑,如果我将上面的 m3u8 放入该站点,则使用该站点,将 DRM 设置为 None 并点击 Test,它加载正常。
  • 奇怪。没有它,它第一次对我不起作用。也许当我在那个网站上尝试它时,它已经以某种方式注册了许可证。
  • 来,试试这个。我还没有“修复”它...v.redd.it/g99ef3uv4yk21/HLSPlaylist.m3u8 试试那个而不在 jwplayer 中设置 DRM。也试试其他人。
  • 更新了原始问题,不幸的是不是(只是)CORS 标头
  • 我看不出这有什么关系?它只是从 Reddit 获取 https,而不是通过 http 呈现它。如果您担心屏幕截图中的警告,这只是一个警告,因为当您将应用转换为“已发布”时,如果它来自 https 源 URL,则无法链接到非 https 的东西。但我看不出这会如何影响发展。
猜你喜欢
  • 2014-09-22
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 2015-03-16
  • 2017-08-29
  • 2014-04-30
  • 2014-03-27
相关资源
最近更新 更多