Chromecast支持从Reddit投放视频吗?(HLS和Dash视频)

6

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

我似乎可以使用Chromecast SDK播放其他HLS/m3u8视频(例如 谷歌自己的示例HLS视频),但我无法让这些源中的任何一个起作用。
我尝试过将流类型设置为“live”或“buffered”,并尝试了内容类型为“application/x-mpegURL”的https://v.redd.it/3hyw7hwoajn21/HLSPlaylist.m3u8,也尝试了同样的dash URL https://v.redd.it/3hyw7hwoajn21/DASHPlaylist.mpd 以及“application/dash+xml”内容类型,但没有成功。我发现这个问题似乎表明有一些可能性?
我还注意到,在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上播放?


也许DASH值得一试。https://developers.google.com/cast/docs/mpl/streaming_protocols。 - user9105725
@Jesse 您的意思是什么?我已经尝试使用“application/dash+xml”作为内容类型,当使用上面提到的DASH流URL时,我是否应该进行不同的操作? - Doug Smith
看起来你需要为破折号构建一个接收器。这对于灭霸来说似乎是很多工作,哈哈。 - user9105725
@Jesse,我有点想为Reddit构建一个视频应用程序,因此它基本上是针对整个Reddit视频平台而不仅仅是这个Thanos视频。你所说的接收器应用程序是什么意思?那会改变什么?即使使用接收器应用程序,您也不能同时进行两个活动媒体流,对吗? - Doug Smith
嗯,<URL>实际上就是它所说的,或者这是为了截图而更改的?它应该是一个真实的网址。 - user9105725
2个回答

7

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


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

Cast问题跟踪器上的回复显示,如果流是复用的,则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>

原始来源

另一个例子


CORS的解决方案


Google Cast参考文档提供了解决方案:

如果您在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。如果远程服务器提供了重复的标头,请删除它们。

@Jesse代理成为“客户端”,CDN看到的流量数量相同。还有其他原因,他们可能不喜欢它,并且在法律协议中可能已经涵盖。 - aergistal
它需要一个来源头,我相信这是CORS的事情。然而,我仍然坚持我的原始道德答案。可能,但不推荐。https://corsproxy.github.io/ - user9105725
@Jesse Origin 是一个请求头,在这种情况下它并不重要,因为代理服务器返回的是 Access-Control-Allow-Origin 头信息,而且它总是会回应任何 (*)。 - aergistal
2
哇,你全都搞定了。 - Doug Smith
1
很高兴它能够正常工作。事实证明@Jesse是正确的,官方修复确实有些hacky。希望他们在未来的CAF版本中能够改进HLS支持。 - aergistal
显示剩余15条评论

6

结论

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

模拟你的问题

使用此测试工具:

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

它模拟了您在代码中使用Chromecast SDK时遇到的一些相同体验。谷歌视频不带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 player

您指出它可以在不需要设置任何DRM设置的情况下正常工作。

iPhone / Apple TV

我尝试了一下,m3u8视频能够直接使用AirPlay从我的手机投放到Apple TV(4K)。

模拟总结

所有的M3U8视频已经可以通过Airplay从iPhone流式传输到AppleTV。它似乎在Edge和Safari中起作用,所以也许只有因为Reddit已经接受了将Airplay用于苹果流媒体服务,而没有接受Chromecast。不太确定那里,但还有人需要更多的解释。

根本原因分析

请注意,您分享的谷歌链接包括此标头:

Access-Control-Allow-Origin

这里的header被设置为*(也就是全部),表示服务器将共享所请求的资源与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标头允许服务器指定如何与外部域共享其资源。当向Server A发出GET请求以访问资源时,Server A将用Access-Control-Allow-Origin标头的值进行响应。在很多情况下,该值将为*,这意味着Server A将与Internet上的任何域共享所请求的资源。在其他情况下,此标头的值可能设置为特定域(或域列表),这意味着Server A将与该特定域(或域列表)共享其资源。Access-Control-Allow-Origin标头对于资源安全非常重要。

有几个资源表明必须从服务器端启用CORS:

https://dev59.com/714c5IYBdhLWcg3wEGp_#28360045

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。如果要为任何媒体启用Tracks,则必须在您的track流和媒体流上启用CORS。因此,如果您的服务器上没有CORS标头用于简单的mp4媒体,并且随后添加简单的字幕轨道,则除非您更新服务器以包含相应的CORS标头,否则您将无法流式传输媒体。此外,您需要允许至少以下标题:Content-Type,Accept-Encoding和Range。请注意,最后两个标题是您之前可能不需要的其他标题。


C#和Java是我最熟悉的编程语言。但是,它们大多数都有相同的感觉。等我有时间了再去看看吧。顺便说一句,我在测试jwplayer时使用了MS Edge浏览器。所以,可能是微软的问题。 - user9105725
我在 Mac 上没有 Edge,但在 Safari 中可以正常加载,但在 Firefox 中完全无法加载。非常有趣。然而它不会让我选择 Playready,因为它被灰显。 - Doug Smith
Dash_720确实是一个mp4,只是没有音频元素。 - Doug Smith
1
更新了原始问题,不幸的是,这不仅仅涉及CORS头信息。 - Doug Smith
1
我不明白那跟什么有关系?这只是从Reddit获取https,然后通过http呈现它。如果您担心屏幕截图中的警告,那只是一个警告,因为当您将应用程序转换为“发布”时,如果它来自https源URL,则无法链接到非https内容。但我不明白那会如何影响开发。 - Doug Smith
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接