Created
October 13, 2015 09:59
-
-
Save gangstaJS/7a93427c8f3c274aae44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
set_time_limit(0); | |
/* ----------------------------- CONFIG -----------------------------*/ | |
$master_server = "dev2.muvik.tv"; | |
$file_server = 1; | |
// -- API MASTER | |
define('MASTER_CONVERT_RESULT', 'http://'.$master_server.'/api/convert_result/dota2/', true); | |
define('MUVIK_GET_TASK', 'http://'.$master_server.'/api/task/dota2/?', true); | |
define('MUVIK_SEND_STAT', 'http://'.$master_server.'/api/stat/', true); | |
define('SET_SERVER_LOCATION', 'http://'.$master_server.'/api/set_server_location/dota2/', true); | |
// -- FILE SERVER CONFIGS | |
define( 'ROOT_PATH', '/home/muvik/fs'.$file_server.'.muvik.tv/www/', true ); | |
define('CONVERT_PATH', '/home/muvik/fs'.$file_server.'.muvik.tv/www/convert_file/', true); | |
define('SYS_PATH', '/home/muvik/fs'.$file_server.'.muvik.tv/sys/', true); | |
define( 'REAL_FILE_PATH', 'files/', true ); | |
// -------------------------------------------- | |
define('BASE_DOMAIN', 'muvik.tv/', true ); | |
define('MUVIK_API_SECRET', 'I44sC8AQerm6Fc236da1jr4dOn9Cn', true ); | |
define('THIS_SERVER', $file_server, true); | |
define('COUNT_WORKERS', 1, true); // !important; | |
// -- | |
define('RESULT_LOG', SYS_PATH."convertor_result.log", true); | |
define('ERRORS_LOG', SYS_PATH.'convertor_errors.log', true); | |
/*--------------------------- END CONFIGS -----------------------------*/ | |
if(disk_free_space('/') < 1073741824) { | |
log_write(ERRORS_LOG, 'ERROR: not free space'); | |
die; | |
} | |
/* - ---------------------------------- */ | |
$worker = 0; | |
if ($handle = opendir(CONVERT_PATH)) { | |
while (false !== ($entry = readdir($handle))) { | |
if ($entry != "." && $entry != "..") { | |
if (preg_match("/\.proccess$/", $entry)) { | |
$worker++; | |
} | |
} | |
} | |
closedir($handle); | |
} | |
if($worker >= COUNT_WORKERS) die("WORKERS LIMIT OVER \r\n"); | |
/* ------------------------------------ */ | |
$task = json_decode(file_get_contents(MUVIK_GET_TASK."secret=".MUVIK_API_SECRET, false), true); | |
if($task['status'] == 1) { | |
// -- | |
$progress_log = CONVERT_PATH.$task['md5_file'].".progress.log"; | |
$proccess = CONVERT_PATH.$task['md5_file'].".proccess"; | |
// -- | |
if($task['server_location'] != THIS_SERVER) { | |
$fs_location = "http://fs".intval($task['server_location']).".".BASE_DOMAIN."giveme/".$task['md5_file']; | |
$copy_res = copy($fs_location, CONVERT_PATH.$task['md5_file']); | |
if(!$copy_res) { | |
log_write(ERRORS_LOG, 'ERROR: copy file '.$task['md5_file'].', from '.$fs_location); | |
die('ERROR: copy file '.PHP_EOL); | |
} else { | |
$res_server_loaction = set_server_loaction($task['md5_file'], $task['object_id']); | |
if(!isset($res_server_loaction['status']) || ( $res_server_loaction['status'] == 0 )) { | |
log_write(ERRORS_LOG, 'ERROR: file is copy '.$task['md5_file'].', but cant set server loaction'); | |
die; | |
} | |
} | |
} | |
$input_file = CONVERT_PATH.$task['md5_file']; | |
// get info about video; | |
$movie = new ffmpeg_movie($input_file, false); | |
$params = []; | |
// size | |
$params['height'] = $movie->getFrameHeight(); | |
$params['width'] = $movie->getFrameWidth(); | |
// -- | |
/* ------------------------------------ */ | |
$good_v_codecs = array('h264', 'vp8'); | |
$good_a_codecs = array('aac', 'vorbis'); | |
$good_ext = array('mp4', 'webm'); | |
$good_ext_bool = false; | |
$a_codec = ''; | |
$v_codec = $movie->getVideoCodec(); | |
if($movie->hasAudio()) { | |
$a_codec = $movie->getAudioCodec(); | |
} | |
// -------------------------------- | |
if(in_array($task['extension'], $good_ext)) { | |
$good_ext_bool = true; | |
} | |
// -------------------------------- | |
/* ------------------------------------- */ | |
$duration = $movie->getDuration(); | |
$sizes = array( | |
'720p' => array(1280, 720), | |
'480p' => array(640, 480), | |
//'360p' => array(480, 320), | |
); | |
// -- | |
function getwidth($h0, $h1, $w1) { // $h0/$h1*$w1 | |
$w = round($h0/$h1*$w1); | |
return $w-($w%2); | |
} | |
// ----------------------------- | |
$copy_v = false; | |
$copy_a = false; | |
$copy_params = array(); | |
if($good_ext_bool) { // if good extension try copy audio or video streams; | |
if(in_array($v_codec, $good_v_codecs)) { | |
$copy_v = true; | |
} | |
if(!empty($a_codec) && in_array($a_codec, $good_a_codecs)) { | |
$copy_a = true; | |
} | |
$copy_params = array('ext' => $task['extension'], 'q' => 'sd', 'v_c' => $copy_v, 'a_c' => $copy_a); | |
} | |
// -- | |
$go = array(); // масив заданий на конвертацию; | |
// если пригодно для 720p; | |
if ($params['height'] >= $sizes['720p'][1]) { | |
$width720 = getwidth($sizes['720p'][1], $params['height'], $params['width']); | |
$height720 = $sizes['720p'][1]; | |
//array_push($go, array('webm', 'hd', array($width720,$height720))); | |
array_push($go, array('mp4', 'hd', array($width720,$height720))); | |
if(!empty($copy_params)) { | |
$copy_params['q'] = 'hd'; | |
} | |
} | |
// ----------------------- | |
$width480 = ''; | |
$height480 = ''; | |
// получаем новый размер с учетом пропорций; | |
if ($params['height'] >= $sizes['480p'][1]) { | |
$width480 = getwidth($sizes['480p'][1], $params['height'], $params['width']); | |
$height480 = $sizes['480p'][1]; | |
} else { | |
// если размер меньше 480p; | |
$width480 = $params['width']; | |
$height480 = $params['height']; | |
} | |
// array('mp4', 'sd', array($width480,$height480), true, true); /extension/quality/sizes/copy a:stream/copy v:stream | |
array_push($go, array('mp4', 'sd', array($width480,$height480))); | |
//array_push($go, array('webm', 'sd', array($width480,$height480))); | |
// ########################################################################################################### | |
$res = true; | |
$st = 2; //для прогресса, что бы понять какой по счету формат конвертится; | |
foreach($go as $format) { | |
if(!$res) break; | |
// -- | |
$v_c = false; | |
$a_c = false; | |
if(!empty($copy_params) && ($copy_params['ext'] == $format[0]) && ($copy_params['q'] == $format[1]) ) { | |
$v_c = $copy_params['v_c']; | |
$a_c = $copy_params['a_c']; | |
} | |
// -- | |
log_write(RESULT_LOG, "START CONVERT: format -".$format[0].", quality -".$format[1].", size -".$format[2][0]."x".$format[2][1]); | |
$res = convert($format[0]/*формат*/, $format[1]/*quality*/, $format[2]/*размерность*/, $input_file/*входящий файл*/, $proccess, $progress_log, $duration, $st, $v_c, $a_c); | |
$st++; | |
if($res) { | |
// шлем запрос мастеру готово некоторое качество; | |
$ready_q = array('format' => $format[0], 'quality' => $format[1], 'md5_file' => $task['md5_file'], 'object_id' => $task['object_id']); | |
some_ready($ready_q); | |
} else { | |
break; | |
} | |
} | |
// --- | |
if(!$res) { | |
log_write(ERRORS_LOG, 'ERROR CONVER: '.json_encode($formats)); | |
die('Error convert'); | |
} | |
convert_complit($task['object_id']); | |
log_write(RESULT_LOG, '########################## CONVERT COMPLIT: '. $task['md5_file']." ###########################"); | |
// -- | |
} else { | |
die("Error server response, or not tasks".PHP_EOL); | |
} | |
// ------------------- | |
function convert($format, $q, $size = array(), $input_file, $proccess, $progress_log, $duration, $st, $copy_v = false, $copy_a = false) { | |
list($width, $height) = $size; | |
$out_file = $input_file."-".$q.".".$format; | |
$max_bitrate = round(filesize($input_file)/1048576*8192/$duration); | |
$cmd = ''; | |
$crf_mp4 = array('hd' => 21, 'sd' => 28); | |
$crf_webm = array('hd' => 5, 'sd' => 10); | |
$bt_webm = array('hd' => 3, 'sd' => 1); | |
// -- | |
switch ($format) { | |
case 'mp4': | |
$cmd = "ffmpeg -i {$input_file} -y -s {$width}x{$height} -crf ".$crf_mp4[$q]." {$out_file}"; | |
break; | |
case 'webm': | |
$cmd = "ffmpeg -i {$input_file} -y -s {$width}x{$height} -c:v libvpx -qmin 0 -qmax 50 -crf ".$crf_webm[$q]." -b:v ".$bt_webm[$q]."M -c:a libvorbis {$out_file}"; | |
break; | |
} | |
if($copy_v && $copy_a && ($max_bitrate <= 4500)) { | |
$cmd = "ffmpeg -i {$input_file} -y -codec copy {$out_file}"; | |
} | |
log_write(RESULT_LOG, "FILE IN PROCCESS ".$cmd); | |
echo $cmd.PHP_EOL; | |
// отправляем файл на конвертацию; | |
$pipes = array(); | |
$descriptors = array(2 => array('file', $progress_log, 'a')); | |
$p = proc_open($cmd, $descriptors, $pipes); | |
// статус процесса конвертации; | |
$status = proc_get_status($p); | |
// если конвертация в процессе создаем блокирующий файл; | |
if($status['running']) { | |
file_put_contents($proccess, $st); | |
} | |
while(1) { | |
sleep(3); | |
$status = proc_get_status($p); | |
if(!$status['running']) break; | |
} | |
if($status['exitcode'] == 0) { | |
proc_close($p); | |
// удаляем лог прогресса и блокирующий файл; | |
unlink($proccess); | |
unlink($progress_log); | |
return true; | |
} else { | |
return false; | |
} | |
} | |
// -------- | |
function log_write($path, $msg){ | |
file_put_contents($path , "[".date('y.m.d H:i:s ')."] ".$msg."\r\n", FILE_APPEND|LOCK_EX ); | |
} | |
// ------- | |
function some_ready($formats_result = array()) { | |
$c_res = http_build_query(array( | |
'secret' => MUVIK_API_SECRET, | |
'convert_result' => 3, | |
'formats_result' => json_encode($formats_result) | |
)); | |
$options = array( | |
'http' => array( | |
'header' => "Content-type: application/x-www-form-urlencoded\r\n", | |
'method' => 'POST', | |
'content' => $c_res, | |
), | |
); | |
$context = stream_context_create($options); | |
return file_get_contents(MASTER_CONVERT_RESULT, false, $context); | |
} | |
// ------- | |
function set_server_loaction($md5_file, $object_id) { | |
$c_res = http_build_query(array( | |
'secret' => MUVIK_API_SECRET, | |
'server_location' => THIS_SERVER, | |
'object_id' => $object_id, | |
)); | |
$options = array( | |
'http' => array( | |
'header' => "Content-type: application/x-www-form-urlencoded\r\n", | |
'method' => 'POST', | |
'content' => $c_res, | |
), | |
); | |
$context = stream_context_create($options); | |
return json_decode(file_get_contents(SET_SERVER_LOCATION, false, $context), true); | |
} | |
// ---------------------------------------- | |
function convert_complit($object_id) { | |
$c_res = http_build_query(array( | |
'secret' => MUVIK_API_SECRET, | |
'convert_result' => 4, | |
'object_id' => $object_id | |
)); | |
$options = array( | |
'http' => array( | |
'header' => "Content-type: application/x-www-form-urlencoded\r\n", | |
'method' => 'POST', | |
'content' => $c_res, | |
), | |
); | |
$context = stream_context_create($options); | |
return file_get_contents(MASTER_CONVERT_RESULT, false, $context); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment