媒体的 Google Cloud Storage 签名网址

2024-05-20

我已经建立了一个视频网站,为用户提供 m3u8 和关联的 ts 文件。我不希望媒体文件免费可用,所以我所做的是:当用户在网站上时,在 mysql 中使用他们的 IP 和令牌创建一个会话;当他们请求特定媒体子域 (mp4.domain.com) 中的任何文件时,Nginx 身份验证模块会使用 url 和附加令牌作为通过 javascript 设置的请求 cookie 查询 localhost:8080...查询数据库并允许/拒绝对文件的访问取决于会话信息。

现在效果很好,根据服务器负载,开销在 8 - 20 MS 之间,并且在生成 m3u8 链接时无需在 PHP 中修改 url; OSMF 只是获取 m3u8 并请求文件,javascript 添加令牌 cookie,而 Bob 是你的叔叔。

现在我们正在迁移到 Google Cloud Storage,我面临的问题是我无法真正控制其中任何一个...m3u8 的签名 url 很容易,但每个 m3u8 都必须是为每个分辨率、缩略图和音频 aac 的每个 ts 文件动态生成签名 url(为了给您一个想法,我选择的随机视频总共有 1,043 个文件)...需要生成 1,043 个不同的签名 url,每个大约 6 MS总生成时间为 6 秒...这太可怕了。

有没有其他方法来管理这个问题?我不太热衷于云存储 API,但我似乎找不到其他任何东西...ACL 似乎对此毫无用处,我能想到的唯一其他事情就是每天轮换文件位置?...基础以混淆它们。有没有人遇到过类似的情况,或者知道我可以从哪里开始解决这个问题?


经过更多研究,我得出以下结论:

我的第一次计算是使用 Google 的 gsutil 工具完成的,该工具在计算签名 URL 哈希时似乎会引入大量开销,例如:

gsutil 代码:

gsutil signurl -d 60m /path/to/google.p12 gs://bucket/file

执行时间:0.73812007904053

,但是,使用本机 PHP 函数创建签名 URL 要快得多:

PHP代码:

function storageURL($bucket,$archivo) {
    $expires = time()+60; 
    $to_sign = ("GET\n\n\n".$expires."\n/".$bucket.'/'.$archivo);
    $fp = fopen('/path/to/google.pem', 'r');
    $priv_key = fread($fp, 8192);
    fclose($fp);
    $pkeyid = openssl_get_privatekey($priv_key);
    if(!openssl_sign($to_sign,$signature,$pkeyid,'sha256')) {
        $signature = 'sinfirma';
    } else {
        $signature = urlencode(base64_encode($signature));
    }
    return ('https://'.$bucket.'.storage.googleapis.com/'.$archivo.'[email protected] /cdn-cgi/l/email-protection&Expires='.$expires.'&Signature='.$signature);
}

执行时间:0.0007929801940918

这改变了一切,因为运行 2000 次 PHP 代码迭代仍然只给我 1.0643119812012 的执行时间,加上用于创建所有 m3u8 文件的额外 0.0325711573357 加上 0.0039050579071045 的额外 6 次迭代来为 m3u8 创建签名 URL;总执行时间为 1.100788196444004 秒,其中最大部分取决于视频的长度。

这实际上看起来很好,因为用户习惯了较长视频的较长“加载”或“缓冲”时间,因此当视频较长时大约 0.5 - 大约 1.5 秒的额外时间不会对可用性产生太大影响。

顺便说一句,在当前状态下,服务器上目前有 689 个视频,总共有 864,138 个相关的 .ts 和 .aac 文件,每个视频有 6 个 m3u8 (180,360,480,720,1080,AAC) 加上一个额外的 m3u8 主文件播放列表...因此,为所有视频生成每小时的 url 将需要 (689 [master m3u8] + 864,138 [assets] + 4134 [qual m3u8]) 868,961 次 PHP 代码迭代,总运行时间为 467.15262699127(约 7 分钟),考虑到动态生成每个 URL 的运行时,这是可以管理的,但没有实际意义。

这一切都使用 Google Compute n1-highmem-2 实例,该实例不是那么强大,因此切换到更强大的机器将使所有这一切变得更快。

但所有这些都带来了另一个维度,因为谷歌(就像所有其他公司一样)对每个存储桶上的每次 PUT 操作收费,因此成本计算是有序的。查看上个月的统计数据,我看到总共 447,103 次视频播放(嘿,这是一个小网站),根据提议的方案,将为每个视频点击生成 7 个 PUT 操作(6 比特率 m3u8 + 1 master m3u8),该月总共有 3,129,721 个额外的 PUT,计算成本(3129721 / 10000 * 0.01)给我一个 3.13 美元的额外成本……虽然很小,但如果该网站变得更受欢迎,可能会成为一个问题。另一个解决方案(每个人每小时签名的 URL)将生成 ((689 [master m3u8] + 4134 [qual m3u8]) * 24 [gens per day] * 30 [days per Month]) 3,472,560 个额外的 PUT...这大约是相同,所以我在两个方案之间进行选择时处于或接近收支平衡点(成本方面)。我必须使用前几个月的数据在这里做更多的数字,以便更好地了解这一点,因为一种方案(每次点击的 URL)取决于用户数量,另一种方案(全局 URL 生成)取决于视频数量......并且它们各自以完全不同的方式扩展。

