public static function Run() { chdir(realpath(dirname(__FILE__) . '/../')); require_once 'includes/global.php'; $doc_root = Config::Get('document_root'); $DB = GetDB(); self::Log('Starting...'); self::MarkRunning(); while (true) { // See if we were requested to stop if (self::ShouldStop()) { self::Log('User requested stop...'); break; } self::Ping(); $DB->Connect(); $queue_item = $DB->Row('SELECT * FROM `tbx_thumb_queue` ORDER BY `queued` LIMIT 1'); if (!empty($queue_item)) { $video = $DB->Row('SELECT * FROM `tbx_video` WHERE `video_id`=?', array($queue_item['video_id'])); if (!empty($video)) { $DB->Update('UPDATE `tbx_thumb_queue` SET `date_started`=? WHERE `video_id`=?', array(Database_MySQL::Now(), $video['video_id'])); $clips = $DB->FetchAll('SELECT * FROM `tbx_video_clip` WHERE `video_id`=? AND `type`!=? ORDER BY `clip_id`', array($queue_item['video_id'], 'Embed')); $dir = new Video_Dir(Video_Dir::DirNameFromId($video['video_id'])); Video_FrameGrabber::SetLogFile($dir->GetBaseDir() . '/thumbnailer.log'); $thumb_start = time(); try { if (!empty($clips)) { $thumbs = array(); $duration = 0; // Number of thumbs to create per clip $amount = round(Config::Get('thumb_amount') / count($clips)); // Move existing thumbnails $dir->MoveFiles($dir->GetThumbsDir(), $dir->GetTempDir(), JPG_EXTENSION); // Process each clip foreach ($clips as $clip) { self::Ping(); // Remote video if (preg_match('~https?://~i', $clip['clip'])) { $http = new HTTP(); if ($http->Get($clip['clip'], $clip['clip'])) { $video_file = $dir->AddOriginalFromVar($http->body, File::Extension($clip['clip'])); $vi = new Video_Info($video_file); $vi->Extract(); $duration += $vi->length; $temp_thumbs = Video_FrameGrabber::Grab($video_file, $dir->GetProcessingDir(), $amount, Config::Get('thumb_quality'), Config::Get('thumb_size'), $vi); // Move generated thumbs from the processing directory foreach ($temp_thumbs as $temp_thumb) { $thumbs[] = $dir->AddThumbFromFile($temp_thumb); } @unlink($video_file); } } else { $temp_thumbs = Video_FrameGrabber::Grab($doc_root . '/' . $clip['clip'], $dir->GetProcessingDir(), $amount, Config::Get('thumb_quality'), Config::Get('thumb_size')); // Move generated thumbs from the processing directory foreach ($temp_thumbs as $temp_thumb) { $thumbs[] = $dir->AddThumbFromFile($temp_thumb); } } } // Get the relative URL for each thumb and add to database $thumb_ids = array(); foreach ($thumbs as $thumb) { $thumb = str_replace($doc_root, '', $thumb); $thumb_ids[] = DatabaseAdd('tbx_video_thumbnail', array('video_id' => $video['video_id'], 'thumbnail' => $thumb)); } // Determine number of thumbnails and select random display thumbnail $num_thumbnails = count($thumbs); $display_thumbnail = null; if ($num_thumbnails > 0) { // Select display thumbnail randomly from the first 40% $display_thumbnail = $thumb_ids[rand(0, floor(0.4 * $num_thumbnails))]; } $update = array('video_id' => $video['video_id'], 'num_thumbnails' => $num_thumbnails, 'display_thumbnail' => $display_thumbnail); if (empty($video['duration']) && !empty($duration)) { $update['duration'] = $duration; } DatabaseUpdate('tbx_video', $update); // Remove old thumbnails $DB->Update('DELETE FROM `tbx_video_thumbnail` WHERE `video_id`=?' . (!empty($thumb_ids) ? ' AND`thumbnail_id` NOT IN (' . join(',', $thumb_ids) . ')' : ''), array($video['video_id'])); $dir->ClearTemp(); } } catch (Exception $e) { // Restore old thumbnails $dir->MoveFiles($dir->GetTempDir(), $dir->GetThumbsDir(), JPG_EXTENSION); Video_FrameGrabber::Log($e->getMessage() . (strtolower(get_class($e)) == 'baseexception' ? $e->getExtras() : '') . "\n" . $e->getTraceAsString()); self::UpdateStatsProcessed($thumb_start, $thumb_end, $queue_item['queued'], true); } $thumb_end = time(); $DB->Update('DELETE FROM `tbx_thumb_queue` WHERE `video_id`=?', array($queue_item['video_id'])); self::UpdateStatsProcessed($thumb_start, $thumb_end, $queue_item['queued']); } } else { break; } } self::MarkStopped(); self::Log('Exiting...'); }
function tbxVideoEdit() { Privileges::Check(Privileges::VIDEOS); $DB = GetDB(); $schema = GetDBSchema(); $v = Validator::Create(); $v->RegisterFromXml($schema->el('//table[name="tbx_video"]')); $v->RegisterFromXml($schema->el('//table[name="tbx_video_custom"]')); if (!String::IsEmpty($_REQUEST['username'])) { $v->Register($DB->QueryCount('SELECT COUNT(*) FROM `tbx_user` WHERE `username`=?', array($_REQUEST['username'])) > 0, Validator_Type::IS_TRUE, 'The Username entered does not exist'); } if (!$v->Validate()) { return JSON::Failure(array('message' => 'Video could not be updated; please fix the following items', 'errors' => $v->GetErrors())); } $_REQUEST['display_thumbnail'] = empty($_REQUEST['display_thumbnail']) ? null : $_REQUEST['display_thumbnail']; $_REQUEST['date_recorded'] = String::Nullify($_REQUEST['date_recorded']); $_REQUEST['tags'] = Tags::Format($_REQUEST['tags']); $_REQUEST['username'] = String::Nullify(Request::Get('username')); $_REQUEST['duration'] = Format::DurationToSeconds($_REQUEST['duration']); $original = $DB->Row('SELECT * FROM `tbx_video` WHERE `video_id`=?', array($_REQUEST['video_id'])); // Handle uploaded thumbs, if any $dir = new Video_Dir(Video_Dir::DirNameFromId($original['video_id'])); $thumbs_added = 0; $thumb_ids = array(); Request::FixFiles(); if (isset($_FILES['thumb_uploads'])) { foreach ($_FILES['thumb_uploads'] as $upload) { if (File::Extension($upload['name']) == JPG_EXTENSION && ($imgsize = getimagesize($upload['tmp_name'])) !== false) { $temp_file = $dir->AddTempFromFile($upload['tmp_name'], JPG_EXTENSION); if (Video_Thumbnail::CanResize()) { $temp_file = Video_Thumbnail::Resize($temp_file, Config::Get('thumb_size'), Config::Get('thumb_quality'), $dir->GetTempDir()); } $thumb = $dir->AddThumbFromFile($temp_file); $thumbs_added++; $thumb = str_replace(Config::Get('document_root'), '', $thumb); $thumb_ids[] = array('uri' => $thumb, 'id' => DatabaseAdd('tbx_video_thumbnail', array('video_id' => $original['video_id'], 'thumbnail' => $thumb))); } } if ($thumbs_added > 0) { $dir->ClearTemp(); $_REQUEST['num_thumbnails'] = $original['num_thumbnails'] + $thumbs_added; } } // Update base database tables $video = DatabaseUpdate('tbx_video', $_REQUEST); DatabaseUpdate('tbx_video_custom', $_REQUEST); // Handle changes to video clips foreach ($_REQUEST['clips'] as $clip_id => $clip) { DatabaseUpdate('tbx_video_clip', array('video_id' => $video['video_id'], 'clip_id' => $clip_id, 'clip' => $clip['clip'])); } if ($_REQUEST['is_private'] && !$original['is_private']) { $_REQUEST['private_id'] = sha1(uniqid(mt_rand(), true)); DatabaseAdd('tbx_video_private', $_REQUEST); if ($original['status'] == STATUS_ACTIVE) { Tags::RemoveFromFrequency($original['tags']); } } else { if (!$_REQUEST['is_private']) { if ($original['status'] == STATUS_ACTIVE) { if ($original['is_private']) { Tags::AddToFrequency($_REQUEST['tags']); } else { Tags::UpdateFrequency($original['tags'], $_REQUEST['tags']); } } $DB->Update('DELETE FROM `tbx_video_private` WHERE `video_id`=?', array($_REQUEST['video_id'])); } } if ($original['status'] == STATUS_ACTIVE) { $t = new Template(); $t->ClearCache('categories.tpl'); } UpdateCategoryStats($original['category_id'], $video['category_id']); UpdateSponsorStats($original['sponsor_id'], $_REQUEST['sponsor_id']); $output = array('id' => $video['video_id'], 'message' => 'Video has been successfully updated', 'html' => SearchItemHtml('video', $video), 'thumbs' => $thumb_ids); JSON::Success($output); }
public static function Run() { chdir(realpath(dirname(__FILE__) . '/../')); require_once 'includes/global.php'; $doc_root = Config::Get('document_root'); $DB = GetDB(); self::Log('Starting...'); self::MarkRunning(); while (true) { // See if we were requested to stop if (self::ShouldStop()) { self::Log('User requested stop...'); break; } self::Ping(); $DB->Connect(); $queue_item = $DB->Row('SELECT *,`tbx_conversion_queue`.`video_id` AS `video_id`,`tbx_conversion_queue`.`queued` AS `queued` FROM `tbx_conversion_queue` LEFT JOIN ' . '`tbx_thumb_queue` USING (`video_id`) WHERE `tbx_thumb_queue`.`video_id` IS NULL ORDER BY `tbx_conversion_queue`.`queued` LIMIT 1'); if (!empty($queue_item)) { $video = $DB->Row('SELECT * FROM `tbx_video` WHERE `video_id`=?', array($queue_item['video_id'])); if (!empty($video)) { $DB->Update('UPDATE `tbx_video` SET `conversion_failed`=0 WHERE `video_id`=?', array($video['video_id'])); $DB->Update('UPDATE `tbx_conversion_queue` SET `date_started`=? WHERE `video_id`=?', array(Database_MySQL::Now(), $video['video_id'])); $clips = $DB->FetchAll('SELECT * FROM `tbx_video_clip` WHERE `video_id`=? ORDER BY `clip_id`', array($queue_item['video_id'])); $dir = new Video_Dir(Video_Dir::DirNameFromId($video['video_id'])); Video_Converter::SetLogFile($dir->GetBaseDir() . '/convert.log'); $convert_start = time(); $conversion_failed = false; foreach ($clips as $clip) { $clip_path = null; $old_path = null; try { // Stored locally, move to originals directory if ($clip['clip'][0] == '/') { $old_path = $doc_root . $clip['clip']; $clip_path = $dir->AddOriginalFromFile($old_path); } else { $http = new HTTP(); if ($http->Get($clip['clip'], $clip['clip'])) { $clip_path = $dir->AddOriginalFromVar($http->body, File::Extension($clip['clip'])); } else { throw new BaseException('Could not download clip for conversion: ' . $http->error); } } $output_file = Video_Converter::Convert($clip_path, $dir->GetProcessingDir(), Config::Get('video_format'), Config::Get('video_bitrate'), Config::Get('audio_bitrate'), Config::Get('video_size'), array('ConversionQueue', 'Ping')); $converted_video = $dir->AddClipFromFile($output_file); $DB->Disconnect(); $DB->Connect(); $DB->Update('UPDATE `tbx_video_clip` SET `clip`=?,`filesize`=? WHERE `clip_id`=?', array(str_replace($doc_root, '', $converted_video), filesize($converted_video), $clip['clip_id'])); } catch (Exception $e) { if (!empty($old_path) && !empty($clip_path)) { rename($clip_path, $old_path); } Video_Converter::Log($e->getMessage() . (strtolower(get_class($e)) == 'baseexception' ? $e->getExtras() : '') . "\n" . $e->getTraceAsString()); $conversion_failed = true; } } $convert_end = time(); $dir->ClearProcessing(); $dir->ClearTemp(); $DB->Connect(); $DB->Update('DELETE FROM `tbx_conversion_queue` WHERE `video_id`=?', array($queue_item['video_id'])); if ($conversion_failed) { self::UpdateStatsProcessed($convert_start, $convert_end, $queue_item['queued'], true); $DB->Update('UPDATE `tbx_video` SET `conversion_failed`=1 WHERE `video_id`=?', array($video['video_id'])); } else { // Update stats self::UpdateStatsProcessed($convert_start, $convert_end, $queue_item['queued']); $status = empty($video['next_status']) ? STATUS_ACTIVE : $video['next_status']; // Set video status $DB->Update('UPDATE `tbx_video` SET `status`=? WHERE `video_id`=?', array($status, $video['video_id'])); if ($video['status'] != $status && $status == STATUS_ACTIVE && !$video['is_private']) { Tags::AddToFrequency($video['tags']); } UpdateCategoryStats($video['category_id']); } } } else { break; } } self::MarkStopped(); self::Log('Exiting...'); }
public function Import() { $imported = 0; $http = new HTTP(); if ($http->Get($this->feed['feed_url'])) { $xml = simplexml_load_string($this->ToUTF8($http->body), 'XML_Element', LIBXML_NOERROR, LIBXML_NOWARNING, LIBXML_NOCDATA); if ($xml !== false) { $DB = GetDB(); foreach ($xml->xpath('//videos/video') as $xvideo) { // Check for duplicates, and skip if ($DB->QueryCount('SELECT COUNT(*) FROM `tbx_video_feed_history` WHERE `feed_id`=? AND `unique_id`=?', array($this->feed['feed_id'], $xvideo->id->val()))) { continue; } // Setup defaults $video = $this->defaults; $video['title'] = $xvideo->title->val(); $video['description'] = $xvideo->description->val(); $video['tags'] = Tags::Format($xvideo->tags->val()); if (empty($video['description'])) { $video['description'] = $video['title']; } // Process <clips> $clips = array(); $screens = array(); foreach ($xvideo->xpath('./clips/clip') as $xclip) { $video['duration'] += $xclip->duration; $clip_url = $xvideo->clip_url->val(); $flv = $xclip->flv->val(); // Account for malformed feeds where the clip_url contains the URL to the video // file rather than the required root URL if (strstr($clip_url, $flv) === false) { $clip_url = $clip_url . $flv; } $clips[] = array('type' => 'URL', 'clip' => $clip_url); foreach ($xclip->xpath('./screens/screen') as $xscreen) { $screen_url = $xvideo->screen_url->val(); $screen = $xscreen->val(); // Account for malformed feeds where the screen_url contains the URL to the image // file rather than the required root URL if (strstr($screen_url, $screen) === false) { $screen_url = $screen_url . $screen; } $screens[] = array('thumbnail' => $screen_url); } } if (count($clips) > 0) { $best_category = GetBestCategory(join(' ', array($video['title'], $video['description'], $video['tags']))); if (!empty($best_category)) { $video['category_id'] = $best_category; } if ($this->feed['flag_convert']) { $video['status'] = STATUS_QUEUED; $video['next_status'] = $this->feed['status']; } $video['video_id'] = DatabaseAdd('tbx_video', $video); DatabaseAdd('tbx_video_custom', $video); DatabaseAdd('tbx_video_stat', $video); if (!$video['is_private']) { Tags::AddToFrequency($video['tags']); } $video['queued'] = time(); if ($this->feed['flag_convert']) { DatabaseAdd('tbx_conversion_queue', $video); } if ($this->feed['flag_thumb']) { DatabaseAdd('tbx_thumb_queue', $video); } UpdateCategoryStats($video['category_id']); $video_dir = new Video_Dir(Video_Dir::DirNameFromId($video['video_id'])); foreach ($clips as $clip) { $clip['video_id'] = $video['video_id']; DatabaseAdd('tbx_video_clip', $clip); } $display_thumbnail = null; foreach ($screens as $screen) { $thttp = new HTTP(); if ($thttp->Get($screen['thumbnail'], $screen['thumbnail'])) { $temp_file = $video_dir->AddTempFromVar($thttp->body, JPG_EXTENSION); $imgsize = @getimagesize($temp_file); if ($imgsize !== false) { if (Video_Thumbnail::CanResize()) { $local_filename = Video_Thumbnail::Resize($temp_file, Config::Get('thumb_size'), Config::Get('thumb_quality'), $video_dir->GetThumbsDir()); } else { $local_filename = $video_dir->AddThumbFromFile($temp_file, JPG_EXTENSION); } $local_filename = str_replace(Config::Get('document_root'), '', $local_filename); $thumb_id = DatabaseAdd('tbx_video_thumbnail', array('video_id' => $video['video_id'], 'thumbnail' => $local_filename)); if (empty($display_thumbnail)) { $display_thumbnail = $thumb_id; } } } } $video_dir->ClearTemp(); if (!empty($display_thumbnail)) { $DB->Update('UPDATE `tbx_video` SET `display_thumbnail`=? WHERE `video_id`=?', array($display_thumbnail, $video['video_id'])); } $DB->Update('INSERT INTO `tbx_video_feed_history` VALUES (?,?)', array($this->feed['feed_id'], $xvideo->id->val())); $imported++; } } $DB->Update('UPDATE `tbx_video_feed` SET `date_last_read`=? WHERE `feed_id`=?', array(Database_MySQL::Now(), $this->feed['feed_id'])); UpdateSponsorStats($this->feed['sponsor_id']); } // Start up the thumbnail and converson queues if needed if (!Config::Get('flag_using_cron')) { if ($this->feed['flag_convert']) { ConversionQueue::Start(); } if ($this->feed['flag_thumb']) { ThumbQueue::Start(); } } } return $imported; }