Google云端存储已为媒体签署了网址

时间:2014-09-11 03:59:42

标签: php google-cloud-storage

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

现在这很好用,根据服务器负载,开销在8到20 MS之间,并且在生成m3u8链接时不需要在PHP中修改URL。 OSMF只获取m3u8并询问文件,javascript添加令牌cookie而Bob是你的叔叔。

现在我们正在迁移到Google云端存储,而我遇到的问题是我无法真正控制其中任何一个...... m3u8的签名网址很简单,但每个m3u8都会对于每个分辨率,缩略图和音频aac,每个ts文件必须使用签名网址动态生成(为了给你一个想法,我选择的随机视频总共有1,043个文件)...这是1,043个不同的签名网址,大致生成6 MS每次给出6秒的总生成时间......这很可怕。

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

1 个答案:

答案 0 :(得分:2)

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

我的第一次计算是使用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.'?GoogleAccessId=XXXXXXX@developer.gserviceaccount.com&Expires='.$expires.'&Signature='.$signature);
}

执行时间:0.0007929801940918

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

这实际上看起来很好,因为用户已经习惯了更长时间的加载"或者"缓冲"对于较长的视频来说,如果视频较长时间约为0.5 - ~1.5秒,则不会真正影响可用性。

另外,在当前状态下,服务器上目前有689个视频,共有864,138个相关的.ts和.aac文件,每个视频有6 m3u8s(180,360,480,720,1080,AAC)加上另外的m3u8对于主播放列表...所以为所有视频生成每小时网址需要(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主m3u8),当月总计3,129,721个额外​​的PUT,计算成本(3129721/10000 * 0.01)给我一个3.13美元的额外成本的美元数字...小但是如果网站成为可能成为一个问题更流行。另一个解决方案(每个人每小时签名的URL)将生成((689 [master m3u8] + 4134 [qual m3u8])* 24 [gens per day] * 30 [每月天数])3,472,560个额外的PUT ...这大致是同样,所以我处于或接近盈亏平衡点(成本方面),以便在两种方案之间进行选择。我必须使用前几个月在这里做更多的数字'数据以更好地了解这一点,因为一个方案(每次点击的URL)取决于用户数量而另一个(全局URL生成)取决于视频数量......并且它们各自以完全不同的方式扩展。

从本质上讲,使用本机代码,问题似乎纯粹是带有小编码向量的货币(重写视频播放代码与引入每小时URL生成)。在做出最终决定之前,需要先仔细查看和比较两者。

虽然云存储API中的新ACL(比如m3u8作为有效载荷的媒体部分文件)可以绑定到m3u8,但是可以使得一切都更顺畅......有什么地方我可以提出这个加入Google存储团队?

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

这是我提出的最终解决方案,到目前为止似乎工作正常。

设定:

Google Cloud Compute Instance上的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文件复制到连接硬盘上的正确目录

  • nginx.conf中的新服务器块,它将.m3u8文件解析为PHP 1.- OSMF播放器请求master m3u8,JS添加会话令牌 2.- PHP检查会话令牌+ IP以验证用户 3.-如果有效,则回声当前视频m3u8 4.-如果没有经过验证,echos m3u8说你不能看到这个视频

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

云存储分区(mp4domain) - mp4.domain.com

存储桶已应用默认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文件,所以不必在客户端进行黑客攻击。

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