我目前有一个视频文件正在通过shell_exec()
电话转换为不同的格式。调用或格式转换没有问题,一切正常;但我的下一步是将该文件推送到 s3 存储桶。
但是,我注意到文件系统缓存不一定会立即刷新我新写入的文件,所以我将一个 0 字节文件推送到 s3,即使每当我在文件系统上查看它时它的长度都是正确的。在调用 shell_exec 和 s3-push 之间在我的代码中插入任意 5 秒睡眠解决了这个问题,但感觉非常糟糕,而且我无法知道 5 秒睡眠是否总是足够的,尤其是在使用更大的视频文件和系统正在加载。
我很确定除非我执行同步调用(再次通过 shell_exec),否则我不能强制刷新磁盘缓存,但我不想使用这种方法,因为它会影响服务器上所有带有任何缓冲数据的文件,而不仅仅是我正在操作的单个文件。
所以我写了这段简单的代码来监控文件大小,直到任何磁盘缓存刷新完成:
$prevSize = -1;
$size = filesize($myFileName);
while ($prevSize < $size) {
sleep(1);
clearstatcache(true, $myFileName);
if ($size > 0)
$prevSize = $size;
$size = filesize($myFileName);
}
基本上,只是循环直到至少有一些东西被刷新到文件中,并且文件大小已经保持一致至少一秒钟。
我不知道的是,磁盘刷新是否只有在所有文件缓存都成功刷新到磁盘时才会更新大小;或者它是否会一次刷新几个块,我可能会发现自己试图将部分刷新的文件推送到 s3 并最终导致它被损坏。
任何意见,将不胜感激。
编辑
现有代码如下所示:
private static function pushToS3($oldFilePath, $s3FileName, $newFilePath) {
self::testFileFlush($newFilePath);
file_put_contents(
$s3FileName,
file_get_contents($newFilePath)
);
}
private function processVidoe($oldFilePath, $s3FileName, $newFilePath) {
// Start Conversion
$command = "ffmpeg -i \"$oldFilePath\" -y -ar 44100 \"$newFilePath\"";
$processID = shell_exec("nohup ".$command." >/dev/null & echo $!");
self::pushToS3($oldFilePath, $s3FileName, $newFilePath);
unlink($newFilePath);
unlink($oldFilePath);
}
这是对在单个服务器上运行的旧遗留代码的修改,只是将文件存储在服务器的文件系统中;但我已经更改了基础设施以在多个 AWS EC2 应用程序服务器上运行以实现弹性,并使用 S3 在 EC2 之间提供文件资源共享。文件由我们的用户上传到应用服务器,然后转换为 flv 并推送到 S3,以便它们可供所有 EC2 实例使用。
长期解决方案将使用 AWS Elastic Transcoder,此时我可以简单地将原始数据推送到 S3 并向 Elastic Transcoder 提交排队请求,但这还需要一段时间。