PHP:Return 立即响应,但 运行 多个冗长的 shell_exec 函数在后台
PHP: Return response immediately, but run multiple lengthy shell_exec functions in the background
我正在创建一个简单的网络服务,它接受视频上传,运行对视频进行多种不同的编码(mp4、webm、ogv),然后将新创建的文件上传到我们的视频主机。
假设我有多个命令..
shell_exec('ffmpeg -i input.mp4 -f mp4 -c:v libx264 -preset slow -crf 24 -s 1280x720 -c:a libfdk_aac -profile:a aac_he -ar 22050 -b:a 64k -movflags +faststart output-1280x720.mp4');
shell_exec('ffmpeg -i input.mp4 -f mp4 -c:v libx264 -preset slow -crf 24 -s 1920x1080 -c:a libfdk_aac -profile:a aac_he -ar 22050 -b:a 64k -movflags +faststart output-1920x1080.mp4');
shell_exec('ffmpeg -i input.mp4 -f ogg -c:v libtheora -q:v 5 -s 1280x720 -c:a libvorbis -ar 22050 -b:a 64k -movflags +faststart output-1280x720.ogv');
shell_exec('ffmpeg -i input.mp4 -f ogg -c:v libtheora -q:v 5 -s 1920x1080 -c:a libvorbis -ar 22050 -b:a 64k -movflags +faststart output-1920x1080.ogv');
综上所述,我想...
- 打印立即响应:{success: true}
- 同步启动多个 ffmpeg 作业。
- 每个作业完成后,发送一个 POST 到另一台服务器(每个 shell_exec 发送一个 POST)。
如果作业成功,只发送 POST 也很好,但我可以通过检查输出文件是否存在于服务器上来轻松解决这个问题。
我知道我可以通过简单地将 >/dev/null 2>/dev/null &
附加到每个命令来在后台强制 shell_exec 到 运行 -- 这将允许我立即打印响应 -- 但是我认为通过这样做,这将导致所有作业并行 运行,而且,由于这是转移输出,当作业完成时我没有得到任何真正的回调。
有什么想法吗??
我决定采用异步请求文件的想法。为了保持干净,我能够将它全部包含在一个单独的文件中,该文件 "re-calls" 本身具有不同的 POST 请求。
$root_path = $_SERVER['DOCUMENT_ROOT'] . '/';
$root_http = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . '/';
function request_async($url, $params, $type='POST', $timeout=30) {
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts = parse_url($url);
$fp = fsockopen(
$parts['host'],
isset($parts['port']) ? $parts['port'] : 80,
$errno,
$errstr,
$timeout
);
if ('GET' == $type) $parts['path'] .= '?'.$post_string;
$out = "$type ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if ('POST' == $type && isset($post_string)) $out .= $post_string;
fwrite($fp, $out);
fclose($fp);
}
function get_http_path($path, $relative = FALSE){
global $root_http, $root_path;
return str_replace($root_path, $relative ? '/' : $root_http, $path);
}
$url = $_POST['url'];
$media = $_POST['media'];
if (isset($url)) {
request_async(get_http_path(__FILE__), array(media => $url), 'POST', 1800);
echo '{"success": true}';
} else
if (isset($media)) {
$data = file_get_contents($media);
// KICK OFF JOBS HERE
echo '{"success": true}';
} else {
echo '{"success": false}';
}
我正在创建一个简单的网络服务,它接受视频上传,运行对视频进行多种不同的编码(mp4、webm、ogv),然后将新创建的文件上传到我们的视频主机。
假设我有多个命令..
shell_exec('ffmpeg -i input.mp4 -f mp4 -c:v libx264 -preset slow -crf 24 -s 1280x720 -c:a libfdk_aac -profile:a aac_he -ar 22050 -b:a 64k -movflags +faststart output-1280x720.mp4');
shell_exec('ffmpeg -i input.mp4 -f mp4 -c:v libx264 -preset slow -crf 24 -s 1920x1080 -c:a libfdk_aac -profile:a aac_he -ar 22050 -b:a 64k -movflags +faststart output-1920x1080.mp4');
shell_exec('ffmpeg -i input.mp4 -f ogg -c:v libtheora -q:v 5 -s 1280x720 -c:a libvorbis -ar 22050 -b:a 64k -movflags +faststart output-1280x720.ogv');
shell_exec('ffmpeg -i input.mp4 -f ogg -c:v libtheora -q:v 5 -s 1920x1080 -c:a libvorbis -ar 22050 -b:a 64k -movflags +faststart output-1920x1080.ogv');
综上所述,我想...
- 打印立即响应:{success: true}
- 同步启动多个 ffmpeg 作业。
- 每个作业完成后,发送一个 POST 到另一台服务器(每个 shell_exec 发送一个 POST)。
如果作业成功,只发送 POST 也很好,但我可以通过检查输出文件是否存在于服务器上来轻松解决这个问题。
我知道我可以通过简单地将 >/dev/null 2>/dev/null &
附加到每个命令来在后台强制 shell_exec 到 运行 -- 这将允许我立即打印响应 -- 但是我认为通过这样做,这将导致所有作业并行 运行,而且,由于这是转移输出,当作业完成时我没有得到任何真正的回调。
有什么想法吗??
我决定采用异步请求文件的想法。为了保持干净,我能够将它全部包含在一个单独的文件中,该文件 "re-calls" 本身具有不同的 POST 请求。
$root_path = $_SERVER['DOCUMENT_ROOT'] . '/';
$root_http = 'http' . (isset($_SERVER['HTTPS']) ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . '/';
function request_async($url, $params, $type='POST', $timeout=30) {
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts = parse_url($url);
$fp = fsockopen(
$parts['host'],
isset($parts['port']) ? $parts['port'] : 80,
$errno,
$errstr,
$timeout
);
if ('GET' == $type) $parts['path'] .= '?'.$post_string;
$out = "$type ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if ('POST' == $type && isset($post_string)) $out .= $post_string;
fwrite($fp, $out);
fclose($fp);
}
function get_http_path($path, $relative = FALSE){
global $root_http, $root_path;
return str_replace($root_path, $relative ? '/' : $root_http, $path);
}
$url = $_POST['url'];
$media = $_POST['media'];
if (isset($url)) {
request_async(get_http_path(__FILE__), array(media => $url), 'POST', 1800);
echo '{"success": true}';
} else
if (isset($media)) {
$data = file_get_contents($media);
// KICK OFF JOBS HERE
echo '{"success": true}';
} else {
echo '{"success": false}';
}