称为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,将内容类型设置为“ application / x-mpegURL”,并且尝试了相同的方法内容类型为“ application / dash + xml”的破折号URL https://v.redd.it/3hyw7hwoajn21/DASHPlaylist.mpd也无效。我发现this question似乎暗示着某种可能性?
我还注意到DASH文件中存在单独的视频和音频流(https://v.redd.it/3hyw7hwoajn21/DASH_720和https://v.redd.it/3hyw7hwoajn21/audio),最坏的情况是有一种方法可以在单独播放音频流的情况下播放视频流在Chromecast上也一样?
Chromecast是否可以播放这些视频类型?
Jesse和aergistal认为这与缺少CORS标头有关。我构建了一个自定义的接收器应用程序,以便能够获得更好的调试日志,这确实是(第一个)问题。 Chromecast抱怨CORS。
在使用nginx时,我构建了一个本地反向代理,该代理添加了所有CORS标头,然后我为Chromecast提供了该代理URL,而这个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上的播放问题,注定它不能正常工作吗?
答案 0 :(得分:6)
结论
最符合道德的答案是与Reddit一起使用,以确保它们设置正确的CORS标头。 Google文档中需要CORS标头。
模拟您的问题
使用此测试器:
https://developer.jwplayer.com/tools/stream-tester/
它模拟了您在使用Chromecast SDK的代码中获得的一些相同体验。在没有Playready DRM设置的情况下播放了Google视频,但在大多数浏览器中,reddit视频没有播放。
MS EDGE和jwplayer
如果您选择Playready并为Playready网址添加任何内容,即使将其保留为空白,则适用于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)。
模拟摘要
使用Airplay可以很好地将所有M3U8视频从iPhone传输到AppleTV。它在Edge以及Safari中似乎都可以使用,所以也许只能使用,因为Reddit接受了通过airplay作为服务而不是Chromecast的Apple流媒体服务。那里不是很确定,但是还有什么可以解释的呢?有人再澄清一下会很好。
根本原因分析
请注意,您共享的Google链接包含以下标头:
Access-Control-Allow-Origin
,并且它设置为*(也称为全部),这意味着服务器将与Internet上的任何域共享请求的资源。
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媒体流包含轨道,也需要CORS。如果要为任何媒体启用轨道,则必须为轨道流和媒体流都启用CORS。因此,如果您的服务器上没有适用于您的简单mp4媒体的CORS标头,然后添加了简单的字幕轨道,则除非您更新服务器以包括适当的CORS标头,否则将无法流式传输媒体。此外,您至少需要允许以下标头:Content-Type,Accept-Encoding和Range。请注意,最后两个标头是您以前可能不需要的其他标头。
答案 1 :(得分:4)
具有单独音轨的HLS解决方案
根据最新日志中的信息,所选的段格式和流中使用的实际格式之间不匹配。流在AAC
中使用MPEG-TS
,而Cast SDK尝试将其解析为打包的音频。
“投放”问题跟踪器上的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>
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
您将需要至少允许:GET
,OPTIONS
,Content-Type
和Range
标头,并公开Content-Length
,Content-Range
。如果远程服务器提供了重复的标头,则将其删除。