mon*_*ffy 6 amazon-web-services http-live-streaming ios video.js
如何在 iOS Safari 浏览器中流式传输 HLS(.m3u8)?我的视频存储在 AWS S3 Bucket 中,访问视频和音频的唯一方法.m3u8
是传递签名 URL。
我正在使用videojs
流式传输视频。 videojs.Hls.xhr.beforeRequest
不适用于 iOS 浏览器。我还读到 iOS 不支持 MSE,是否有任何替代方法可以用来传递签名 URL 以便能够在 iOS 浏览器上流式传输我的视频?
这是我的示例代码和错误截图:
videojs.Hls.xhr.beforeRequest = function(options) {
if (options.uri.includes('Audio')) {
options.uri = options.uri + '?Policy=' + policy + '&Key-Pair-Id=' + keyPairId + '&Signature=' + signature;
}
else if (options.uri.includes('Video')) {
options.uri = options.uri + '?Policy=' + policy + '&Key-Pair-Id=' + keyPairId + '&Signature=' + signature;
}
return options
}
var overrideNative = false;
var player = videojs('video-test', {
"controls": true,
"fluid": true,
"preload": 'none',
"techOrder": ["html5"],
"html5": {
"hls": {
"withCredentials": true,
overrideNative: overrideNative,
},
},
nativeVideoTracks: !overrideNative,
nativeAudioTracks: !overrideNative,
nativeTextTracks: !overrideNative
});
player.src(
{
src: url, type: "application/x-mpegURL", withCredentials: true
});
Run Code Online (Sandbox Code Playgroud)
完全相同的问题,除了在 ReactJS 中实现之外,videojs vhs 覆盖不起作用,因为它与 Safari 和解析(或不解析)选项以查看通过寄存器 m3u8 的后续调用的安全参数有关。
还有其他一些人处理这个问题,例如 https://github.com/awslabs/unicornflix/issues/15
我已经尝试了所有方法,从 amazon IVS+VideoJS 尝试,到将我的类模块重写为函数式以尝试我找到的示例;并且基本上总是在这个问题上结束
---------------在下面更新-------------- (并抓住一个舒适的座位)
使用安全 cookie(适用于基于 iOS 的浏览器 + 所有 Safari)和 Chrome 和其他所有内容的安全 URL,通过 Cloudfront 从 S3 提供受保护的视频。
网站架构:
假设:与上述云架构等价的设置,特别是CF到S3存储桶的IAM配置,以及IAM和CORS的相关S3安全配置。
TL/DR :
NON-SAFARI aka Chrome 等 - 使用安全网址(非常简单的 OOTB);上述指南适用于 chrome,但不适用于 safari。
Safari 需要安全 cookie 来本地流式传输 hls,并且根本不会识别 xhr.beforeRequest 重载。基于 SAFARI 的 SAFARI / iOS 浏览器 - 使用安全 cookie 下面的所有内容都解释了这一点。
设置饼干,听起来很容易!这可能是为什么在 AWS CloudFront、AWS 论坛或 AWSDeveloper Slack 频道中的任何地方都没有端到端的示例,这可能很容易,因为,嘿,它只是 cookie,对吗?
对。 结束 TL/DR
解决方案详情
“啊哈!” 时刻终于明白,要使其工作,您需要能够从您自己的服务器为 cloudfront 服务器设置 cookie,这基本上是一个巨大的网络安全禁忌。又名 - '域需要相同,一直向下/向上网络呼叫'
在这里链接https://www.spacevatican.org/2015/5/1/using-cloudfront-signed-cookies/
两者都结合了原始 AWS 文档,关于签名 cookie 和域的 cname 以应用于子域,最后所有这些都对我来说是结合在一起的。
解决办法是:
上面所做的是确保端到端,您能够发送 cookie,从 dev.<your-domain>.com 或您未来的产品开始的呼叫中分配给 .<your-domain>.com <your-domain>.com 到相同的 uri,但在后端的不同端口上,然后通过 CNAME 到 CF,这是 cookie 现在可以看到的子域。此时,由 CF 将所需的标头传递给 S3 实例。
但是等等,还有更多的事情要做客户端。一开始甚至阻止我看到 cookie 的事情是,除非请求者/发起者在启动它的网络调用中使用“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
});
})
}
Run Code Online (Sandbox Code Playgroud)
当我的 axios 调用没有 'withCredentials: true' 时,cookie 永远不会被发回;我一有那个?我的 cookie 至少被发送回第一个调用者 localhost(cookie 中没有域参数,它默认调用,我当时作为本地主机),因此这意味着它永远不会将它传递给 CF,当时是 2435h23l4jjfsj.cloudfront.net 名称。
因此,更新 axios 以使用 dev.<your-domain>.com 进行服务器访问,并在调用有关视频的后端信息时设置了 withCredentials 标志和我的 cookie。正如 AWS 文档所指出的那样,需要在调用安全内容之前完全设置 cookie,因此已完成。
在上述对我的 api 的调用中,我得到了类似的信息
{src:’https://cloudfront.<your-domain>.com/path-to-secure-register-m3u8-file’, qps:’?policy=x&signature=y&key-pair-id=z’, blah blah}
Run Code Online (Sandbox Code Playgroud)
[侧边栏 - 签名的 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;
};
Run Code Online (Sandbox Code Playgroud)
在寄存器 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'});
Run Code Online (Sandbox Code Playgroud)
中断- 现在我们已将 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
Run Code Online (Sandbox Code Playgroud)
在这一点上,东西仍然无法正常工作。这是因为云代码将 CF 234hgjghg.cloudfront.net 域放入策略中,而不是我的 CNAME 映射。我在云端更新了这个。所以现在我对视频数据的调用,使用 cloudfront.<your-domain>.com 而不是这里描述的 cloudfront.net https://forums.aws.amazon.com/thread.jspa将 URL 返回到安全的 m3u8 ? messageID=610961劑在最后的响应步骤 3 中。
此时,如果我使用 safari 调试工具,我知道我已经接近了,因为我对尝试流式传输的响应从 no key 或 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>
Run Code Online (Sandbox Code Playgroud)
错误,在其中,是对我的 S3 存储桶的引用。这对我来说意味着,我的 CF 发行版基本上对基于 cookie 的策略、密钥 ID 和签名感到满意,并将我传递给 S3,但 S3 告诉我迷路了。
不过此时的好处是,从 dev.<your-domain>.com 一直到 cloudfront.<your-domain>.com 调用了 m3u8 注册文件,并且设置了 3 个所需的 Cloudfront cookie,并且然后在对 .ts 或 .m3u8 的所有后续调用中
好的,所以我在 s3 配置中花了一些时间(没有编辑任何内容,只是查看所有内容……对我来说看起来 100% 很好),然后返回到 CF 分发行为编辑页面,在那里设置要转发的标题。设置(下面列出,然后是我的屏幕截图):
分发保存和传播后,Safari 和 Chrome 视频播放都有效!
这是一个相当大的漏洞,比我预期的要困难一个学位(或 15 个),但是当然,一旦全部写出来,这一切似乎都是合乎逻辑和显而易见的。我希望这至少可以部分帮助我在互联网上找到的其他人使用 S3 前的 AWS Cloudfront 跨所有主要浏览器安全流式传输私有内容
归档时间: |
|
查看次数: |
1975 次 |
最近记录: |