使用 Amazon CloudFront 为移动设备“流式传输”视频
Posted
技术标签:
【中文标题】使用 Amazon CloudFront 为移动设备“流式传输”视频【英文标题】:Video "streaming" for mobile devices with Amazon CloudFront 【发布时间】:2011-11-12 04:53:16 【问题描述】:我为客户维护了一个视频应用程序,我们刚刚完成了通过他们提供的流分发将桌面站点移植到 Amazon S3 + CloudFront 的过程。需要明确的是,我不是在谈论实时流媒体(我的大部分 Google 都采用),我不是在谈论 Flash 流媒体。
我们有一个当前使用 Influxis 的移动网站。它不是很贵,但我们希望在亚马逊上进行整合,因为它们应该比过去几个月的 Influxis 更稳定。
我承认,虽然我对 Flash 流媒体有相当多的了解,但我并不是 100% 了解 html 视频。它只是直接下载还是可以做可变比特率?理想情况下,我们希望它能够针对 3G 连接不佳的人进行缩减。
即使“可能”,亚马逊是否支持通过其下载分发来扩展带宽?据我了解,它的流式分发只适用于 Flash/RTMP。
如果有人对良好的移动流媒体有任何建议,我也会欢迎他们。
【问题讨论】:
【参考方案1】:打包视频(即“HLS”) - 对于 ios 设备,通过 HTTP 传送。没有简单的方法可以使用 Cloudfront 有效地提供此功能。
Wowza Media Server 支持使用 SMIL 播放列表的动态 HLS 流。我们在工作流程中使用 WMS - 如果您想进行一些测试,请随时与我联系!
我们有一些额外的功能 - 例如当用户带宽不足以支持流的视频版本时,将图像添加到仅音频流中。
您的问题确实涉及 iOS 设备 - 尽管您提到了移动设备 - 需要 RTSP 连接才能交付给 Blackberries(尽管一些最新的套件支持闪存 - 就像剧本一样)。
同样适用于 android
不幸的是 - RTSP 不支持那种流畅的交付 - 这是一个速率 - 就是这样 :)
【讨论】:
我们也有类似的问题.. 我们所有的视频都存储在 s3 上.. 目前我们正在通过云端进行 RTMP 流式传输.. 现在的问题是 android 没有 Flash,因此我们必须使用HTTP进度下载流媒体..那么我们必须提供哪些选项来提供“自适应比特率流媒体”所有设备桌面/平板电脑/移动设备(Win/Ios/Android)请建议 有什么方法可以在 Android 中集成 cloudfront? 这在十年后并不准确,因此被否决【参考方案2】:非常老的问题,但我在类似的帖子上发布了我对类似问题的解决方案,所以我也在这里分享它Stream AWS S3 HLS Videos in iOS Browsers
---------------以下更新--------------- (找个舒服的座位)
使用安全 cookie(适用于基于 iOS 的浏览器 + 所有 Safari)和适用于 Chrome 和其他所有内容的安全 URL,通过 Cloudfront 从 S3 传送受保护的视频。
网站架构:
前端:ReactJS 后端:NodeJS 云服务架构:https://aws.amazon.com/blogs/media/creating-a-secure-video-on-demand-vod-platform-using-aws/(以及随附的实验室指南)假设:与上述云架构等效的设置,特别是 CF 到 S3 存储桶的 IAM 配置,以及 IAM 和 CORS 的相关 S3 安全配置。
TL/DR:
NON-SAFARI aka Chrome 等 - 使用安全网址(非常简单的 OOTB);上述指南适用于 chrome,但不适用于 safari。
Safari 需要安全的 cookie 来本地流式传输 hls,并且根本不会识别 xhr.beforeRequest 重载。 基于 SAFARI 的 SAFARI / iOS 浏览器 - 使用安全 cookie 下面的所有内容都解释了这一点。
设置 cookie,听起来很简单!这可能是为什么在 AWS CloudFront、AWS 论坛或 AWSDeveloper Slack 频道中没有端到端示例的原因,它被认为很简单,因为,嘿,它只是 cookie,对吧?
没错。 结束 TL/DR
解决方案详情
“啊哈!”那一刻终于明白,要使其正常工作,您需要能够从您自己的服务器为云端服务器设置 cookie,这基本上是一个巨大的网络安全禁忌。 aka - “域需要相同,一直向下/向上网络调用”
cmets在这里https://jwplayer-support-archive.netlify.app/questions/16356614-signed-cookies-on-cloudfront-with-hls-and-dash
这里链接https://www.spacevatican.org/2015/5/1/using-cloudfront-signed-cookies/
两者都与原始 AWS 文档相结合,该文档是关于带有域 cname 的签名 cookie 以应用于子域,最终都为我结合了。
解决办法是:
-
为您的云端实例设置 CNAME;即:您不能针对 5j1h24j1j.cloudfront.net 设置 cookie,因为您不拥有它,但您可以在 DNS 中对 cloudfront.
上面所做的是确保 END TO END,您能够发送 cookie,从 dev.
但是等等,客户端还有更多工作要做。 一开始甚至阻止我看到饼干的一件事是它们没有被设置 除非请求者/发起者在启动它的网络调用中使用“withCredentials: true”标志。在我的代码中,这是一个基于 ReactJS componentDidMount() 的 Axios 网络 REST GET 调用,用于调用我的后端 nodeJS 端点以获取视频列表(nodeJS 从 AWS 中的 graphQL 获取,但我的修复解释不需要这些)。
componentDidMount()
axios.get('http://dev.<your-domain>.com:3000/api/my-data-endpoint'
,
withCredentials: true,
)
.then(vidData =>
this.setState(
....//set stuff for player component include to use
);
)
当我的 axios 调用没有“withCredentials: true”时,cookie 永远不会被发回;我一有那个?我的 cookie 至少被发送回第一个调用者 localhost(cookie 中没有域参数,它默认调用,我当时作为本地主机),因此这意味着它永远不会将它传递给 CF,它是当时的 2435h23l4jjfsj.cloudfront.net 名称。
因此,更新 axios 以使用 dev.
在上述对我的 api 的调用中,我得到了类似的东西
src:’https://cloudfront.<your-domain>.com/path-to-secure-register-m3u8-file’, qps:’?policy=x&signature=y&key-pair-id=z’, blah blah
[边栏 - 签名的 url 均由 lambda 在云端生成] 对于 Chrome,播放器代码会将两者附加在一起,然后无论您在哪里实例化 video.js 播放器,重载 videojs.Hls.xhr.beforeRequest 如下
videojs.Hls.xhr.beforeRequest = function (options)
options.uri = `$options.uri$videojs.getAllPlayers()[0].options().token`;
return options;
;
在注册 m3u8 文件启动后,将 ?policy=x&signature=y&Key-Pair-ID=z 的查询字符串放在流中每个子文件的末尾。
上面描述的对api的后端调用,也在json作为响应发送之前拆开QP设置cookie,如下
res.cookie("CloudFront-Key-Pair-Id", keypair, httpOnly: true, path: "/", domain: ‘<your-domain>.com');
res.cookie("CloudFront-Signature", sig, httpOnly: true, path: "/", domain: ‘<your-domain>.com');
res.cookie("CloudFront-Policy", poli, httpOnly: true, path: "/", domain: ‘<your-domain>.com');
中断 - 现在我们已将 withCredentials 设置为 true,您可能会看到 CORS 问题;乐趣。 在您的服务器端代码(我的 reactJS)中,我在我的 nodejs 路由器中设置了一些标头
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Origin", "http://dev.<your-domain>.com:8080"); // will be set to just <your-domain>.com for production
在这一点上,东西仍然没有工作。这是因为云代码将 CF 234hgjghg.cloudfront.net 域放入策略中,而不是我的 CNAME 映射。我在云端更新了这个。所以现在我对视频数据的调用,使用 cloudfront.
此时,如果我使用 safari 调试工具,我知道我已经接近了,因为我对尝试流式传输的响应从无密钥或 cookie xml 更改为
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
错误,其中包含对我的 S3 存储桶的引用。这对我来说意味着,我的 CF 分发基本上对基于 cookie 的策略、密钥 ID 和签名感到满意,并且已将我传递给 S3,但 S3 让我迷路。
此时的好处是,3 个必需的云端 cookie 是从 dev.
好的,所以我在 s3 配置中花了一些时间(没有编辑任何内容,只是查看所有内容……这对我来说看起来 100% 没问题),然后返回 CF 分发行为编辑页面,在那里您将标题设置为向前。 设置(下面列出,然后是我的截图):
缓存和原始请求设置:使用旧缓存设置 缓存基于选定的请求标头 - 白名单 添加来源、访问控制请求标头、访问控制请求方法。您需要明确输入最后 2 个,它们没有为我自动完成,也没有显示在建议列表中,但添加自定义按钮有效。 对象缓存:使用原始缓存标头 转发 cookie/查询字符串 - 两者都没有(改进缓存) 限制查看者访问(使用签名的 url 或 cookie)- 是的(这就是这个令人头疼的问题,哈哈) 受信任的签名者,自己分发保存和传播后,Safari 和 Chrome 视频播放都可以正常工作!
这是一个相当大的漏洞,而且比我预期的要困难一个学位(或 15 个),但当然,一旦全部写出来,这一切似乎都如此合乎逻辑和显而易见。我希望这至少部分地帮助我在互联网上找到的其他人,使用 S3 前面的 AWS Cloudfront 在所有主要浏览器上安全地流式传输私有内容
【讨论】:
【参考方案3】:使用 AWS MediaConvert 将您的 mp4 转换为 HLS 流 - 播放列表 (.m3u8) 以及加密的 .ts 文件。如果您需要更高的安全性,请将其加密。
然后你需要一个像 VideoJS 这样的播放器,它可以播放渐进式下载视频和音频,以及流式视频和音频。 VideoJS 还可以读取解密文件的 URL,并在下载、解密和播放加密的 .ts 片段时实时使用它。
还可以查看Amazon S3 Video Player 的 WordPress,它可以让您在没有任何编码的情况下完成上述所有操作。
【讨论】:
以上是关于使用 Amazon CloudFront 为移动设备“流式传输”视频的主要内容,如果未能解决你的问题,请参考以下文章