From 018f720fc65b950e14db154f83e83137a86011c8 Mon Sep 17 00:00:00 2001 From: Fabio Varesano Date: Sun, 14 Jan 2007 09:45:57 +0000 Subject: Support for concurrent video conversion. --- plugins/video_ffmpeg_helper/video_render.php | 117 ++++++++++++------------ plugins/video_ffmpeg_helper/video_scheduler.php | 108 ++++++++++++++++++++++ 2 files changed, 164 insertions(+), 61 deletions(-) create mode 100644 plugins/video_ffmpeg_helper/video_scheduler.php diff --git a/plugins/video_ffmpeg_helper/video_render.php b/plugins/video_ffmpeg_helper/video_render.php index 5622fd9..99b0f4b 100644 --- a/plugins/video_ffmpeg_helper/video_render.php +++ b/plugins/video_ffmpeg_helper/video_render.php @@ -3,14 +3,15 @@ /** * @file - * Implement video rendering scheduling. + * Renders a video. This script is called concurrently by video_scheduler.php + * This script has to be launched with "php video_render.php nid vid" * * @author Fabio Varesano */ - - + + /** - * video_render.php configuration + * video_scheduler.php configuration */ // set to the ffmpeg executable @@ -23,8 +24,12 @@ define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video'); // number of conversion jobs active at the same time define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); +// nice value to append at the beginning of the command +define('VIDEO_RENDERING_NICE', 'nice -n 19'); + + /** - * video_render.php configuration ends. + * video_scheduler.php configuration ends. * DO NOT EDIT BELOW THIS LINE */ @@ -47,41 +52,35 @@ error_reporting(E_ALL); // allow execution only from the command line! if(empty($_SERVER['REQUEST_METHOD'])) { - video_render_main(); + if($_SERVER['argc'] != 3) { // check for command line arguments + watchdog('video_render', t('Incorrect parameters to the video_render.php script.', WATCHDOG_ERROR)); + print t('Incorrect parameters'); + } + else { + video_render_main(); + } } else { print t('This script is only executable from the command line.'); die(); } +print("\n"); - -/** - * Main for video_render.php -*/ function video_render_main() { - if($jobs = video_render_select()) { - foreach ($jobs as $job) { - video_render_start($job); - } - } - else { - watchdog('video_render', t('no video conversion jobs to schedule.')); - } -} - + // set the status to active + _video_render_job_change_status($_SERVER['argv'][1], $_SERVER['argv'][2], VIDEO_RENDERING_ACTIVE); + $job = _video_render_load_job($_SERVER['argv'][1], $_SERVER['argv'][2], VIDEO_RENDERING_ACTIVE); -/** - * Starts rendering for a job -*/ -function video_render_start($job) { - // print_r($job); - //db_query('DELETE FROM {video_rendering} WHERE nid=%d AND vid=%d', $job->nid, $job->vid); - + if($job == NULL) { + watchdog('video_render', t('video_render.php has been called with an invalid job resource. exiting.')); + die; + } $command = _video_render_get_command($job); - print('executing ' . $command); + //print('executing ' . $command); + watchdog('video_render', t('executing: ') . $command); //execute the command ob_start(); @@ -89,7 +88,7 @@ function video_render_start($job) { $command_output = ob_get_contents(); ob_end_clean(); - print $command_output; + //print $command_output; if (!file_exists($job->convfile)) { watchdog('video_render', t('video conversion failed. ffmpeg reported the following output: ' . $command_output, WATCHDOG_ERROR)); @@ -106,51 +105,28 @@ function video_render_start($job) { $file = ((object) $file); - print_r($file); + //print_r($file); $dest_dir = variable_get('video_upload_default_path', 'videos') .'/'; if (file_copy($file, file_directory_path() . '/' . $dest_dir)) { $file->fid = db_next_id('{files}_fid'); - print_r($file); + //print_r($file); db_query("INSERT INTO {files} (fid, nid, filename, filepath, filemime, filesize) VALUES (%d, %d, '%s', '%s', '%s', %d)", $file->fid, $job->nid, $file->filename, $file->filepath, $file->filemime, $file->filesize); db_query("INSERT INTO {file_revisions} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $job->vid, $file->list, $file->description); // set vidfile to "" to let video_upload overwrite it with the latest uploaded file - db_query('UPDATE {video} SET vidfile = "%s" WHERE nid=%d AND vid=%d', "", $job->nid, $job->vid); - + db_query('UPDATE {video} SET vidfile = "%s", videox = %d, videoy = %d WHERE nid=%d AND vid=%d', "", $job->calculatedx, $job->calculatedy, $job->nid, $job->vid); + _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_COMPLETE); } else { - watchdog('video_render', t('error moving video to the final directory. Check folder permissions.'), WATCHDOG_ERROR); + watchdog('video_scheduler', t('error moving video to the final directory. Check folder permissions.'), WATCHDOG_ERROR); } } } -/** - * Select VIDEO_RENDERING_FFMPEG_INSTANCES jobs from the queue - * - * @return an array containing jobs -*/ -function video_render_select() { - - $result = db_query('SELECT * FROM {video_rendering} vr INNER JOIN {node} n ON vr.vid = n.vid INNER JOIN {video} v ON n.vid = v.vid WHERE n.nid = v.nid AND vr.nid = n.nid AND vr.status = %d ORDER BY n.created', VIDEO_RENDERING_PENDING); - - // TODO: order jobs by priority - - $jobs = array(); - $i = 0; - $count = db_num_rows($result); - while($i < $count && $i < VIDEO_RENDERING_FFMPEG_INSTANCES) { - $jobs[] = db_fetch_object($result); - $i++; - } - - return $jobs; -} - - /** * Get a string cointaining the command to be executed including options */ @@ -169,7 +145,7 @@ function _video_render_get_command(&$job) { // set to the converted file output $job->convfile = $convfile; - return "$converter $options"; + return VIDEO_RENDERING_NICE . " $converter $options"; } @@ -180,12 +156,31 @@ function _video_render_get_command(&$job) { */ function _video_render_get_size(&$job) { $def_width = variable_get('video_ffmpeg_helper_auto_converter_width', 400); - $x = $job->videox; - $y = $job->videoy; - $height = $def_width * ($y / $x); // do you remember proportions?? :-) + $height = $def_width * ($job->videoy / $job->videox); // do you remember proportions?? :-) + + $job->calculatedx = $def_width; + $job->calculatedy = $height; + return $def_width . 'x' . $height; } +/** + * Load a job +*/ +function _video_render_load_job($nid, $vid, $status) { + $result = db_query('SELECT * FROM {video_rendering} vr INNER JOIN {node} n ON vr.vid = n.vid INNER JOIN {video} v ON n.vid = v.vid WHERE n.nid = v.nid AND vr.nid = n.nid AND vr.status = %d AND n.nid = %d AND n.vid = %d', $status, $nid, $vid); + + return db_fetch_object($result); +} + + +/** + * Change the status to $status of the job having nid=$nid and vid=$vid +*/ +function _video_render_job_change_status($nid, $vid, $status) { + $result = db_query('UPDATE {video_rendering} SET status = %d WHERE nid = %d AND vid = %d', $status, $nid, $vid); +} + ?> diff --git a/plugins/video_ffmpeg_helper/video_scheduler.php b/plugins/video_ffmpeg_helper/video_scheduler.php new file mode 100644 index 0000000..de64bc0 --- /dev/null +++ b/plugins/video_ffmpeg_helper/video_scheduler.php @@ -0,0 +1,108 @@ + + */ + + +/** + * video_scheduler.php configuration +*/ + +// set to the ffmpeg executable +define('VIDEO_RENDERING_FFMPEG_PATH', '/usr/bin/ffmpeg'); + +// set to the temp file path. +//IMPORTANT: the user who runs this script must have permissions to create files there. If this is not the case the default php temporary folder will be used. +define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video'); + +// number of conversion jobs active at the same time +define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); + +/** + * video_scheduler.php configuration ends. + * DO NOT EDIT BELOW THIS LINE +*/ + +/** + * Define some constants +*/ +define('VIDEO_RENDERING_PENGING', 0); +define('VIDEO_RENDERING_ACTIVE', 5); +define('VIDEO_RENDERING_COMPLETE', 10); + + +include_once './includes/bootstrap.inc'; +// disable error reporting for bootstrap process +error_reporting(E_ERROR); +// let's bootstrap: we will be able to use drupal apis +drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); +// enable full error reporting again +error_reporting(E_ALL); + + +// allow execution only from the command line! +if(empty($_SERVER['REQUEST_METHOD'])) { + video_scheduler_main(); +} +else { + print t('This script is only executable from the command line.'); + die(); +} + + + +/** + * Main for video_scheduler.php +*/ +function video_scheduler_main() { + + if($jobs = video_scheduler_select()) { + foreach ($jobs as $job) { + video_scheduler_start($job); + } + } + else { + watchdog('video_scheduler', t('no video conversion jobs to schedule.')); + } +} + + +/** + * Starts rendering for a job +*/ +function video_scheduler_start($job) { + exec("php video_render.php $job->nid $job->vid > /dev/null &"); +} + + +/** + * Select VIDEO_RENDERING_FFMPEG_INSTANCES jobs from the queue + * + * @return an array containing jobs +*/ +function video_scheduler_select() { + + $result = db_query('SELECT * FROM {video_rendering} vr INNER JOIN {node} n ON vr.vid = n.vid INNER JOIN {video} v ON n.vid = v.vid WHERE n.nid = v.nid AND vr.nid = n.nid AND vr.status = %d ORDER BY n.created', VIDEO_RENDERING_PENDING); + + // TODO: order jobs by priority + + $jobs = array(); + $i = 0; + $count = db_num_rows($result); + while($i < $count && $i < VIDEO_RENDERING_FFMPEG_INSTANCES) { + $jobs[] = db_fetch_object($result); + $i++; + } + + return $jobs; +} + + + + +?> -- cgit v1.2.3