PHP - 读取和写入相同的文件挂起

标签 php ffmpeg progress file-writing file-read

我正在尝试使用 FFMPEG 在服务器上制作一些带有视频的作品,我需要做的是获取进程的进度。

我搜索了一下,找到了 this solution它告诉将日志写入文件,然后读取和解析它。

问题

让我发疯的是我告诉 FFMPEG - 使用 exec - (process A) 将日志写入文件,但是当我尝试读取它时- 使用 file_get_contents() - (process B)它不会显示内容,直到 process A 完成(或中断 PHP 脚本)。

因此,当进程 A 完成或提示“PHP 脚本超时”时,我可以根据需要读取文件,刷新页面(进程 B ) 并显示当时的内容。

我尝试过的

我已经尝试使用 fopen() 创建包含 ww+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(它保持为 正在加载)。

我需要什么

我需要能够加载文件并在写入文件时显示我想要显示的信息(通过 execFFMPEG 或其他 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/

相关文章:

php - 扩展 Twig 的 AppVariable

PHP foreach 插入语句问题与数组

ffmpeg - 使用 FFMPEG 的 Mp4 视频旋转

c++ - 在 Linux 上使用 FFmpeg 从 OpenCV 3 编写 x264

ios - 从 web 下载图像到照片应用程序 AFNetworking 3

php - 如何在没有收到响应的情况下发出 cUrl 请求?

php - 在数据库表中搜索大量关键字

ffmpeg - 两个 .ts 文件之间缺少一帧

Android ProgressBar 使渐变渐变透明

performance - Powershell Get-ChildItem 进度问题