6

使用 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

浏览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 自己的示例 HLS 视频),但我似乎无法让这些资源中的任何一个工作。

我试过https://v.redd.it/3hyw7hwoajn21/HLSPlaylist.m3u8将流类型设置为“实时”或“缓冲”,我已经尝试将内容类型设置为“application/x-mpegURL”,并且我对内容类型为“application/dash+xml”的破折号 URL 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] 在 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 上的播放问题,它是否注定无法工作?

4

2 回答 2

7

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


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

Cast 问题跟踪器上的回复显示,如果流是多路复用的,则HlsSegmentFormat默认为。MPEG2_TSMPEG_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


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

于 2019-03-25T18:21:35.187 回答
6

结论

最合乎道德的答案是与 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。更多关于下面的内容。

火狐和 jwplayer

似乎没有任何东西可以与 jwplayer 一起使用。

Chrome 和 jwplayer

不适用于 jwplayer。

Safari 和 jwplayer 播放器

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

iPhone/苹果电视

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

模拟总结

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

根本原因分析

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

Access-Control-Allow-Origin

并且它被设置为 * (aka. 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

甚至谷歌也表示需要设置这些标题: 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。请注意,最后两个标头是您以前可能不需要的附加标头。

于 2019-03-24T01:17:58.107 回答