params['audiobitrate'] = variable_get('video_ffmpeg_helper_auto_cvr_audio_bitrate', $this->audio_bitrate); $this->params['videobitrate'] = variable_get('video_ffmpeg_helper_auto_cvr_video_bitrate', $this->video_bitrate); //@todo: move this to the actual widget and save in video_files table. $this->params['size'] = variable_get('video_ffmpeg_width', $this->video_width) . 'x' . variable_get('video_ffmpeg_height', $this->video_height); $this->params['ffmpeg'] = variable_get('video_ffmpeg_path', $this->ffmpeg); $this->nice = variable_get('video_ffmpeg_nice_enable', false) ? 'nice -n 19 ' : ''; $this->params['videoext'] = variable_get('video_ffmpeg_ext', $this->video_ext); $this->params['enable_faststart'] = variable_get('video_ffmpeg_enable_faststart', 0); $this->params['faststart_cmd'] = variable_get('video_ffmpeg_faststart_cmd', '/usr/bin/qt-faststart'); $use_version = 'php5'; // check if php5 is ok if ($use_version == 'php5' && version_compare(PHP_VERSION, '5.0.0', '<')) { $use_version = 'php4'; } module_load_include('php', 'video', 'libraries/phpvideotoolkit/phpvideotoolkit.' . $use_version); $this->toolkit = new PHPVideoToolkit($this->params['ffmpeg'], file_directory_temp() . '/'); } // Returns an array of available encoding & decoding codecs public function get_codecs() { $info = $this->toolkit->getFFmpegInfo(false); $available_codecs = $info['codecs']; $codecs = array('decode' => array(), 'encode' => array()); foreach ($available_codecs as $key => $value) { $codecs['encode'][$key] = array(); $codecs['decode'][$key] = array(); foreach ($value as $codec_key => $codec) { if ($codec['encode']) { $codecs['encode'][$key][$codec_key] = $codec['fullname']; } if ($codec['decode']) { $codecs['decode'][$key][$codec_key] = $codec['fullname']; } } } return $codecs; } public function generate_thumbnails($video) { global $user; // Setup our thmbnail path. $video_thumb_path = variable_get('video_thumb_path', 'videos/thumbnails'); // Get the file system directory. $schema_thumb_path = file_default_scheme() . '://' . $video_thumb_path . '/' . $video['fid']; file_prepare_directory($schema_thumb_path, FILE_CREATE_DIRECTORY); // Total thumbs to generate $total_thumbs = variable_get('video_thumbs', 5); $videofile = file_load($video['fid']); //get the actual video file path from the stream wrappers $videopath = drupal_realpath($videofile->uri); //get the playtime from the current transcoder $duration = $this->get_playtime($videopath); $files = NULL; for ($i = 1; $i <= $total_thumbs; $i++) { $seek = ($duration / $total_thumbs) * $i - 1; //adding minus one to prevent seek times equaling the last second of the video $filename = file_munge_filename("video-thumb-for-" . $video['fid'] . "-$i.jpg", '', TRUE); $thumbfile = $schema_thumb_path . '/' . $filename; //skip files already exists, this will save ffmpeg traffic if (!is_file(drupal_realpath($thumbfile))) { $result = $this->toolkit->setInputFile($videopath); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $this->toolkit->extractFrame($seek); $result = $this->toolkit->setOutput(drupal_realpath($schema_thumb_path) . '/', $filename, PHPVideoToolkit::OVERWRITE_EXISTING); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $result = $this->toolkit->execute(false, true); if ($result !== PHPVideoToolkit::RESULT_OK) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } if (!file_exists(drupal_realpath($thumbfile))) { $error_param = array('%file' => $thumbfile); $error_msg = t("Error generating thumbnail for video: generated file %file does not exist.", $error_param); // Log the error message. watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); continue; } } // Begin building the file object. // @TODO : use file_munge_filename() $file = new stdClass(); $file->uid = $user->uid; $file->status = 0; $file->filename = trim($filename); $file->uri = $thumbfile; $file->filemime = file_get_mimetype($filename); $file->filesize = filesize(drupal_realpath($thumbfile)); $file->timestamp = time(); $files[] = $file; } return $files; } public function convert_video($video) { // This will update our current video status to active. // $this->change_status($video->vid, VIDEO_RENDERING_ACTIVE); // get the paths so tokens will compatible with this // @todo : add best method to get existing file path and add converted there $target = str_replace('original', '', drupal_dirname($video->uri)); $converted_base_dir = $target . 'converted/' . $video->fid; if (!file_prepare_directory($converted_base_dir, FILE_CREATE_DIRECTORY)) { watchdog('transcoder', 'Video conversion failed. Could not create the directory: ' . $converted_base_dir, array(), WATCHDOG_ERROR); return FALSE; } //get the actual video file path from the stream wrappers $original_video_path = drupal_realpath($video->uri); // process presets $presets = $video->presets; $converted_files = array(); foreach ($presets as $name => $preset) { $settings = $preset['settings']; // override with preset settings if (isset($settings['width']) && !empty($settings['width']) && isset($settings['height']) && !empty($settings['height']) && variable_get('video_use_preset_wxh', FALSE)) { $video->dimensions = $settings['width'] . 'x' . $settings['height']; } $converted_filename = file_munge_filename(str_replace(' ', '_', pathinfo($original_video_path, PATHINFO_FILENAME)) . '.' . $settings['video_extension'], $settings['video_extension']); $converted = $converted_base_dir . '/' . $converted_filename; //get the actual video file path from the stream wrappers $converted_video_path = drupal_realpath($converted); $dimensions = $this->dimensions($video); $dimension = explode('x', $dimensions); $video_info = $this->get_video_info($original_video_path); if ($this->params['enable_faststart'] && in_array($settings['video_extension'], array('mov', 'mp4'))) { $ffmpeg_output = file_directory_temp() . '/' . basename($converted_video_path); } else { $ffmpeg_output = $converted_video_path; } $result = $this->toolkit->setInputFile($original_video_path); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } if (!empty($settings['max_frame_rate'])) { $result = $this->toolkit->setVideoFrameRate($settings['max_frame_rate']); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } } $result = $this->toolkit->setVideoCodec($settings['video_codec'], false); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $settings['audio_sample_rate'] = (!empty($settings['audio_sample_rate'])) ? $settings['audio_sample_rate'] : $video_info['audio']['sample_rate']; if ($settings['audio_sample_rate'] < 1000) { $settings['audio_sample_rate'] *= 1000; } $settings['audio_sample_rate'] = min($settings['audio_sample_rate'], 44100); $result = $this->toolkit->setAudioSampleFrequency($settings['audio_sample_rate']); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $result = $this->toolkit->setAudioCodec($settings['audio_codec'], false); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $result = $this->toolkit->setAudioChannels($settings['audio_channels']); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } if (empty($settings['audio_bitrate'])) { $settings['audio_bitrate'] = $this->audio_bitrate; } if ($settings['audio_bitrate'] < 1000) { $settings['audio_bitrate'] *= 1000; } $result = $this->toolkit->setAudioBitRate($settings['audio_bitrate']); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } if (empty($settings['video_bitrate'])) { $settings['video_bitrate'] = $this->video_bitrate; } if ($settings['video_bitrate'] < 1000) { $settings['video_bitrate'] *= 1000; } $result = $this->toolkit->setVideoBitRate($settings['video_bitrate']); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $result = $this->toolkit->setVideoDimensions($dimension[0], $dimension[1]); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $result = $this->toolkit->setOutput(dirname($ffmpeg_output) . '/', $converted_filename, PHPVideoToolkit::OVERWRITE_EXISTING); if (!$result) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $result = $this->toolkit->execute(false, true); if ($result !== PHPVideoToolkit::RESULT_OK) { // if there was an error then get it $error_msg = t($this->toolkit->getLastError()); watchdog('transcoder', $error_msg, array(), WATCHDOG_ERROR); $this->toolkit->reset(); continue; } $command_output = $this->toolkit->getLastOutput(); /* if ($ffmpeg_output != $converted_video_path && file_exists($ffmpeg_output)) { // Because the transcoder_interface doesn't allow the run_command() to include the ability to pass // the command to be execute so we need to fudge the command to run qt-faststart. $cmd_path = $this->params['cmd_path']; $this->params['cmd_path'] = $this->params['faststart_cmd']; $command_output .= $this->run_command($ffmpeg_output . ' ' . $converted_video_path, $verbose); $this->params['cmd_path'] = $cmd_path; // Delete the temporary output file. drupal_unlink($ffmpeg_output); } */ //lets check to make sure our file exists, if not error out if (!file_exists($converted_video_path) || !filesize($converted_video_path)) { watchdog('transcoder', 'Video conversion failed for preset %preset. FFMPEG reported the following output: ' . $command_output, array('%orig' => $video->uri, '%preset' => $name), WATCHDOG_ERROR); $this->change_status($video->vid, VIDEO_RENDERING_FAILED); return FALSE; } // Setup our converted video object $video_info = pathinfo($converted_video_path); //update our converted video $video->converted = new stdClass(); $video->converted->vid = $video->vid; $video->converted->filename = $video_info['basename']; $video->converted->uri = $converted; $video->converted->filemime = file_get_mimetype($converted); $video->converted->filesize = filesize($converted); $video->converted->status = VIDEO_RENDERING_COMPLETE; $video->converted->preset = $name; $video->converted->completed = time(); $converted_files[] = $video->converted; } // Update our video_files table with the converted video information. db_update('video_files') ->fields(array( 'status' => VIDEO_RENDERING_COMPLETE, 'completed' => time(), 'data' => serialize($converted_files))) ->condition('vid', $video->converted->vid, '=') ->execute(); watchdog('transcoder', 'Successfully converted %orig to %dest', array('%orig' => $video->uri, '%dest' => $video->converted->uri), WATCHDOG_INFO); return TRUE; } /** * Get some information from the video file */ public function get_video_info($video) { $video_info = $this->toolkit->getFileInfo($video); return $video_info; } /** * Return the playtime seconds of a video */ public function get_playtime($video) { $video_info = $this->get_video_info($video); return $video_info['duration']['seconds']; } /* * Return the dimensions of a video */ public function get_dimensions($video) { $video_info = $this->get_video_info($video); $res = array('width' => 0, 'height' => 0); // Get dimensions $res['width'] = $video_info['video']['dimensions']['width'] ? $video_info['video']['dimensions']['width'] : NULL; $res['height'] = $video_info['video']['dimensions']['height'] ? $video_info['video']['dimensions']['height'] : NULL; return $res; } /** * Interface Implementations * @see sites/all/modules/video/includes/transcoder_interface#get_name() */ public function get_name() { return $this->name; } /** * Interface Implementations * @see sites/all/modules/video/includes/transcoder_interface#get_value() */ public function get_value() { return $this->value; } /** * Interface Implementations * @see sites/all/modules/video/includes/transcoder_interface#get_help() */ public function get_help() { return l(t('PHP Video Toolkit online documentation'), 'http://sourceforge.net/projects/phpvideotoolkit/'); } /** * Interface Implementations * @see sites/all/modules/video/includes/transcoder_interface#admin_settings() */ public function admin_settings() { $form = array(); $form = array(); $form['video_ffmpeg_toolkit_start'] = array( '#type' => 'markup', '#markup' => '