我正在尝试使用 FFMPEG 在服务器上制作一些带有视频的作品,我需要做的是获取进程的进度。
我搜索了一下,找到了 this solution它告诉将日志写入文件,然后读取和解析它。
问题
让我发疯的是我告诉 FFMPEG - 使用 exec
- (process A) 将日志写入文件,但是当我尝试读取它时- 使用 file_get_contents()
- (process B)它不会显示内容,直到 process A 完成(或中断 PHP 脚本)。
因此,当进程 A 完成或提示“PHP 脚本超时”时,我可以根据需要读取文件,刷新页面(进程 B ) 并显示当时的内容。
我尝试过的
我已经尝试使用 fopen()
创建包含 w
、w+
和 a
的文件参数,使用 - 和不使用 - fclose()
。我也尝试使用 flock()
以防万一它知道它已经被锁定并且不必等待,它可以更快地读取到 process B ,但是然后FFMPEG 无法写入文件。
我搜索了 multithreading也是,但我认为必须有一种更简单、更简单的方法。
我还使用了 CURL 和 HTTP 上下文,如 this link建议,但没有运气。
我也试过使用 PHP-FFMPEG,但它不支持最新的 FFMPEG 版本,所以我不能使用它。
我之前说“(或中断 PHP 脚本)”是因为我试图等待,当 PHP 超时时,进程 B 工作正常并且文件仍在更新.
代码
进程A(fileA.php)
exec('ffmpeg -y -i input_file.mp4 output_file.avi 2> C:\Full\Path\To\File\log.txt 1>&2');
进程B(fileB.php)
$content = file_get_contents($file);
if($content){
//get duration of source
preg_match("/Duration: (.*?), start:/", $content, $matches);
$rawDuration = $matches[1];
//rawDuration is in 00:00:00.00 format. This converts it to seconds.
$ar = array_reverse(explode(":", $rawDuration));
$duration = floatval($ar[0]);
if (!empty($ar[1])) $duration += intval($ar[1]) * 60;
if (!empty($ar[2])) $duration += intval($ar[2]) * 60 * 60;
//get the time in the file that is already encoded
preg_match_all("/time=(.*?) bitrate/", $content, $matches);
$rawTime = array_pop($matches);
//this is needed if there is more than one match
if (is_array($rawTime)){$rawTime = array_pop($rawTime);}
//rawTime is in 00:00:00.00 format. This converts it to seconds.
$ar = array_reverse(explode(":", $rawTime));
$time = floatval($ar[0]);
if (!empty($ar[1])) $time += intval($ar[1]) * 60;
if (!empty($ar[2])) $time += intval($ar[2]) * 60 * 60;
//calculate the progress
$progress = round(($time/$duration) * 100);
echo "Duration: " . $duration . "<br>";
echo "Current Time: " . $time . "<br>";
echo "Progress: " . $progress . "%";
}
过程
我只是在 Chrome 选项卡上打开 fileA.php
,几秒钟后,我在另一个 Chrome 选项卡上打开 fileB.php
(它保持为 正在加载)。
我需要什么
我需要能够加载文件并在写入文件时显示我想要显示的信息(通过 exec
和 FFMPEG
或其他 PHP 脚本) ,因此我可以通过一些 AJAX 调用来更新进度百分比。
额外信息
此时,我在装有 Windows 7 Professional 的 IIS 7.5 上使用 PHP 5.4。
感谢大家的时间、帮助和耐心!
最好的问候。
最佳答案
看来现在可以了。经过如此多的尝试但没有成功,我所做的唯一似乎有意义的修改是编写 session_write_close()
before 调用 exec
命令。所以,按照我的例子,它会是这样的:
session_write_close();
exec('ffmpeg -y -i input_file.mp4 output_file.avi 2> C:\Full\Path\To\File\log.txt 1>&2');
现在,如果有人告诉我这是否有意义,或者它是否与我看不到的其他东西有关,我将非常高兴。
谢谢!
关于PHP - 读取和写入相同的文件挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35131640/