*/
/**
* Define some constants
*/
define('VIDEO_RENDERING_PENGING', 0);
define('VIDEO_RENDERING_ACTIVE', 5);
define('VIDEO_RENDERING_COMPLETE', 10);
/**
* Implementation of hook_help().
*/
function video_ffmpeg_helper_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('Enable thumbnails support for video module.');
}
}
/**
* Implementation of hook_menu()
*/
function video_ffmpeg_helper_menu($may_cache) {
$items = array();
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'),
'type' => MENU_NORMAL_ITEM,
);
}
return $items;
}
/**
* 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'));
}
if (!is_numeric($form_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'));
}
}
}
/**
* 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'");
}
}
$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.'),
'#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'),
'#description' => t('Provide the options for the thumbnailer. Available argument values are: ').'
- '.t('%videofile (the video file to thumbnail)').'
- '.t('%thumbfile (a newly created temporary file to overwrite with the thumbnail)').'
- '.t('%seek (seconds to seek into video before extracting image).').'
'.t('Only the first two are mandatory. For example, older versions of ffmpeg should use something like: !old While newer versions should use something like: !new', array('!old' => "-i %videofile -y -an -f mjpeg -ss %seek -t 0.001 %thumbfile
", '!new' => '-i %videofile -an -y -f mjpeg -ss %seek -vframes 1 %thumbfile
')),
'#default_value' => variable_get('video_ffmpeg_helper_thumbnailer_options', '-i %videofile -an -y -f mjpeg -ss %seek -vframes 1 %thumbfile'),
);
$form['autothumb']['video_ffmpeg_helper_auto_thumbnail_seek'] = array(
'#type' => 'textfield',
'#title' => t('Video seek offset for thumbnail'),
'#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',
'#title' => t('Automatic video conversion'),
'#collapsible' => TRUE,
'#collapsed' => 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.') . '
' . t("IMPORTANT: you will need the video_render.php correctly configured and run by cron. See README.txt for more informations."),
'#default_value' => variable_get('video_ffmpeg_helper_auto_conversion', false),
);
$form['autoconv']['video_ffmpeg_helper_auto_converter_width'] = array(
'#type' => 'textfield',
'#title' => t('Video rendering width'),
'#description' => t('The width of the converted video. The height will be automatically calculated to maintain aspect ratio.'),
'#size' => 3,
'#maxlength' => 3,
'#default_value' => variable_get('video_ffmpeg_helper_auto_converter_width', 400),
);
$form['autoconv']['video_ffmpeg_helper_auto_converter_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_converter_video_bitrate', 200),
);
$form['autoconv']['video_ffmpeg_helper_auto_converter_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_converter_audio_bitrate', 64),
);
$form['autoconv']['video_ffmpeg_helper_auto_converter_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_converter_busy_video_path', 'busy.flv'),
);
$form['autoconv']['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE
);
$form['autoconv']['advanced']['video_ffmpeg_helper_auto_converter_options'] = array(
'#type' => 'textfield',
'#title' => t('Video converter options'),
'#description' => t('Provide the ffmpeg options to configure the video conversion. Available argument values are: ').''.
'- '.t('%videofile (the video file to convert)').
'
- '.t('%convertfile (a newly created file to store the converted file)').
'
- '.t('%size (video resolution of the converted file)').
'
'.
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_converter_options', '-y -i %videofile -f flv -ar 22050 -ab %audiobitrate -s %size -b %videobitrate %convertfile'),
);
return system_settings_form($form);
}
/**
* Implementation of hook_form_alter()
*/
function video_ffmpeg_helper_form_alter($form_id, &$form) {
//print_r($form);
if($form_id == 'video_node_form') {
if (function_exists('_image_check_settings')) {
_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;
}
}
}
/**
* Implementation of hook_nodeapi()
*/
function video_ffmpeg_helper_nodeapi(&$node, $op, $teaser) {
if($node->type == 'video') {
switch ($op) {
case 'load':
; // for future uses
break;
case 'submit':
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':
if(variable_get('video_ffmpeg_helper_auto_conversion', false)) {
// add rendering job to queue
_video_ffmpeg_helper_add_rendering($node);
}
break;
case 'prepare':
; // for future uses
break;
case 'view':
; // for future uses
break;
case 'delete':
db_query('DELETE FROM {video_rendering} WHERE vid = %d AND nid = %d', $node->vid, $node->nid);
break;
}
}
}
/**
* Add a video conversion rendering process to the queue
*/
function _video_ffmpeg_helper_add_rendering(&$node) {
$file = $_SESSION['video_upload_file_stored']->filepath;
//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_PENGING, 0, 0);
// let's add the rendering in progress video
$node->vidfile = variable_get('video_ffmpeg_helper_auto_converter_busy_video_path', 'busy.flv');
db_query('UPDATE {video} SET vidfile = "%s" WHERE nid=%d AND vid=%d', $node->vidfile, $node->nid, $node->vid);
}
/**
* Get some informations from the video file
*/
function _video_ffmpeg_helper_get_video_info(&$node) {
// escape file name for safety
$file = escapeshellarg($_SESSION['video_upload_file']->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;
if(variable_get('video_ffmpeg_helper_auto_resolution', false)) {
// get resolution
$pattern = '/[0-9]{3}x[0-9]{3}/';
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];
}
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);
$tmp = explode(".", $hmsmm[2]);
$seconds = $tmp[0];
$hours = $hmsmm[0];
$minutes = $hmsmm[1];
$node->playtime_seconds = $seconds + ($hours * 3600) + ($minutes * 60);
}
//print_r($node); die;
}
/* Generates a thumbnail from the video file
*
* @param $node
* object with node information
*
* @return
* 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;
}
$debug = variable_get('video_image_auto_thumbnail_debug', false);
$videofile = escapeshellarg($_SESSION['video_upload_file']->filepath);
$thumbfile = tempnam(file_directory_temp(), 'tnail-thumb');
$seek = variable_get('video_image_auto_thumbnail_seek', 2);
$tnail = variable_get('video_image_thumbnailer_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'));
$command = "$tnail $options";
ob_start();
passthru($command." 2>&1", $tnail_return);
$tnail_output = ob_get_contents();
ob_end_clean();
if ($debug) {
drupal_set_message(t('Thumbnailer command: ').$command);
drupal_set_message(t('Thumbnailer output: ')."\n$tnail_output\n
");
}
if (!file_exists($thumbfile)) {
drupal_set_message(t('video_image_auto_thumbnail: file %file does not exist', array('%file' => $thumbfile)), 'error');
}
$file = array(
'filename' => $_SESSION['video_upload_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'));
}
}
return (object)$file;
}