本质上,使用本机代码,问题似乎纯粹是金钱上的小编码向量(重写视频播放代码与引入每小时 URL 生成)。在做出最终决定之前,需要对两者进行研究和比较。

虽然,Cloud Storage API 中的一个新 ACL(例如以 m3u8 作为有效负载的媒体部分文件)可以绑定到 m3u8,这将使一切工作更顺利……我可以在某个地方向 Google 提出这个建议吗?存储团队?

-- 30/10 编辑:最终解决方案 --

这是我想出的最终解决方案,到目前为止似乎运行良好。

Setup:

Google 云计算实例上的 Nginx - m3u8.domain.com

  • 视频转换器执行以下操作: 1.- ffmpeg将源文件转换为180,360,480,720,1080,AAC子文件 2.- ffmpeg 将文件分割成 11 秒的块(文件较少,iOS 仍然接受) 3.- PHP 将所有媒体文件复制到 GS 存储桶 4.- PHP解析生成的m3u8文件并创建动态m3u8文件 5.- PHP 将 size.m3u8 文件和 master.m3u8 文件复制到附加 HDD 上的正确目录

  • nginx.conf 中的新服务器块将 .m3u8 文件解析为 PHP 1.- OSMF播放器请求master m3u8,JS添加会话令牌 2.- PHP 检查会话令牌 + IP 来验证用户 3.- 如果经过验证,则回显当前视频 m3u8 4.- 如果未验证,则回显 m3u8 表示不允许您观看此视频

对于 2:44:08 的视频文件,该过程需要 0.7 - 0.9 秒,用户几乎看不到。对于较短的视频来说,它是指数级的小。

云存储桶 (mp4domain) - mp4.domain.com

该存储桶应用了默认 ACL,该 ACL 使所有文件均为私有文件,但可供用于生成签名网址的 Google ID 访问。

因此,单个视频具有以下文件:

SERVER/nginx/mp4/uniqid/uniqid.m3u8
SERVER/nginx/mp4/uniqid/180p/stream.m3u8
SERVER/nginx/mp4/uniqid/360p/stream.m3u8
SERVER/nginx/mp4/uniqid/480p/stream.m3u8
SERVER/nginx/mp4/uniqid/720p/stream.m3u8
SERVER/nginx/mp4/uniqid/1080p/stream.m3u8
SERVER/nginx/mp4/uniqid/audio/stream.m3u8

GS/bucketmp4/uniqid/180p/segment##.ts
GS/bucketmp4/uniqid/360p/segment##.ts
GS/bucketmp4/uniqid/480p/segment##.ts
GS/bucketmp4/uniqid/720p/segment##.ts
GS/bucketmp4/uniqid/1080p/segment##.ts
GS/bucketmp4/uniqid/audio/segment##.aac

(所以似乎认为这是代码,否则不会让我格式化它)

这样,对 GS 的写入只需完成一次,并且由于所有客户端都认为他们正在接收纯 m3u8 文件,因此无需在客户端进行黑客攻击。

希望这可以帮助有类似问题的人。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

