使用PHP从FFMPEG读取实时输出

时间:2018-09-29 15:27:10

标签: php ffmpeg pipe output live

我要处理的问题是在执行时从ffmpeg命令获取shell输出,并使用php将其写入html页面。

经过一番研究,我在这里发现了一个非常相似的请求:Update page content from live PHP and Python output using Ajax,这似乎很完美,但是根本没有用。

基本思想是使用AJAX请求来调用PHP脚本,该脚本应执行命令并回显进程中的实时读取内容,请小心使用 this.readyState == 3 (否则,JS脚本仅在完成后才会收到响应)

对于PHP部分,我尝试使用上面答案中的代码(显然适合我的需要):

function liveExecuteCommand($command){

    while (@ ob_end_flush()); // end all output buffers if any

    $proc = popen($command, 'r');

    $live_output     = "";
    $complete_output = "";

    while (!feof($proc))
    {
        $live_output     = fread($proc, 4096);
        $complete_output = $complete_output . $live_output;
        echo "<pre>$live_output</pre>";
        @ flush();
    }

    pclose($proc);           

}

对于我使用的AJAX部分

function getLiveStream(){


        var ajax = new XMLHttpRequest();
          ajax.onreadystatechange = function() {
            if (this.readyState == 3) {

              document.getElementById("result").innerHTML = this.responseText;
            }               
        };          
        var url = 'process/getlive';
        ajax.open('GET', url,true);
        ajax.send();
   }

可悲的是这不起作用。

正在执行的命令是:'ffmpeg.exe -i "C:/Users/BACKUP/Desktop/xampp/htdocs/testarea/test.mp4" -map 0:0 -map 0:1 -c:v libx264 -preset fast -crf 26 -c:a libmp3lame -ar 24000 -q:a 5 "C:\Users\BACKUP\Desktop\xampp\htdocs\testarea\output/test.mkv"',我已经对其进行了测试并且可以正常工作。

当我运行html页面和其中的ajax脚本时,ffmpeg命令甚至无法运行,因为我已在任务管理中签入。它只是返回一个空白文本。

当我自己运行php脚本时,该命令将运行,该文件将被转换,但完全不回显任何内容。

经过更多研究后,我还找到了此页面,该页面似乎是出于以下确切目的而制作的:https://github.com/4poc/php-live-transcode/blob/master/stream.php

相关部分位于结尾,之前的代码用于处理特定于ffmpeg的选项。但这也没有用,但结果却完全相同。

现在我正在考虑简单地将输出写入文件并以动态方式读取它,但是我真的很想知道为什么它们都不对我有用的原因。

编辑:PHP Execute shell command asynchronously and retrieve live output回答了如何从正在写入的临时文件而不是直接从进程中获取内容。

1 个答案:

答案 0 :(得分:0)

ffmpeg将其状态写入stderr而不是stdout,请参见http://php.net/manual/en/function.popen.php示例2

<?php
error_reporting(E_ALL);

/* Add redirection so we can get stderr. */
$handle = popen('/path/to/executable 2>&1', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>