diff options
| author | Heshan Wanigasooriya <heshanmw@gmail.com> | 2009-04-27 09:47:43 +0000 | 
|---|---|---|
| committer | Heshan Wanigasooriya <heshanmw@gmail.com> | 2009-04-27 09:47:43 +0000 | 
| commit | a69b21cc7ee12c117b58f0d940f7cb9d38278384 (patch) | |
| tree | 685d65bdf14b69c614b1b6676fb30cdb56c9c25d /plugins/video_ffmpeg_helper | |
| parent | 8914e5e66485a1cb9ee1fb741ae47a561167104e (diff) | |
| download | video-a69b21cc7ee12c117b58f0d940f7cb9d38278384.tar.gz video-a69b21cc7ee12c117b58f0d940f7cb9d38278384.tar.bz2  | |
adding plugins to the HEAD
Diffstat (limited to 'plugins/video_ffmpeg_helper')
| -rw-r--r-- | plugins/video_ffmpeg_helper/README.txt | 42 | ||||
| -rw-r--r-- | plugins/video_ffmpeg_helper/video_ffmpeg_helper.info | 5 | ||||
| -rw-r--r-- | plugins/video_ffmpeg_helper/video_ffmpeg_helper.install | 93 | ||||
| -rw-r--r-- | plugins/video_ffmpeg_helper/video_ffmpeg_helper.module | 469 | ||||
| -rw-r--r-- | plugins/video_ffmpeg_helper/video_render.php | 124 | ||||
| -rw-r--r-- | plugins/video_ffmpeg_helper/video_scheduler.php | 38 | 
6 files changed, 538 insertions, 233 deletions
diff --git a/plugins/video_ffmpeg_helper/README.txt b/plugins/video_ffmpeg_helper/README.txt index e69de29..5b6788c 100644 --- a/plugins/video_ffmpeg_helper/README.txt +++ b/plugins/video_ffmpeg_helper/README.txt @@ -0,0 +1,42 @@ +FFMPEG Video.module helper +========================== + +This helper module facilitates uploading new videos using the video module. It +features a batch processing queue for videos to be transcoded and automatic +thumbnail generation. + +IMPORTANT: the ffmpeg helper currently only works on unix based environment. It currently doesn't support Windows based servers. + +Install instructions +-------------------- + +1. Activate the video_ffmpeg_helper module +2. Setup it's advanced options to meet your needs +3. Move (or symlink) video_render.php and video_scheduler.php into your Drupal root +4. Edit the first line of those files to meet your needs +5. Check permissions of the files and folders (/tmp/video and files/* must be writable by the webserver or the user executling the cron job) +6. You now have two options to execute the video_scheduler.php script: + +  6.1 (default) Enable the execution of video_scheduler.php using standard drupal cron. +   +  6.2 Schedule the execution of video_scheduler.php using unix cron + +    The crontab should look something like this: +     +    # m     h       dom     mon     dow     user            command +    */20     *       *       *       *       www-data        cd /absolute/path/to/drupal/ ; php video_scheduler.php http://www.example.com/path_to_drupal +     +    This will execute the video_scheduler every 20 minutes. +     +    Note that the video_scheduler doesn't produce any output and cannot be called +    from the web. It will, however, put some information in the watchdog. +     + + +Troubleshooting +------------------------ + +Configuring and installing ffmpeg in a web server environment might be pretty difficult. In order to help you troubleshoot the transcoding process the ffmpeg helper puts debugging informations on the drupal logs. I strongly suggest to have a look at them if you are experiencing problems with transcoding. + +The ffmpeg puts in the drupal logs the commands it was trying to execute. You might try to rerun them on a command shell in order understand what went wrong. +   diff --git a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info index f2ed8e6..e5ce7aa 100644 --- a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info +++ b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.info @@ -1,5 +1,6 @@ -; $Id$  name = Video ffmpeg Helper  description = Provide apis for ffmpeg. Simplify video nodes creation. -dependencies = video video_upload +dependencies[] = video +dependencies[] = video_upload  package = "Video" +core = 6.x
\ No newline at end of file diff --git a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install index a8cedff..36289d5 100644 --- a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install +++ b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.install @@ -1,40 +1,77 @@  <?php -// $Id$ - -  /**   * @file   * Provide installation functions for video_ffmpeg_helper.module .   *   * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo   */ +/** + * Implementation of hook_schema(). + */ +function video_ffmpeg_helper_schema() { +  $schema['video_rendering'] = array( +    'description' => t('TODO'), +    'fields' => array( +      'vid' => array( +        'description' => t('TODO'), +        'type' => 'int', +        'unsigned' => TRUE, +        'not null' => TRUE, +        'default' => 0, +      ), +      'nid' => array( +        'description' => t('TODO'), +        'type' => 'int', +        'unsigned' => TRUE, +        'not null' => TRUE, +        'default' => 0, +      ), +      'origfile' => array( +        'description' => t('TODO'), +        'type' => 'text', +        'not null' => TRUE, +        'default' => '', +      ), +      'pid' => array( +        'description' => t('TODO'), +        'type' => 'int', +        'unsigned' => TRUE, +        'not null' => TRUE, +        'default' => 0, +      ), +      'status' => array( +        'description' => t('TODO'), +        'type' => 'int', +        'unsigned' => TRUE, +        'not null' => TRUE, +        'default' => 0, +      ), +      'started' => array( +        'description' => t('TODO'), +        'type' => 'int', +        'not null' => TRUE, +        'default' => 0, +      ), +      'completed' => array( +        'description' => t('TODO'), +        'type' => 'int', +        'not null' => TRUE, +        'default' => 0, +      ), +    ), +    'primary key' => array('vid'), +  ); + +  return $schema; +} +  function video_ffmpeg_helper_install() { -  switch ($GLOBALS['db_type']) { -    case 'mysql': -    case 'mysqli': -      db_query("CREATE TABLE {video_rendering} ( -        vid int(10) unsigned NOT NULL default '0', -        nid int(10) unsigned NOT NULL default '0', -        origfile text NOT NULL default '', -        pid int(10) unsigned NOT NULL default '0', -        status int(1) unsigned NOT NULL default '0', -        started int NOT NULL default '0', -        completed int NOT NULL default '0', -        PRIMARY KEY  (vid) -      ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;"); -      break; -    case 'pgsql': -      db_query("CREATE TABLE {video_rendering} ( -        vid integer NOT NULL default '0', -        nid integer NOT NULL default '0', -        origfile text NOT NULL default '', -        pid integer NOT NULL default '0', -        status integer NOT NULL default '1', -        PRIMARY KEY  (vid) -      );"); -      break; -  } +  // Create tables. +  drupal_install_schema('video_ffmpeg_helper');  } diff --git a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module index c1f94ec..446058d 100644 --- a/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module +++ b/plugins/video_ffmpeg_helper/video_ffmpeg_helper.module @@ -1,44 +1,85 @@  <?php -// $Id$  /**   * @file   * Provide some api for use ffmpeg. Simplify video nodes creation.   *   * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo   */  /**   * Define some constants  */ -define('VIDEO_RENDERING_PENDING', 0); +define('VIDEO_RENDERING_PENDING', 1);  define('VIDEO_RENDERING_ACTIVE', 5);  define('VIDEO_RENDERING_COMPLETE', 10); +define('VIDEO_RENDERING_FAILED', 20); + + + +function video_ffmpeg_helper_cron() { +  global $base_url; +   +  if(variable_get('video_ffmpeg_helper_auto_cvr_cron', true)) { +    exec("php video_scheduler.php $base_url > /dev/null &"); +  } +} + + +/** + * Implementatio of hook_perm() +*/ +function video_ffmpeg_helper_perm() { +  return array('bypass automatic video conversion'); +}  /**   * Implementation of hook_help().   */ -function video_ffmpeg_helper_help($section) { -  switch ($section) { +function video_ffmpeg_helper_help($path, $arg) { +  switch ($path) {      case 'admin/modules#description': -      return t('Enable thumbnails support for video module.'); +      return t('Enable ffmpeg support for video module.');    }  }  /**   * Implementation of hook_menu()   */ -function video_ffmpeg_helper_menu($may_cache) { +function video_ffmpeg_helper_menu() {    $items = array(); +/* TODO +   Non menu code that was placed in hook_menu under the '!$may_cache' block +   so that it could be run during initialization, should now be moved to hook_init. +   Previously we called hook_init twice, once early in the bootstrap process, second +   just after the bootstrap has finished. The first instance is now called boot +   instead of init. +    +   In Drupal 6, there are now two hooks that can be used by modules to execute code +   at the beginning of a page request. hook_boot() replaces hook_boot() in Drupal 5 +   and runs on each page request, even for cached pages. hook_boot() now only runs +   for non-cached pages and thus can be used for code that was previously placed in +   hook_menu() with $may_cache = FALSE: +    +   Dynamic menu items under a '!$may_cache' block can often be simplified +   to remove references to arg(n) and use of '%<function-name>' to check +   conditions. See http://drupal.org/node/103114. +    +   The title and description arguments should not have strings wrapped in t(), +   because translation of these happen in a later stage in the menu system. +*/ +    $may_cache=true;    if ($may_cache) { -      $items[] = array( -      'path' => 'admin/content/video/ffmpeg_helper', -      'title' => t('Video ffmpeg Helper'), -      'description' => t('Administer video_ffmpeg_helper module settings'), -      'callback' => 'drupal_get_form', -      'callback arguments' => array('video_ffmpeg_helper_admin_settings'), -      'access' => user_access('administer site configuration'), +      $items['admin/settings/video/ffmpeg_helper'] = array( +      'title' => 'Video ffmpeg Helper', +      'description' => 'Administer video_ffmpeg_helper module settings', +      'page callback' => 'drupal_get_form', +      'page arguments' => array('video_ffmpeg_helper_admin_settings'), +      'access arguments' => array('administer site configuration'),        'type' => MENU_NORMAL_ITEM,      );    } @@ -48,23 +89,18 @@ function video_ffmpeg_helper_menu($may_cache) {  /**   * Validation for settings form   */ -function video_ffmpeg_helper_admin_settings_validate($form_id, &$form_values, &$form) { -  if ($form_values['video_ffmpeg_helper_auto_thumbnail']) { -    if (function_exists('is_executable')) { -      $test = 'is_executable'; -    } else { -      $test = 'file_exists'; -    } -    if (!$test($form_values['video_ffmpeg_helper_ffmpeg_path'])) { -      form_set_error('video_image_ffmpeg_path', t('Set correct path for thumbnailer')); +function video_ffmpeg_helper_admin_settings_validate($form, &$form_state) { +  if (variable_get('video_image_auto_thumbnail', 0)) { +    if (!_video_ffmpeg_helper_check_exe_path($form_state['values']['video_ffmpeg_helper_ffmpeg_path'])) { +      form_set_error('video_ffmpeg_helper_ffmpeg_path', t('Set correct path for ffmpeg'));      } -    if (!is_numeric($form_values['video_ffmpeg_helper_auto_thumbnail_seek'])) { +    if (!is_numeric($form_state['values']['video_ffmpeg_helper_auto_thumbnail_seek'])) {        form_set_error('video_ffmpeg_helper_auto_thumbnail_seek', t('Seek time must be an integer'));      } -	$options = $form_values['video_ffmpeg_helper_thumbnailer_options']; -	if (!strstr($options, '%videofile') || !strstr($options, '%thumbfile')) { -	  form_set_error('video_ffmpeg_helper_thumbnailer_options', t('Thumbnail options must contain mandatory arguments %videofile and %thumbfile')); -	} +    $options = $form_state['values']['video_ffmpeg_helper_thumbnailer_options']; +    if (!strstr($options, '%videofile') || !strstr($options, '%thumbfile')) { +      form_set_error('video_ffmpeg_helper_thumbnailer_options', t('Thumbnail options must contain mandatory arguments %videofile and %thumbfile')); +    }    }  } @@ -73,55 +109,43 @@ function video_ffmpeg_helper_admin_settings_validate($form_id, &$form_values, &$   * Settings form   */  function video_ffmpeg_helper_admin_settings() { -  // let's execute after video_image -  if (module_exists('video_image')) { -    if (variable_get('video_ffmpeg_helper_auto_thumbnail', 0)) { -      $upload_weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_image'")); -      db_query("UPDATE {system} SET weight=".($upload_weight+1)." WHERE name='video_ffmpeg_helper'"); -    } +  // let's execute after video_image and video_upload +  if (module_exists('video_image') && variable_get('video_image_auto_thumbnail', 0)) { +    $weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_image'")); +  } else { // video_image might be disabled.. execute after video_upload +    $weight = db_result(db_query("SELECT weight FROM {system} WHERE name='video_upload'"));    } -   +  // update the weight in the system table +  db_query("UPDATE {system} SET weight=".($weight+1)." WHERE name='video_ffmpeg_helper'"); +    $form['video_ffmpeg_helper_ffmpeg_path'] = array(      '#type' => 'textfield',      '#title' => t('FFmpeg executable path'),      '#description' => t('Set the full path to the ffmpeg executable here.'),      '#default_value' => variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg'),    ); -   -   + +    $form['video_ffmpeg_helper_auto_resolution'] = array(      '#type' => 'checkbox',      '#title' => t('Enable resolution helper'), -    '#description' => t('Use ffmpeg Helper to automaticcally get the resolution from the video.'), +    '#description' => t('Use ffmpeg Helper to automatically get the resolution from the video.'),      '#default_value' => variable_get('video_ffmpeg_helper_auto_resolution', false),    ); -   +    $form['video_ffmpeg_helper_auto_playtime'] = array(      '#type' => 'checkbox',      '#title' => t('Enable playtime helper'),      '#description' => t('Use ffmpeg Helper to automaticcally get the playtime from the video.'),      '#default_value' => variable_get('video_ffmpeg_helper_auto_playtime', false),    ); -   +    $form['autothumb'] = array(            '#type' => 'fieldset',            '#title' => t('Automatic video thumbnailing'),            '#collapsible' => TRUE,            '#collapsed' => TRUE        ); -  $form['autothumb']['video_ffmpeg_helper_auto_thumbnail'] = array( -      '#type' => 'checkbox', -      '#title' => t('Auto thumbnail for videos'), -      '#description' => t('If set up correctly, this will auto-generate a thumbnail for each video created.'), -      '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail', false), -    ); -  $form['autothumb']['video_ffmpeg_helper_auto_thumbnail_only'] = array( -      '#type' => 'checkbox', -      '#title' => t('Use auto-thumbnailer exclusively for video images'), -      '#description' => t('If checked, this will disable the file upload box for the user-supplied thumbnail.  Only check this if you have checked to be sure that auto-thumbnailing works.  Auto thumbnail must be selected for this to be enabled.'), -      '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail_only', false), -      '#disabled' => !variable_get('video_ffmpeg_helper_auto_thumbnail', false), -    );    $form['autothumb']['video_ffmpeg_helper_thumbnailer_options'] = array(        '#type' => 'textfield',        '#title' => t('Video thumbnailer options'), @@ -134,12 +158,6 @@ function video_ffmpeg_helper_admin_settings() {        '#description' => t('Time in seconds to seek into video before extracting the thumbnail'),        '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail_seek', 2),      ); -  $form['autothumb']['video_ffmpeg_helper_auto_thumbnail_debug'] = array( -      '#type' => 'checkbox', -      '#title' => t('Debug auto-thumbnail process'), -      '#default_value' => variable_get('video_ffmpeg_helper_auto_thumbnail_debug', false), -    ); -      // automatic video conversion settings    $form['autoconv'] = array(            '#type' => 'fieldset', @@ -147,10 +165,16 @@ function video_ffmpeg_helper_admin_settings() {            '#collapsible' => TRUE,            '#collapsed' => TRUE        ); +  $form['autoconv']['video_ffmpeg_helper_auto_cvr_cron'] = array( +      '#type' => 'checkbox', +      '#title' => t('Use drupal cron for autoconversion'), +      '#description' => t('Click this if you want to execute the video_scheduler.php from the standard drupal cron. If you want to use distributed encodings you might want to disable this.'), +      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_cron', true), +    );    $form['autoconv']['video_ffmpeg_helper_auto_conversion'] = array(        '#type' => 'checkbox',        '#title' => t('Auto conversion for videos'), -      '#description' => t('If set up correctly, this will auto-convert each uploaded video to the configured format.') . '<br />' . t("IMPORTANT: you will need the video_render.php correctly configured and run by cron. See README.txt for more informations."), +      '#description' => t('If set up correctly, this will auto-convert each uploaded video to the configured format.') . '<br />' . t("IMPORTANT: you will need the video_render.php correctly configured and run by cron. See README.txt in the video_ffmpeg_helper folder for more informations."),        '#default_value' => variable_get('video_ffmpeg_helper_auto_conversion', false),      );    $form['autoconv']['video_ffmpeg_helper_auto_cvr_width'] = array( @@ -164,24 +188,18 @@ function video_ffmpeg_helper_admin_settings() {    $form['autoconv']['video_ffmpeg_helper_auto_cvr_video_bitrate'] = array(        '#type' => 'textfield',        '#title' => t('Video bitrate'), -      '#description' => t('The video bitrate in kbit/s of the converted video.'), -      '#size' => 3, -      '#maxlength' => 4, -      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', 200), +      '#description' => t('The video bitrate in bit/s of the converted video.'), +      '#size' => 10, +      '#maxlength' => 10, +      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', 200000),      );    $form['autoconv']['video_ffmpeg_helper_auto_cvr_audio_bitrate'] = array(        '#type' => 'textfield',        '#title' => t('Audio bitrate'), -      '#description' => t('The audio bitrate in kbit/s of the converted video.'), -      '#size' => 3, -      '#maxlength' => 4, -      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', 64), -    ); -  $form['autoconv']['video_ffmpeg_helper_auto_cvr_busy_video_path'] = array( -      '#type' => 'textfield', -      '#title' => t('Busy video path'), -      '#description' => t('Provide the relative path to a video displayed when the video is being rendered.'), -      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_busy_video_path', 'busy.flv'), +      '#description' => t('The audio bitrate in bit/s of the converted video.'), +      '#size' => 10, +      '#maxlength' => 10, +      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', 64000),      );    $form['autoconv']['advanced'] = array(            '#type' => 'fieldset', @@ -197,8 +215,8 @@ function video_ffmpeg_helper_admin_settings() {        '<li>'.t('%convertfile (a newly created file to store the converted file)').        '<li>'.t('%size (video resolution of the converted file)').        '</ul>'. -      t('For further informations refer to the !ffmpegdoc', array('!ffmpegdoc' => l(t('Official FFMpeg documentation.'), 'http://ffmpeg.mplayerhq.hu/ffmpeg-doc.html', NULL, NULL, TRUE))), -      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate %convertfile'), +      t('For further informations refer to the !ffmpegdoc', array('!ffmpegdoc' => l(t('Official FFMpeg documentation.'), 'http://ffmpeg.mplayerhq.hu/ffmpeg-doc.html', array('fragment' => TRUE)))), +      '#default_value' => variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate -qscale 1 %convertfile'),      );    return system_settings_form($form);  } @@ -207,8 +225,10 @@ function video_ffmpeg_helper_admin_settings() {  /**   * Implementation of hook_form_alter()   */ -function video_ffmpeg_helper_form_alter($form_id, &$form) { +function video_ffmpeg_helper_form_alter(&$form, &$form_state, $form_id) { +  $node = $form['#node']; +      //print_r($form);    if($form_id == 'video_node_form') { @@ -216,19 +236,16 @@ function video_ffmpeg_helper_form_alter($form_id, &$form) {        _image_check_settings();        $form['#attributes'] = array("enctype" => "multipart/form-data"); -      if (variable_get('video_ffmpeg_helper_auto_thumbnail_only', false)) { -        // delete the video image parts -        $form['image'] = NULL; -      }      } -    if(variable_get('video_ffmpeg_helper_auto_resolution', false) || variable_get('video_ffmpeg_helper_auto_convert', false)) { -      $form['video']['videox'] = NULL; -      $form['video']['videoy'] = NULL; -    } -    if(variable_get('video_ffmpeg_helper_auto_playtime', false)) { -      $form['video']['playtime'] = NULL; +    if($node->vtype == 'upload' && user_access('bypass automatic video conversion') && variable_get('video_ffmpeg_helper_auto_conversion', false)) { +      $form['video']['video_ffmpeg_helper_convertion_bypass'] = array( +        '#type' => 'checkbox', +        '#title' => t('Bypass automatic video conversion'), +        '#description' => t('Check this if you want that your video is submitted as it is, without being converted.'), +        '#default_value' => $node->video_ffmpeg_helper_convertion_bypass, // for node previews +      );      }    } @@ -237,42 +254,80 @@ function video_ffmpeg_helper_form_alter($form_id, &$form) {  /**   * Implementation of hook_nodeapi() + * + * NOTE: video_ffmpeg nodeapi is executed after video_player rendering   */  function video_ffmpeg_helper_nodeapi(&$node, $op, $teaser) { -  if($node->type == 'video') { -     +  if($node->type == 'video' && $node->vtype == 'upload') {      switch ($op) { -      case 'load':  -        ; // for future uses -        break; -         -      case 'submit': +      case 'load': +      // let's check if we have a valid encoded video +        if(isset($node->serial_data['video_encoded_fid']) && +          is_numeric($node->serial_data['video_encoded_fid']) && +          $node->serial_data['video_encoded_fid'] > 0) { +          // this video have an encoded version. let's use it insted of the original one. We can safely do this as video_ffmpeg_helper will be scheduled by Drupal after video and video_upload modules +          $output = array(); +          $file = _video_upload_get_file($node->serial_data['video_encoded_fid']); +          $output['current_video_rendered_file'] = $file; +          $output['vidfile'] = file_create_url($file->filepath); +          // set the filesize +          $output['size'] = $file->filesize; +           +          return $output; +        } +        //print $node->serial_data['video_encoded_fid']; die; +          if(variable_get('video_ffmpeg_helper_auto_resolution', false) || variable_get('video_ffmpeg_helper_auto_playtime', false)) {            _video_ffmpeg_helper_get_video_info($node);          } -                  break; -         -      case 'insert': + +      case 'submit': +        break; + +      case 'update': +        /* delete the already existing batch script, we'll recreate it below */          if(variable_get('video_ffmpeg_helper_auto_conversion', false)) { +          db_query('DELETE FROM {video_rendering} WHERE vid = %d AND nid = %d', $node->vid, $node->nid); +        } +      /* FALLTHROUGH */ +      case 'insert': +        if(variable_get('video_ffmpeg_helper_auto_conversion', false) && $node->new_video_upload_file_fid > 0 && !$node->video_ffmpeg_helper_convertion_bypass) {            // add rendering job to queue            _video_ffmpeg_helper_add_rendering($node);          } -         +          break; -         +        case 'prepare':          ; // for future uses        break;        case 'view': -        ; // for future uses +        if($teaser == FALSE) { +          if(_video_ffmpeg_helper_is_being_processed($node)) { +            // if the video is still being processed we display a "rendering in progress" message +            $node->content['video_player']['#value'] = theme('video_ffmpeg_helper_inprogress', $node); +          } +          else if($node->serial_data['video_encoded_fid'] == -1) { // conversion failed +            $node->content['video_player']['#value'] = theme('video_ffmpeg_helper_encoding_failed', $node); +          } +        } +        //print_r($node); die;          break; +      case 'alter': +        ; // for future uses +      break; +        case 'delete':          db_query('DELETE FROM {video_rendering} WHERE vid = %d AND nid = %d', $node->vid, $node->nid); +        if($node->serial_data['video_encoded_fid'] > 0) { +          $file = _video_upload_get_file($node->serial_data['video_encoded_fid']); +          _video_upload_delete_file($file); +        }          break; -         +      }    }  } @@ -282,14 +337,29 @@ function video_ffmpeg_helper_nodeapi(&$node, $op, $teaser) {   * Add a video conversion rendering process to the queue  */  function _video_ffmpeg_helper_add_rendering(&$node) { -  $file = $_SESSION['video_upload_file_stored']->filepath; +  $file = _video_upload_get_file($node->new_video_upload_file_fid);    //print_r($node); die; -  db_query('INSERT INTO {video_rendering} (vid, nid, origfile, pid, status, started, completed) VALUES (%d, %d, "%s", %d, %d, %d, %d)', $node->vid, $node->nid, $file, 0, VIDEO_RENDERING_PENDING, 0, 0); +  db_query('INSERT INTO {video_rendering} (vid, nid, origfile, pid, status, started, completed) VALUES (%d, %d, "%s", %d, %d, %d, %d)', $node->vid, $node->nid, $file->filepath, 0, VIDEO_RENDERING_PENDING, 0, 0); + +  drupal_set_message(t('Video submission queued for processing. Please wait: our servers are preparing your video for web displaying.'));    // let's add the rendering in progress video    $node->vidfile = variable_get('video_ffmpeg_helper_auto_cvr_busy_video_path', 'busy.flv');    db_query('UPDATE {video} SET vidfile = "%s" WHERE nid=%d AND vid=%d', $node->vidfile, $node->nid, $node->vid); -   + +} + + +/** + * Returns true if the video is being encoded or queeded +*/ +function _video_ffmpeg_helper_is_being_processed($node) { +  $result = db_query("SELECT status FROM {video_rendering} WHERE vid = %d AND nid = %d", $node->vid, $node->nid); +  $status = db_result($result); +  if($status == VIDEO_RENDERING_PENDING || $status == VIDEO_RENDERING_ACTIVE) { // video is still being converted +    return TRUE; +  } +  return FALSE;  } @@ -297,62 +367,94 @@ function _video_ffmpeg_helper_add_rendering(&$node) {  /**   * Get some informations from the video file  */ -function _video_ffmpeg_helper_get_video_info(&$node) { +function _video_ffmpeg_helper_get_video_info(&$node, $value=null) { +  static $ffmpeg_info; + +  if (isset($value)) { +    $ffmpeg_info[$node->nid] = $value; +    return; +  } +   +  $fileobj = $node->new_video_upload_file ? $node->new_video_upload_file : _video_upload_get_file($node->new_video_upload_file_fid); + +  // check if we have some info in the cache for the given node +  if(isset($ffmpeg_info[$fileobj->filename])) { +    return $ffmpeg_info[$fileobj->filename]; +  } +      // escape file name for safety -  $file = escapeshellarg($_SESSION['video_upload_file']->filepath); +  $file = escapeshellarg($fileobj->filepath);    // create the full command to execute    $command = variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg') . ' -i ' . $file; -   -  drupal_set_message('executing' . $command); -   +    //execute the command    ob_start();    passthru($command." 2>&1", $command_return);    $command_output = ob_get_contents();    ob_end_clean(); -  // print $command_output; +  // cache the result for further calls +  $ffmpeg_info[$node->nid] = $command_output; +  return $command_output; +} + + +/** + * Return the video resolution + */ +function _video_ffmpeg_helper_auto_resolution(&$node) { +  if(!$node->new_video_upload_file && !$node->new_video_upload_file_fid) { // no new files uploaded. skipping auto resolution process +    return null; +  } +    if(variable_get('video_ffmpeg_helper_auto_resolution', false)) { + +    // call ffmpeg -i +    $ffmpeg_output = _video_ffmpeg_helper_get_video_info($node); +      // get resolution -    $pattern = '/[0-9]{2,4}x[0-9]{2,4}/'; -    preg_match_all($pattern, $command_output, $matches, PREG_PATTERN_ORDER); -    $resolution = $matches[0][0]; -    $xy = explode("x", $resolution); -     -    // store resolution information to the node object -    $node->videox = $xy[0]; -    $node->videoy = $xy[1]; +    $pattern = '/Video: .*, ([0-9]{2,4}x[0-9]{2,4})/'; +    preg_match_all($pattern, $ffmpeg_output, $matches, PREG_PATTERN_ORDER); +    $resolution = $matches[1][0]; + +    return explode("x", $resolution);    } -   -   +  return null; +} + + +/** + * Return the playtime seconds of a video +*/ +function _video_ffmpeg_helper_auto_playtime(&$node) { +    if(variable_get('video_ffmpeg_helper_auto_playtime', false)) { -    // get playtime -    $pattern = '/[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]/'; -    preg_match_all($pattern, $command_output, $matches, PREG_PATTERN_ORDER); -    $playtime = $matches[0][0]; -    // ffmpge return lenght as 00:00:31.1 Let's get playtime from that -    $hmsmm = explode(":", $playtime); +    // call ffmpeg -i +    $ffmpeg_output = _video_ffmpeg_helper_get_video_info($node); +    // get playtime +    $pattern = '/Duration: ([0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9])/'; +    preg_match_all($pattern, $ffmpeg_output, $matches, PREG_PATTERN_ORDER); +    $playtime = $matches[1][0]; + +    // ffmpeg return lenght as 00:00:31.1 Let's get playtime from that +    $hmsmm = explode(":", $playtime); +      $tmp = explode(".", $hmsmm[2]);      $seconds = $tmp[0]; -     +      $hours = $hmsmm[0];      $minutes = $hmsmm[1]; -     -    $node->playtime_seconds = $seconds + ($hours * 3600) + ($minutes * 60); +    return $seconds + ($hours * 3600) + ($minutes * 60);    } -   -  //print_r($node); die; -    } - - -/* Generates a thumbnail from the video file +/** + * Generates a thumbnail from the video file   *   * @param $node   *   object with node information @@ -361,54 +463,103 @@ function _video_ffmpeg_helper_get_video_info(&$node) {   *   a drupal file object   */  function _video_ffmpeg_helper_auto_thumbnail(&$node) { -  if(empty($_SESSION['video_upload_file']) || -      !$_SESSION['video_upload_file']->newfile || -      $node->iid || $_SESSION['video_upload_file']->iid || -      $_SESSION['video_upload_file']->thumbnailed) { -    if (variable_get('video_image_auto_thumbnail_debug', false)) { -      if (empty($_SESSION['video_upload_file'])) -        drupal_set_message(t('no video has been uploaded: make sure that video_image weight is greater than video_upload weight; make sure that the video file is not too large to be uploaded.')); -    } -    return null; +  if (!$node->new_video_upload_file ||  +      ($node->new_video_upload_file && count($_POST) && $_POST['new_video_upload_file_fid'])) { +    // we have already thumbnailed this new upload file +    return NULL;    } -  $debug = variable_get('video_image_auto_thumbnail_debug', false); -  $videofile = escapeshellarg($_SESSION['video_upload_file']->filepath); +  if (!$node->new_video_upload_file && $node->current_video_upload_file_fid) { // no new files uploaded. skipping thumnailing stuff +    _video_image_thumbnail_debug(t('No new files to thumbnail')); +    return NULL; +  } +  // gets the newly uploaded file object +  $uploaded_file = $node->new_video_upload_file; + +  // are we debugging? +  // escape the filename for safety +  $videofile = escapeshellarg($uploaded_file->filepath); +  // let's create a temp filename into the drupal temp directory    $thumbfile = tempnam(file_directory_temp(), 'tnail-thumb'); -  $seek = variable_get('video_image_auto_thumbnail_seek', 2); +  // get ffmpeg configurations +  $seek = variable_get('video_ffmpeg_helper_auto_thumbnail_seek', 2);    $tnail = variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg');    $options = preg_replace(array('/%videofile/', '/%thumbfile/', '/%seek/'), array($videofile, $thumbfile, $seek), variable_get('video_image_thumbnailer_options', '-i %videofile -an -y -f mjpeg -ss %seek -vframes 1 %thumbfile')); +  // executes the command    $command = "$tnail $options";    ob_start();    passthru($command." 2>&1", $tnail_return);    $tnail_output = ob_get_contents();    ob_end_clean(); +  _video_ffmpeg_helper_get_video_info($node, $tnail_output); -  if ($debug) { -    drupal_set_message(t('Thumbnailer command: ').$command); -    drupal_set_message(t('Thumbnailer output: ')."<pre>\n$tnail_output\n</pre>"); -  } +  _video_image_thumbnail_debug(t('Thumbnailer command: ').$command); +  _video_image_thumbnail_debug(t('Thumbnailer output: ')."<pre>\n$tnail_output\n</pre>");    if (!file_exists($thumbfile)) { -    drupal_set_message(t('video_image_auto_thumbnail: file %file does not exist', array('%file' => $thumbfile)), 'error'); +    $error_param = array( +      '%file' => $thumbfile, +      '%cmd' => $command, +      '%out' => $tnail_output, +    ); +    $error_msg = t("error generating thumbnail for video: generated file %file does not exist.<br />Command Executed:<br />%cmd<br />Command Output:<br />%out", $error_param); +    // let's log this +    watchdog('video_ffmpeg_helper',$error_msg); +    return false;    }    $file = array( -      'filename' => $_SESSION['video_upload_file']->filename . ".video-thumb.jpg", +      'filename' => $uploaded_file->filename . ".video-thumb.jpg",        'filemime' => 'image/jpeg',        'filesize' => filesize($thumbfile),        'filepath' => $thumbfile,        'nid' => $node->nid,        ); -  $_SESSION['video_upload_file']->thumbnailed = TRUE; -  if ($debug) { -    if ($tnail_return) { -      drupal_set_message(t('Failed to thumbnail video')); -    } else { -      drupal_set_message(t('Successfully thumbnailed video')); -    } +       +  if ($tnail_return) { +    _video_image_thumbnail_debug(t('Failed to thumbnail video')); +    return $false;    } +  _video_image_thumbnail_debug(t('Successfully thumbnailed video'));    return (object)$file;  } +function _video_ffmpeg_helper_check_exe_path($path=NULL) { +  if (!$path) { +    $path = variable_get('video_ffmpeg_helper_ffmpeg_path', '/usr/bin/ffmpeg'); +  } +  if (function_exists('is_executable')) { +    $test = 'is_executable'; +  } else { +    $test = 'file_exists'; +  } +  return $test($path); +} + +/** + * Displays a "encoding in progress message" +*/ +function theme_video_ffmpeg_helper_inprogress($node) { +  return '<div class="video-ffmpeg-helper-inprogress">'. t('This video is currently being processed. Please wait.') . '</div>'; +} + +/** + * Display an "encoding failed" message" +*/ +function theme_video_ffmpeg_helper_encoding_failed($node) { +  return '<div class="video-ffmpeg-helper-encoding-failed">'. t('The video conversion process has failed. You might want to submit a simpler video format like <em>mpeg</em> or <em>divx avi</em>.<br />If the problem persists please contact website administrators.') . '</div>'; +} +/** + * Implementation of hook_theme(). + */ +function video_ffmpeg_helper_theme() { +  return array( +    'video_ffmpeg_helper_encoding_failed' => array( +      'arguments' => array('node' => NULL), +    ), +    'video_ffmpeg_helper_inprogress' => array( +      'arguments' => array('node' => NULL), +    ), +  ); +} diff --git a/plugins/video_ffmpeg_helper/video_render.php b/plugins/video_ffmpeg_helper/video_render.php index a1747a3..bba9220 100644 --- a/plugins/video_ffmpeg_helper/video_render.php +++ b/plugins/video_ffmpeg_helper/video_render.php @@ -1,12 +1,18 @@  <?php -// $Id$  /**   * @file   * 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" + * If you are not using sites/default/settings.php as your settings file,  + * add an optional parameter for the drupal site url: + * "php video_render.php nid vid http://example.com/" or + * "php video_render.php nid vid http://example.org/drupal/"   *   * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo   */ @@ -19,7 +25,7 @@ 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');  +define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video');  // number of conversion jobs active at the same time  define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); @@ -36,12 +42,18 @@ define('VIDEO_RENDERING_NICE', 'nice -n 19');  /**   * Define some constants  */ -define('VIDEO_RENDERING_PENDING', 0); +define('VIDEO_RENDERING_PENDING', 1);  define('VIDEO_RENDERING_ACTIVE', 5);  define('VIDEO_RENDERING_COMPLETE', 10); +define('VIDEO_RENDERING_FAILED', 20); +if (isset($_SERVER['argv'][3])) { +  $url = parse_url($_SERVER['argv'][3]); +  $_SERVER['SCRIPT_NAME'] = $url['path']; +  $_SERVER['HTTP_HOST'] = $url['host']; +} -include_once './includes/bootstrap.inc'; +module_load_include('/includes/bootstrap.inc', 'video_render', 'includes/bootstrap');  // disable error reporting for bootstrap process  error_reporting(E_ERROR);  // let's bootstrap: we will be able to use drupal apis @@ -52,8 +64,8 @@ error_reporting(E_ALL);  // allow execution only from the command line!  if(empty($_SERVER['REQUEST_METHOD'])) { -  if($_SERVER['argc'] != 3) { // check for command line arguments -    watchdog('video_render', t('Incorrect parameters to the video_render.php script.', WATCHDOG_ERROR)); +  if($_SERVER['argc'] < 3) { // check for command line arguments +    watchdog('video_render', 'Incorrect parameters to the video_render.php script.', WATCHDOG_ERROR);      print t('Incorrect parameters');    }    else { @@ -69,29 +81,36 @@ print("\n");  function video_render_main() { +  // get parameters passed from command line +  $nid = $_SERVER['argv'][1]; +  $vid = $_SERVER['argv'][2]; +    // 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); +  _video_render_job_change_status($nid, $vid, VIDEO_RENDERING_ACTIVE); +  // load the job object +  $job = _video_render_load_job($nid, $vid, VIDEO_RENDERING_ACTIVE);    if($job == NULL) { -    watchdog('video_render', t('video_render.php has been called with an invalid job resource. exiting.')); +    watchdog('video_render', 'video_render.php has been called with an invalid job resource. exiting.');      die;    }    $command = _video_render_get_command($job); -   -  //print('executing ' . $command); -  watchdog('video_render', t('executing: ') . $command); -   + +  //print('executing ' . $command); die; +  watchdog('video_render', 'executing: ' . $command); +    //execute the command    ob_start();    passthru($command." 2>&1", $command_return);    $command_output = ob_get_contents();    ob_end_clean(); -   +    //print $command_output; -   -  if (!file_exists($job->convfile)) { -    watchdog('video_render', t('video conversion failed. ffmpeg reported the following output: ' . $command_output, WATCHDOG_ERROR)); + +  if (!file_exists($job->convfile) || !filesize($job->convfile)) { +    watchdog('video_render', 'video conversion failed. ffmpeg reported the following output: ' . $command_output, WATCHDOG_ERROR); +    _video_render_set_video_encoded_fid($job->nid, $job->vid, -1); +    _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_FAILED);    }    else {      // move the video to the definitive location @@ -106,31 +125,65 @@ function video_render_main() {      $file = ((object) $file);      //print_r($file); -    $dest_dir = variable_get('video_upload_default_path', 'videos') .'/'; +    //$dest_dir = variable_get('video_upload_default_path', 'videos') .'/'; +    // the above no more works as token supports - use dirname +    $dest_dir = dirname($job->origfile) . '/'; -    if (file_copy($file, file_directory_path() . '/' . $dest_dir)) { +    if (file_copy($file, $dest_dir)) {        $file->fid = db_next_id('{files}_fid');        //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("INSERT INTO {upload} (fid, vid, list, description) VALUES (%d, %d, %d, '%s')", $file->fid, $job->vid, $file->list, $file->description); + +      // update the video table        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); + +      // update the video_encoded_fid in video serial data +      _video_render_set_video_encoded_fid($job->nid, $job->vid, $file->fid);        _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_COMPLETE); -      // delete the vile +      watchdog('video_render', 'successfully converted %orig to %dest', array('%orig' => $job->origfile, '%dest' => $file->filepath)); + +      // delete the temp file        unlink($job->convfile);      }      else { -      watchdog('video_scheduler', t('error moving video to the final directory. Check folder permissions.'), WATCHDOG_ERROR); +      // get the username of the process owner +      $ownerarray = posix_getpwuid(posix_getuid()); +      $owner=$ownerarray['name']; +      // get the username of the destination folder owner +      $fownerarray = posix_getpwuid(fileowner($dest_dir)); +      $fowner=$fownerarray['name']; +      // get destination folder permissions +      $perms = substr(sprintf('%o', fileperms($dest_dir)), -4); +      watchdog('video_render', 'error moving video %vid_file with nid = %nid to %dir the final directory. Check folder permissions.<br />The script was run by %uname .<br />The folder owner is %fowner .<br />The folder permissions are %perms .', array('%vid_file' => $job->origfile, '%nid' => $job->nid, '%dir' => $dest_dir, '%uname' => $owner, '%fowner' => $fowner, '%perms' => $perms), WATCHDOG_ERROR); +       +      _video_render_set_video_encoded_fid($job->nid, $job->vid, -1); +      _video_render_job_change_status($job->nid, $job->vid, VIDEO_RENDERING_FAILED);      }    }  }  /** + * Set the video_encoded_fid in the video table + * We store -1 as video_encoded_fid if the encoding failed +*/ +function _video_render_set_video_encoded_fid($nid, $vid, $encoded_fid) { +  db_lock_table('video'); +  $node = db_fetch_object(db_query("SELECT serialized_data FROM {video} WHERE nid = %d AND vid = %d", $nid, $vid)); +  $node->serial_data = unserialize($node->serialized_data); +  $node->serial_data['video_encoded_fid'] = $encoded_fid; +  $node->serialized_data = serialize($node->serial_data); +  db_query("UPDATE {video} SET serialized_data = '%s' WHERE nid = %d AND vid = %d", $node->serialized_data, $nid, $vid); +  db_unlock_tables(); +} + + + +/**   * Get a string cointaining the command to be executed including options  */  function _video_render_get_command(&$job) { @@ -140,14 +193,14 @@ function _video_render_get_command(&$job) {    $audiobitrate = variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', 64);    $videobitrate = variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', 200);    $size = _video_render_get_size($job); -   +    $converter = VIDEO_RENDERING_FFMPEG_PATH; -  $options = preg_replace(array('/%videofile/', '/%convertfile/', '/%audiobitrate/', '/%size/', '/%videobitrate/'), array($videofile, $convfile, $audiobitrate, $size, $videobitrate), variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate %convertfile')); -   +  $options = preg_replace(array('/%videofile/', '/%convertfile/', '/%audiobitrate/', '/%size/', '/%videobitrate/'), array($videofile, $convfile, $audiobitrate, $size, $videobitrate), variable_get('video_ffmpeg_helper_auto_cvr_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate -qscale 1 %convertfile')); +    // set to the converted file output    $job->convfile = $convfile; -   +    return VIDEO_RENDERING_NICE . " $converter $options";  } @@ -161,10 +214,17 @@ function _video_render_get_size(&$job) {    $def_width = variable_get('video_ffmpeg_helper_auto_cvr_width', 400);    $height = $def_width * ($job->videoy / $job->videox); // do you remember proportions?? :-) -   + + +  $height = round($height); +  // add one if odd +  if($height % 2) { +    $height++; +  } +    $job->calculatedx = $def_width;    $job->calculatedy = $height; -   +    return $def_width . 'x' . $height;  } @@ -174,7 +234,7 @@ function _video_render_get_size(&$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);  } diff --git a/plugins/video_ffmpeg_helper/video_scheduler.php b/plugins/video_ffmpeg_helper/video_scheduler.php index 4803dc2..7faf446 100644 --- a/plugins/video_ffmpeg_helper/video_scheduler.php +++ b/plugins/video_ffmpeg_helper/video_scheduler.php @@ -1,14 +1,20 @@  <?php -// $Id$  /**   * @file   * Implement video rendering scheduling. + * If you are not using sites/default/settings.php as your settings file,   + * add an optional parameter for the drupal site url: + * "php video_scheduler.php http://example.com/" or + * "php video_scheduler.php http://example.org/drupal/"   *   * @author Fabio Varesano <fvaresano at yahoo dot it> + * porting to Drupal 6 + * @author Heshan Wanigasooriya <heshan at heidisoft.com><heshanmw@gmail.com> + * @todo   */ -  -  + +  /**   * video_scheduler.php configuration  */ @@ -18,7 +24,7 @@ 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');  +define('VIDEO_RENDERING_TEMP_PATH', '/tmp/video');  // number of conversion jobs active at the same time  define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5); @@ -31,12 +37,18 @@ define('VIDEO_RENDERING_FFMPEG_INSTANCES', 5);  /**   * Define some constants  */ -define('VIDEO_RENDERING_PENDING', 0); +define('VIDEO_RENDERING_PENDING', 1);  define('VIDEO_RENDERING_ACTIVE', 5);  define('VIDEO_RENDERING_COMPLETE', 10); +define('VIDEO_RENDERING_FAILED', 20); +if (isset($_SERVER['argv'][1])) { +  $url = parse_url($_SERVER['argv'][1]); +  $_SERVER['SCRIPT_NAME'] = $url['path']; +  $_SERVER['HTTP_HOST'] = $url['host']; +} -include_once './includes/bootstrap.inc'; +module_load_include('/includes/bootstrap.inc', 'video_scheduler', 'includes/bootstrap');  // disable error reporting for bootstrap process  error_reporting(E_ERROR);  // let's bootstrap: we will be able to use drupal apis @@ -60,14 +72,14 @@ else {   * 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.')); +    watchdog('video_scheduler', 'no video conversion jobs to schedule.');    }  } @@ -76,7 +88,8 @@ function video_scheduler_main() {   * Starts rendering for a job  */  function video_scheduler_start($job) { -  exec("php video_render.php $job->nid $job->vid > /dev/null &"); +  $url = (isset($_SERVER['argv'][1])) ? escapeshellarg($_SERVER['argv'][1]) : ''; +  exec("php video_render.php $job->nid $job->vid $url > /dev/null &");  } @@ -88,9 +101,10 @@ function video_scheduler_start($job) {  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 -   + +  // TODO: use db_query_range    $jobs = array();    $i = 0;    $count = db_num_rows($result); @@ -98,7 +112,7 @@ function video_scheduler_select() {      $jobs[] = db_fetch_object($result);      $i++;    } -   +    return $jobs;  }  | 
