Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么PHP在向以proc_open启动的进程写入4096字节后会挂起?_Php_Stdin_Vlc_Proc Open - Fatal编程技术网

为什么PHP在向以proc_open启动的进程写入4096字节后会挂起?

为什么PHP在向以proc_open启动的进程写入4096字节后会挂起?,php,stdin,vlc,proc-open,Php,Stdin,Vlc,Proc Open,对于任何想知道的人来说,在离开这一切几个小时后,它现在工作得非常完美。 我正在尝试使用PHP向VLC传递一个视频文件,作为即将到来的项目提案的概念证明 我通过创建一个小于4KB(灰色10秒)的文件并测试我的脚本来展示它的工作原理,但我很好奇为什么会发生这种情况 下面是一个示例脚本,了解我的意思: 我在Windows10上使用PHP5.5.31。我在PHP网站上看到了一些关于这类问题的bug报告,但他们认为最新版本已经修复了它。我不太理解阻塞流的概念,但我已经尝试过PHPV7.0.3,但没有效果

对于任何想知道的人来说,在离开这一切几个小时后,它现在工作得非常完美。

我正在尝试使用PHP向VLC传递一个视频文件,作为即将到来的项目提案的概念证明

我通过创建一个小于4KB(灰色10秒)的文件并测试我的脚本来展示它的工作原理,但我很好奇为什么会发生这种情况

下面是一个示例脚本,了解我的意思:

我在Windows10上使用PHP5.5.31。我在PHP网站上看到了一些关于这类问题的bug报告,但他们认为最新版本已经修复了它。我不太理解阻塞流的概念,但我已经尝试过PHPV7.0.3,但没有效果


我使用命令行运行此脚本:
php file.php

我在Windows上尝试使用LAME进行WAV到MP3转换时遇到了完全相同的问题,无法找到可行的解决方案

我尝试了几十种方法,包括阻塞/非阻塞写入、写入小块(<1k)数据、睡眠和尝试写入,但它始终无法写入所有数据。在它失败之前,我能写的大约是40kb(写入失败将始终返回0,并且永远不会向流写入更多数据,无论我等待了多长时间;无论以前写入的数据块大小如何。我甚至尝试在写入之间等待几秒钟,它们将始终成功写入30-40kb,并且永远不会写入更多数据)

最终我放弃了,幸运的是LAME可以从文件而不是STDIN读取输入,所以我选择将数据写入临时文件,调用LAME,然后删除临时文件

以下是相关代码:

