因此,我有一个使用ReactPHP来运行进程的应用程序,我需要保持该子进程在后台运行,并能够提供其stdin数据。
在到目前为止的示例中,事情是在运行事件循环之前完成了stdin和stdout IO。
实际上,我已经尝试运行循环,并尝试稍后再写入子进程的stdin ...结果是错误,告诉我stdin为null。我转储了该过程,却发现确实stdin,stdout和stderr都为空。
那么,如何在已经开始的循环中继续将输入提供给正在运行的进程?
代码如下:
<?php
namespace MyApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use React\EventLoop\Factory;
use React\ChildProcess\Process;
class Chat implements MessageComponentInterface {
private $streamUrl;
private $streamName;
private $vcodec;
private $ffpmeg; // The ffmpeg process
public function onOpen(ConnectionInterface $conn) {
error_log('EVENT! socket open');
}
public function onMessage(ConnectionInterface $from, $msg) {
error_log('EVENT! socket message');
error_log("message is: $msg");
if (substr($msg, 0, 13) == 'stream_name: ') {
error_log('SETTING STREAM NAME!.');
$this->streamName = substr($msg, 13);
} elseif (substr($msg, 0, 12) == 'stream_url: ') {
error_log('SETTING STREAM URL!.');
$this->streamUrl = substr($msg, 12);
} elseif (substr($msg, 0, 8) == 'vcodec: ') {
error_log('SETTING VCODEC!.');
$this->vcodec = substr($msg, 8);
} elseif ($msg == 'reset_stream') {
error_log('RESETTING STREAM!.');
//todo kill process.
$this->ffmpeg = null;
$this->streamUrl = null;
$this->streamName = null;
$this->vcodec = null;
}
$hasStreamInfo = !empty($this->vcodec) && !empty($this->streamUrl) && !empty($this->streamName);
if ($hasStreamInfo && empty($this->ffmpeg)) {
error_log("We essentially have all we need to stream at this point.");
$loop = Factory::create();
$this->ffmpeg = new Process('ffmpeg', [
// Facebook requires an audio track, so we create a silent one here.
// Remove this line, as well as `-shortest`, if you send audio from the browser.
'-f', 'lavfi', '-i', 'anullsrc',
// FFmpeg will read input video from STDIN
'-i', '-',
// Because we're using a generated audio source which never ends,
// specify that we'll stop at end of other input. Remove this line if you
// send audio from the browser.
'-shortest',
// If we're encoding H.264 in-browser, we can set the video codec to 'copy'
// so that we don't waste any CPU and quality with unnecessary transcoding.
// If the browser doesn't support H.264, set the video codec to 'libx264'
// or similar to transcode it to H.264 here on the server.
'-vcodec', $this->vcodec,
// AAC audio is required for Facebook Live. No browser currently supports
// encoding AAC, so we must transcode the audio to AAC here on the server.
'-acodec', 'aac',
// FLV is the container format used in conjunction with RTMP
'-f', 'flv',
// The output RTMP URL.
// For debugging, you could set this to a filename like 'test.flv', and play
// the resulting file with VLC. Please also read the security considerations
// later on in this tutorial.
'/home/hel/Desktop/workspace/soketo/test.flv'
// $this->streamUrl
]);
error_log("FFMPEG CREATED.");
$this->ffmpeg->start($loop);
error_log("FFMPEG STARTED.");
$this->ffmpeg->stdout->on('data', function ($chunk) {
echo $chunk;
});
$this->ffmpeg->on('exit', function($exitCode, $termSignal) {
echo 'Process FFMPEG exited with code ' . $exitCode . PHP_EOL;
});
$this->ffmpeg->stdout->on('error', function (Exception $e) {
echo 'error: ' . $e->getMessage();
});
/* $process->stdin->write($data);
$process->stdin->end($data = null);*/
error_log("Stream created, it is time to die.");
$loop->run();
error_log('RUN LOOP.');
return;
} elseif ($hasStreamInfo && !empty($this->ffmpeg)) {
error_log('ffmpeg NOT EMPTY. writing to it.');
var_dump($this->ffmpeg);
$this->ffmpeg->stdin->write($msg);
}
//$process->stdin->end($data = null);
}
public function onClose(ConnectionInterface $conn) {
error_log('EVENT! socket close');
}
public function onError(ConnectionInterface $conn, \Exception $e) {
error_log('EVENT! socket error');
}
}
确实,可能不是我有史以来最好的代码,但是我有点仓促和沮丧。 另外,是的,这个想法是有一个棘轮套接字,我的应用程序将连接到该棘轮套接字,以便将视频流传输到rtmp服务器。
谢谢大家!