I'm trying to execute ffmpeg commands using Symfony Process Component but command is not being processed. What am I doing wrong?
I get the error
The command "'ffmpeg -i [...........]' failed. Exit Code: 127(Command
not found)"
<?php
$info = pathinfo($file);
$dir = "{$info['dirname']}/{$info['filename']}";
File::makeDirectory($dir, 0755, true)
$process = new Process(["ffmpeg -i {$info['basename']} -codec copy -map 0 -f segment -segment_list {$dir}/playlist.m3u8 -segment_list_flags +live -segment_time 10 {$dir}/{$info['filename']}_%02d.ts"]);
$process->setWorkingDirectory($info['dirname']);
$process->start();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
echo $process->getOutput();
?>
You have to put each argument in a separate element of the array, for example:
$process = new Process([
"ffmpeg",
"-i",
"{$info['basename']}",
"-codec",
"copy",
"-map",
"0",
"-f",
"segment",
"-segment_list",
"{$dir}/playlist.m3u8",
"-segment_list_flags",
"+live",
"-segment_time",
"10",
"{$dir}/{$info['filename']}_%02d.ts",
]);
And I think you should either:
use $process->run() instead of $process->start()
or read in more detail how to run a process asynchronously with $process->start()
Related
I am trying to develop a web console using php and xterm.js,
I managed to get the pseudo tty allocated and attach it to xterm.js via websocket but I am not able to tell the process what is the size of terminal to make it work correctly with the size, and I couldn't find any documentation for this.
// using react/child-process
$process = new Process('/usr/bin/env bash -l', null, null, [
0 => ['pty', 'r'],
1 => ['pty', 'w'],
2 => ['pty', 'w'],
]);
$process->start($this->loop);
I found out run stty on the allocated devpts will do the tricks
if (isset($this->processes[spl_object_id($conn)])) {
$process = $this->processes[spl_object_id($conn)];
$data = unpack('i3', $raw);
$col = $data[2];
$row = $data[3];
$getstream = (function () {
return $this->stream;
});
$stty = new Process("stty cols $col rows $row", null, null, [
$getstream->call($process->stdin), // ex: /dev/pts/0
$getstream->call($process->stdout),
$getstream->call($process->stderr),
]);
$stty->start($this->loop);
}
alternatively can do this
use React\ChildProcess\Process;
$gettty = escapeshellcmd(PHP_BINARY).' -r "echo posix_ttyname(STDIN).PHP_EOL;"';
$bash = "setsid bash -l"; // setsid is important here
$process = new Process(
"$gettty && $bash",
null, null,
[
['pty', 'r'],
['pty', 'w'],
['pty', 'w'],
]
);
// TODO: read the first line and get the tty path so can run stty on it later.
Here is a simple example:
https://gist.github.com/eslym/d3bd7809681aa9c1eb34913043df9bb6
I'm trying to run a linux process in Symfony 5.1 as described here:
https://symfony.com/doc/current/components/process.html
use Symfony\Component\Process\Process;
(...)
$command = 'echo hello';
$process = new Process([$command]);
$process->start();
foreach ($process as $type => $data) {
if ($process::OUT === $type) {
echo "\nRead from stdout: ".$data;
} else { // $process::ERR === $type
echo "\nRead from stderr: ".$data;
}
}
No matter what my command line is, I get the following output:
Read from stderr: sh: 1: exec: echo hello: not found
In the docs you mentioned you can see example: https://symfony.com/doc/current/components/process.html#usage
$process = new Process(['ls', '-lsa']);
Source code for Process constructor:
https://github.com/symfony/symfony/blob/5.1/src/Symfony/Component/Process/Process.php#L132
First parameter is:
* #param array $command The command to run and its arguments listed as separate entries
Try $process = new Process(['echo', 'hello']); not $process = new Process(['echo hello']);
When we use proc_open in PHP:
<?php
$descriptors = array(
array('pipe', 'r'),
array('pipe', 'w'),
array('pipe', 'w'),
);
$cmd = 'cat <(ls)';
//$cmd = 'ls';
echo $cmd . PHP_EOL;
$ph = proc_open($cmd, $descriptors, $pipes);
echo stream_get_contents($pipes[1]);
echo stream_get_contents($pipes[2]);
proc_close($ph);
When run this script, an error occurred:
$ php test.php
cat <(ls)
sh: 1: Syntax error: "(" unexpected
but run the raw cmd:
$ cat <(ls)
clusterRegions.php
composer.json
composer.lock
cvCells.php
kent
prepareForTF.php
README.txt
scoreRegions.php
test.php
tests
vendor
Seems that the <() thing cannot be recognized by proc_open.
So how to pass a bash command with a file descriptor to proc_open ?
#Etan Reisner, you are right, when I change to bash, it runs well.
$cmd = 'bash -c "cat <(ls)"';
I have two ways without success and different results, with exec method the ffmpeg actually works and creates the output file but then the website crashes with error 500.
if I use the proc_open method then it runs and creates the log file atest.log in the output store folder, but ffmpeg errors at the end with: store\audio_recording_1441120844021u.mp3: Permission denied and doesn't write the file out.
ffmpeg has IUSR full control permissions and those permissions are also on the store folder.
any ideas???
exec method:-
$cmd = "ffmpeg.exe -i C:\\Windows\\Temp\\recordings\\".$filename." -i watermark.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 store\\".$filename;
echo exec($cmd, $o, $v);
proc_open method:-
$cmd = "ffmpeg.exe -i C:\\Windows\\Temp\\recordings\\".$filename." -i watermark.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 store\\".$filename;
$pipes = array();
$descriptors = array(2 => array('file', 'store\\atest.log', 'a'));
$p = proc_open($cmd, $descriptors, $pipes);
$done = 0;
while (!$done)
{
sleep(1);
$status = proc_get_status($p);
if (!$status['running']) $done = 1;
echo "STEEL RUN\n";
// some manipulations with "store\\atest.log"
}
For the exec() function, adding -nostdin to the FFMPEG command did the trick:
$cmd = "ffmpeg.exe -nostdin -i C:\\Windows\\Temp\\recordings\\".$filename." -i watermark.mp3 -filter_complex amerge -c:a libmp3lame -q:a 4 store\\".$filename;
Happens that i need to track file status through ssh by php(using phpunit). But when i trying to launch this code:
$descriptorspec = array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w'),
);
$cmd = "ssh hostname 'tail -F ~/test.file'";
$proc = proc_open($cmd, $descriptorspec, $pipes, null);
$str = fgets($pipes[1]);
echo $str;
if (!fclose($pipes[0])) {
throw new Exception("Can't close pipe 0");
}
if (!fclose($pipes[1])) {
throw new Exception("pipe 1");
}
if (!fclose($pipes[2])) {
throw new Exception("pipe 2");
}
$res = proc_close($proc);
nothing happens - no output, and i guess deadlock exucuted: script doesn't exit.
Have any ideas? or suggestions?
tail -F doesn't actually "end" - it just keeps dumping output as it becomes available. That's probably the problem. It's blocking on the fgets().
My recommendation: use phpseclib, a pure PHP SSH2 implementation. eg.
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
function packet_handler($str)
{
echo $str;
}
$ssh->exec('tail -F ~/test.file', 'packet_handler');
?>
Although looking at the implementation, now... it doesn't look like it provides you with any mechanism to prematurely quit either. It'd be nice if it was like "if packet_handler returns false then exec() stops running" or something.
I guess in lieu of that you can use ->setTimeout().