// file descriptors for reading and writing to the Lame process
$descriptors = array(
        0 => array('pipe', 'r'), // stdin
        1 => array('pipe', 'w'), // stdout
        2 => array('pipe', 'a'), // stderr
);
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    // workaround for Windows conversion
    // writing to STDIN seems to hang indefinitely after writing approximately 0xC400 bytes
    $wavinput = tempnam(sys_get_temp_dir(), 'wav');
    if (!$wavinput) {
        throw new Exception('Failed to create temporary file for WAV to MP3 conversion');
    }
    file_put_contents($wavinput, $data);
    $size = 0;
} else {
    $wavinput = '-'; // stdin
}
// Mono, variable bit rate, 32 kHz sampling rate, read WAV from stdin, write MP3 to stdout
$cmd  = sprintf("%s -m m -v -b 32 %s -", self::$lame_binary_path, $wavinput);
$proc = proc_open($cmd, $descriptors, $pipes);
if (!is_resource($proc)) {
    throw new Exception('Failed to open process for MP3 encoding');
}
stream_set_blocking($pipes[0], 0); // set stdin to be non-blocking
for ($written = 0; $written < $size; $written += $len) {
    // write to stdin until all WAV data is written
    $len = fwrite($pipes[0], substr($data, $written, 0x20000));
    if ($len === 0) {
        // fwrite wrote no data, make sure process is still alive, otherwise wait for it to process
        $status = proc_get_status($proc);
        if ($status['running'] === false) break;
        usleep(25000);
    } else if ($written < $size) {
        // couldn't write all data, small pause and try again
        usleep(10000);
    } else if ($len === false) {
        // fwrite failed, should not happen
        break;
    }
}
fclose($pipes[0]);
$data = stream_get_contents($pipes[1]);
$err  = trim(stream_get_contents($pipes[2]));
fclose($pipes[1]);
fclose($pipes[2]);
$return = proc_close($proc);
if ($wavinput != '-') unlink($wavinput); // delete temp file on Windows
if ($return !== 0) {
    throw new Exception("Failed to convert WAV to MP3.  Shell returned ({$return}): {$err}");
} else if ($written < $size) {
    throw new Exception('Failed to convert WAV to MP3.  Failed to write all data to encoder');
}
return $data;
//用于读取和写入Lame进程的文件描述符
$descriptor=数组(
0=>array('pipe','r'),//stdin
1=>数组('pipe','w'),//stdout
2=>array('pipe','a'),//stderr
);
if(strtoupper(substr(PHP_OS,0,3))=='WIN'){
//Windows转换的解决方法
//写入大约0xC400字节后,对STDIN的写入似乎会无限期挂起
$wavinput=tempnam(sys_get_temp_dir(),'wav');
如果(!$wavinput){
抛出新异常('未能为WAV到MP3转换创建临时文件');
}
文件内容($wavinput,$data);
$size=0;
}否则{
$wavinput='-';//标准输入
}
//单声道,可变比特率,32 kHz采样率,从标准输入接口读取WAV,将MP3写入标准输出接口
$cmd=sprintf(“%s-m-m-v-b32%s-”,self:$lame\u binary\u path,$wavinput);
$proc=proc_open($cmd、$descriptor、$pipes);
如果(!is_资源($proc)){
抛出新异常('无法打开MP3编码进程');
}
stream_set_blocking($pipes[0],0);//将stdin设置为非阻塞
对于($writed=0;$writed<$size;$writed+=$len){
//写入stdin,直到写入所有WAV数据
$len=fwrite($pipes[0],substr($data,$writed,0x20000));
如果($len==0){
//fwrite未写入任何数据,请确保进程仍处于活动状态,否则等待它进行处理
$status=proc\u get\u status($proc);
如果($status['running']==false)中断;
美国LEEP(25000);
}如果有,则为($writed<$size){
//无法写入所有数据,请暂停片刻,然后重试
美国LEEP(10000);
}else if($len==false){
//写入失败,不应发生
打破
}
}
fclose($pipes[0]);
$data=stream_get_contents($pipes[1]);
$err=trim(流获取内容($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$return=proc_close($proc);
如果($wavinput!='-')取消链接($wavinput);//删除Windows上的临时文件
如果($return!==0){
抛出新异常(“未能将WAV转换为MP3.Shell返回({$return}):{$err}”);
}如果有,则为($writed<$size){
抛出新异常(“未能将WAV转换为MP3。未能将所有数据写入编码器”);
}
返回$data;

这的确是一种奇怪的行为。我还可以使用$descriptorspec for proc_open中的一个文件让它工作。我无法理解为什么我的确切的一些代码现在也可以工作得很好。在我的情况下,写入临时文件是非常不理想的,因为我们要加密视频文件,在f上解密它它不一定是要分发的PHP文件,但正如我所说的,它只是一个概念证明。
// file descriptors for reading and writing to the Lame process
$descriptors = array(
        0 => array('pipe', 'r'), // stdin
        1 => array('pipe', 'w'), // stdout
        2 => array('pipe', 'a'), // stderr
);
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    // workaround for Windows conversion
    // writing to STDIN seems to hang indefinitely after writing approximately 0xC400 bytes
    $wavinput = tempnam(sys_get_temp_dir(), 'wav');
    if (!$wavinput) {
        throw new Exception('Failed to create temporary file for WAV to MP3 conversion');
    }
    file_put_contents($wavinput, $data);
    $size = 0;
} else {
    $wavinput = '-'; // stdin
}
// Mono, variable bit rate, 32 kHz sampling rate, read WAV from stdin, write MP3 to stdout
$cmd  = sprintf("%s -m m -v -b 32 %s -", self::$lame_binary_path, $wavinput);
$proc = proc_open($cmd, $descriptors, $pipes);
if (!is_resource($proc)) {
    throw new Exception('Failed to open process for MP3 encoding');
}
stream_set_blocking($pipes[0], 0); // set stdin to be non-blocking
for ($written = 0; $written < $size; $written += $len) {
    // write to stdin until all WAV data is written
    $len = fwrite($pipes[0], substr($data, $written, 0x20000));
    if ($len === 0) {
        // fwrite wrote no data, make sure process is still alive, otherwise wait for it to process
        $status = proc_get_status($proc);
        if ($status['running'] === false) break;
        usleep(25000);
    } else if ($written < $size) {
        // couldn't write all data, small pause and try again
        usleep(10000);
    } else if ($len === false) {
        // fwrite failed, should not happen
        break;
    }
}
fclose($pipes[0]);
$data = stream_get_contents($pipes[1]);
$err  = trim(stream_get_contents($pipes[2]));
fclose($pipes[1]);
fclose($pipes[2]);
$return = proc_close($proc);
if ($wavinput != '-') unlink($wavinput); // delete temp file on Windows
if ($return !== 0) {
    throw new Exception("Failed to convert WAV to MP3.  Shell returned ({$return}): {$err}");
} else if ($written < $size) {
    throw new Exception('Failed to convert WAV to MP3.  Failed to write all data to encoder');
}
return $data;