媒体的 Google Cloud Storage 签名网址 的相关文章

  • 无法与站点通信以检查致命错误

    无法与站点通信以检查致命错误 因此 PHP 更改已恢复 您需要通过其他方式上传 PHP 文件更改 例如使用 SFTP 有什么解决办法 我正在 WordPress 中编辑头文件 遇到这个问题 尝试这个 我有同样的问题并决定调查一下 更改 wp
  • 如何移动 Zend_Layout 的“视图”

    通常它会是这样的结构 application modules somemodule views scripts index index phtml 我如何将其移动到 application templates somemodule temp
  • 如何让 Laravel“确认”验证器将错误添加到确认字段?

    默认情况下 Laravel 确认 验证器将错误消息添加到原始字段 而不是通常包含确认值的字段 password gt required confirmed min 8 是否有任何简单的方法来扩展验证器或使用一些技巧来强制它始终在确认字段而不
  • Laravel 注册成功后如何重定向到上一页?

    现在redirectTo被设定为 home 我想知道如何重定向到上一页 我尝试使用 protected redirectTo URL previous 但我得到解析错误 期待 or 解决这个问题的最佳解决方案是什么 我想我需要重写 redi
  • 使用 ImapMailbox.php 按日期对 Imap 邮箱进行排序

    我有一个客户支持系统 它会在收到电子邮件时创建电子邮件 我曾经使用后缀和特殊配置来获取电子邮件以添加额外的功能 例如 我想包含从电子邮件发送的附件 系统不会执行此操作 而是创建一封带有主题的电子邮件 因此我可以通过匹配主题来包含附件 我使用
  • PHP DBlib PDO 问题

    我正在尝试通过 php 连接到 MSSQL 服务器 但我的 pdo 连接给我带来了困难和我不太理解的错误 我在下面粘贴的代码一周前运行得很好 突然间它就停止了 没有任何人进行任何更改 我仍然可以连接到服务器并直接从命令行运行查询 但我在 p
  • 如何将JS/CSS文件包含到Slim框架的模板中?

    我正在使用 Slim 框架开发一个简单的网络应用程序 我遇到了一个可能很简单的问题 我想将静态文件 CSS 和 Javascript 包含到我的模板中 我的项目文件夹结构如下 index php lt where all the routi
  • 这是过滤数据并防止 SQL 注入和其他攻击的安全方法吗?

    我创建了两个简单的函数来在插入数据进入 mysql 查询之前对其进行过滤 对于表单字段 我还使用正则表达式来单独检查每个字段 Form filter function filter var HTML is not allowed var s
  • CodeIgniter/PHP - 从视图内调用视图

    基本上 对于我的网络应用程序 我正在尝试更好地组织它 目前 每次我想加载页面时 我都必须从控制器中执行此操作 如下所示 this gt load gt view subviews template headerview this gt lo
  • WooCommerce 自定义字段 - 多选

    我在 WooCommerce 的结账页面添加额外的字段 我可以添加文本框等基本字段 但需要添加一个 多 选择框 用户可以在其中选择多个项目 我已经弄清楚如何通过代码添加选择框 如下所示 add action woocommerce afte
  • 提交简单 PHP 表单时出现禁止错误

    我有一个不复杂的问题 这似乎比应有的更复杂 我有一个简单的表单 用于向网站添加内容 有些字段需要输入html 然而 当您在表单的不同部分输入某些 html 元素时 它会认为它讨厌您并抛出禁止的 403 错误 这是下面的表格
  • 在 PHP 中使用可变变量是不好的做法吗?

    例如 一个简单的MVC类型系统 api class method使用重写为 PHP 变量 htaccess nginx conf 然后做类似的事情
  • 带摘要的 php curl 返回两个响应

    我发现了一个 奇怪 的 php CURL 行为 这让我抓狂 基本上我正在做的是使用curl 进行摘要身份验证的调用 这是我的代码的摘录 curl setopt this gt c CURLOPT HTTPAUTH CURLAUTH DIGE
  • 使用活动目录对 Intranet 站点上的用户进行身份验证

    我建立了一个 内联网 站点 它有自己的登录系统 用户注册为新用户 并使用其上的用户名 密码登录该站点 但是 现在我想扩展它 让 Intranet 站点使用现有的 ActiveDirectory 进行身份验证 这就是我正在寻找的 前进 当用户
  • 是否可以像在终端中使用“ls”命令一样查询Google Cloud Storage?

    我正在使用 python 库来查询 Google Cloud Storage 并使用命名层次结构在存储中组织信息 例如 my bucket simulations version 1 data my bucket simulations v
  • 我应该在 Symfony 中哪里放置既不是控制器也不是模型的类?

    对于我的应用程序包 我需要一些既不是控制器也不是模型的类 例如 我想要一个scorecard具有诸如 技能 效率 美丽 等成员的类 此外 它可能具有诸如 meanScore 之类的成员方法 getters 这样的类在 Symfony 框架中
  • 如何验证上传的文件是视频?

    我的服务器上有一些非常敏感的信息 因此安全性是一个大问题 用户需要能够上传视频 我知道允许用户上传文件会带来安全威胁 因为没有 100 的方法可以阻止他们上传非视频 但我显然可以选择服务器将保留哪些文件 我知道检查文件扩展名是不够的 检查
  • 如何检测iPhone是否有视网膜显示屏?

    如何检测 iPhone 是否配备视网膜显示屏 有靠谱的办法吗 要么是纯 PHP 要么最好是 Zend Framework 方式来执行此操作 我通过这个弄清楚了 var retina window devicePixelRatio gt 1
  • 什么是 PHP session_start()

    它是否基于 cookie 启动当前会话 从 PHP 网站上得到的 PHP如何控制会话 如果我在用户打开我的登录页面时启动会话 我什至可以使用该会话做什么 我可以使用当前会话来获取有关登录用户的信息吗 PHP 会话系统允许您将数据安全地存储在
  • 如何让php页面从html页面接收ajax post

    我有一个非常简单的表单 其中有一个名字输入字段 我捕获了表单数据 并使用标准 jQuery 发布方法通过 ajax 将其传输到 PHP 页面 但是 我根本无法从 PHP 页面获得任何在服务器端捕获数据的响应 我不确定我做错了什么或缺少什么

随机推荐