Source of file Video.php
Size: 13,999 Bytes - Last Modified: 2021-12-23T10:04:44+00:00
/var/www/docs.ssmods.com/process/src/code/Video.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 | <?php /** * Video object: this represents a HTML video tag with all necessary encoded file formats */ class Video extends TranscodableObject { private static $has_one = array ( "Poster" => "Image", "Source" => "File", "MP4" => "File", "WEBM" => "File", "OGV" => "File", ); private static $summary_fields = array( "Thumbnail" => "Poster", "Name" => "Name", "ShowShortCode" => "ShortCode" //"Description" => "Description" ); public function getCMSFields() { $fields = parent::getCMSFields(); // if($this->JobID){ // $fields->addFieldToTab("Root.Main", new LiteralField("JobID", // "<p class=\"message good\">Transcoding job ID: {$this->JobID}, Status: {$this->JobStatus}</p>")); // } // if transcoding started or error if(Session::get('VideoNotification')){ $num = 0; foreach(Session::get('VideoNotification') as $type => $message){ $num += 1; $fields->addFieldToTab("Root.Main", new LiteralField("VideoNotification_".$num, "<p class=\"message $type\">$message</p>") ); } Session::clear('VideoNotification'); } $UploadSizeMB = 350 * 1024 * 1024; // 350 MB in bytes // Switch between two views; // - Uploadfield for source file (any type) to be transcoded OR // - Uploadfields for manually transcoded files $mode = new DropdownField( 'DefaultView', _t('Transcodable.Mode', 'Mode'), array( 'source' => _t('Transcodable.SourceForTranscoding', 'Upload source file for transcoding'), 'transcoded' => _t('Transcodable.EncodedFormats', 'Upload HTML5 encoded formats') ) ); // $mode->setRightTitle(_t('Transcodable.ModeExplain', // 'Upload a source file to be transcoded to all (missing) HTML5 formats. If your source file is already in one of the HTML5 formats, choose "HTML encoded formats" and upload it into the correct upload field (MP4, WEBM or OGG) to have that used as original for transcoding. Only missing formats will be transcoded.')); $sourcehead = LiteralField::create('SourceHead', '<h2>'._t('Transcodable.VideoFiles', 'Video files').'</h2>'. '<p style="font-size: 120%; max-width: 640px; line-height: 130%;">'._t('Transcodable.VideoFilesExplain', 'Upload a source file to be transcoded to all (missing) HTML5 formats and a poster image. If your source file is already in one of the HTML5 formats, choose "HTML encoded formats" and upload it into the correct upload field (MP4, WEBM or OGG) to have that used as original for transcoding. Only missing formats/files will be transcoded.') .'</p>'); $appextensions = Config::inst()->get('File', 'app_categories'); $movextensions = $appextensions['mov']; array_push($movextensions, 'mp4'); // add mp4 to video (seen as audio) $sourcefield = ChunkedUploadField::create("Source") ->setTitle(_t('Transcodable.SourceVideo', "Source video")) ->setFolderName('videos') //->setAllowedFileCategories("mov") ->setAllowedExtensions($movextensions); $sourcefield->getValidator()->setAllowedMaxFileSize($UploadSizeMB); $sourcefieldHolder = DisplayLogicWrapper::create($sourcefield) ->displayIf('DefaultView')->isEqualTo("source")->end(); $posterfield = UploadField::create("Poster") ->setTitle("'Poster' image") ->setFolderName('videos') ->setAllowedExtensions(array("jpg","jpeg","gif","png")); // $posterfieldHolder = DisplayLogicWrapper::create($posterfield) // ->displayIf('DefaultView')->isEqualTo("source")->end(); $mp4field = ChunkedUploadField::create("MP4") ->setTitle(_t('Transcodable.MP4video', "MP4 video")) ->setFolderName('videos') ->setAllowedExtensions(array("mp4")); $mp4field->getValidator()->setAllowedMaxFileSize($UploadSizeMB); $mp4fieldHolder = DisplayLogicWrapper::create($mp4field) ->displayIf('DefaultView')->isEqualTo("transcoded")->end(); // $mp4field->displayIf("DefaultView")->isEqualTo("transcoded")->end(); $webmfield = ChunkedUploadField::create("WEBM") ->setTitle(_t('Transcodable.WEBMvideo', "WEBM video")) ->setFolderName('videos') ->setAllowedExtensions(array("webm")); $webmfield->getValidator()->setAllowedMaxFileSize($UploadSizeMB); $webmfieldHolder = DisplayLogicWrapper::create($webmfield) ->displayIf('DefaultView')->isEqualTo("transcoded")->end(); // $webmfield->displayIf("DefaultView")->isEqualTo("transcoded")->end(); $ogvfield = ChunkedUploadField::create("OGV") ->setTitle(_t('Transcodable.OGVvideo', "OGG theora video")) ->setFolderName('videos') ->setAllowedExtensions(array("ogg","ogv")); $ogvfield->getValidator()->setAllowedMaxFileSize($UploadSizeMB); $ogvfieldHolder = DisplayLogicWrapper::create($ogvfield) ->displayIf('DefaultView')->isEqualTo("transcoded")->end(); // $ogvfield->displayIf("DefaultView")->isEqualTo("transcoded")->end(); $fields->addFieldsToTab('Root.Main', array( $mode, $sourcehead, $sourcefieldHolder, $posterfield, $mp4fieldHolder, $webmfieldHolder, $ogvfieldHolder ) ); if($this->ID){ $fields->addFieldsToTab('Root.Main', new HeaderField('scode', $this->ShowShortCode()), 'Name'); } return $fields; } public function ShowShortCode(){ return '[video id='.$this->ID.']'; } public function PosterCropped($x=160,$y=90) { /* 16:9 Ratio */ return $this->Poster()->CroppedImage($x,$y); } public function Thumbnail() { $Image = $this->Poster(); if ( $Image ) return $Image->CMSThumbnail(); else return null; } // // Better button actions (generate HTML5 videoformats) // private static $better_buttons_actions = array ( 'transcode', ); public function getBetterButtonsActions() { $fields = parent::getBetterButtonsActions(); if($this->SourceID || $this->MP4ID || $this->WEBMID || $this->OGVID) { $fields->push($bbact = BetterButtonCustomAction::create('transcode', _t('Transcodable.TranscodeSource', 'Transcode (missing) formats'))); // $bbact->setRedirectType(BetterButtonCustomAction::REFRESH) // ->setSuccessMessage('Denied for publication'); } return $fields; } /** * Test if transcoding complete * @param type $missingOnly */ public function transcodingComplete() { if($this->MP4ID && $this->WEBMID && $this->OGVID){ return true; } return false; } /** * Transcode missing formats from source * @param type $missingOnly */ public function transcode($missingOnly = true) { // get source in preferred order $source = false; if(!$source && $this->SourceID){ $source = $this->Source(); } if(!$source && $this->MP4ID){ $source = $this->MP4(); } if(!$source && $this->WEBMID){ $source = $this->WEBM(); } if(!$source && $this->OGVID){ $source = $this->OGV(); } if(!$source || !$source->exists()){ Session::set('VideoNotification', array( 'error' => _t('Transcodable.MissingVideoSource', 'Could not find any video to use as source for transcoding')) ); return false; } // Build heywatch configuration $hw_config = "# Video config for Heywatch set source = vid_source set webhook = vid_webhook "; // Add missing files; if(!$this->PosterID){ $hw_config .= " -> jpg = vid_upload/vid_pathvid_name-#num#.jpg, number=1"; } if(!$this->MP4ID){ $hw_config .= " -> mp4 = vid_upload/vid_pathvid_name.mp4"; } if(!$this->WEBMID){ $hw_config .= " -> webm = vid_upload/vid_pathvid_name.webm"; } if(!$this->OGVID){ $hw_config .= " -> ogv = vid_upload/vid_pathvid_name.ogv"; } $ext = pathinfo($source->getFilename(), PATHINFO_EXTENSION); // if we're on localhost, use development webhook, else use real one if(Config::inst()->get('Transcoding', 'transcode_development_webhook')){ $whook = Config::inst()->get('Transcoding', 'transcode_development_webhook'); } else { $whook = Transcode_Controller::staticAbsoluteLink(); } $replacements = array( 'vid_webhook' => $whook, 'vid_upload' => Config::inst()->get('Transcoding', 'transcode_upload_method'), 'vid_path' => Config::inst()->get('Transcoding', 'transcode_relative_video_path_ftp'), 'vid_source' => $source->getAbsoluteURL(), 'vid_name' => basename($source->getFilename(), ".".$ext) // with extension stripped ); $hw_config = strtr($hw_config, $replacements); //Debug::dump($hw_config); $joblog = TranscodeJob::getOrCreateForTranscodable($this->ID); //Debug::dump('joblog OK'); $joblog->TranscodableClass = $this->ClassName; $job = HeyWatch::submit($hw_config, Config::inst()->get('Transcoding', 'transcode_api_key')); //Debug::dump('job submit OK'); if($job->{"status"} == "ok") { // job created $joblog->JobStatus = "started"; $joblog->JobID = $job->{"id"}; // Feedback to user Session::set('VideoNotification', array('good'=>'Transcoding started')); } else { // job not created... $joblog->JobStatus = "error"; //$joblog->JobErrorCode = $job->{"error_code"}; $joblog->JobErrorMessage = $job->{"error_message"}; // Feedback to user Session::set('VideoNotification', array('bad'=>'Transcoding error')); } $joblog->write(); //Debug::dump('joblog write OK'); } public function loadTranscodedFiles(){ // get (a) source file to deduct name etc from... $source = false; if(!$source && $this->SourceID){ $source = $this->Source(); } if(!$source && $this->MP4ID){ $source = $this->MP4(); } if(!$source && $this->WEBMID){ $source = $this->WEBM(); } if(!$source && $this->OGVID){ $source = $this->OGV(); } $ext = pathinfo($source->getFilename(), PATHINFO_EXTENSION); $vid_name = basename($source->getFilename(), ".".$ext); // with extension stripped $vid_path = Config::inst()->get('Transcoding', 'transcode_relative_video_path_base'); $poster_path = "$vid_path$vid_name-01.jpg"; $mp4_path = "$vid_path$vid_name.mp4"; $webm_path = "$vid_path$vid_name.webm"; $ogv_path = "$vid_path$vid_name.ogv"; if(!$this->PosterID && file_exists(BASE_PATH."/".$poster_path)){ $file = new Image(); $file->setFilename($poster_path); $file->write(); $this->PosterID = $file->ID; } if(!$this->MP4ID && file_exists(BASE_PATH."/".$mp4_path)){ $file = new File(); $file->setFilename($mp4_path); $file->write(); $this->MP4ID = $file->ID; } if(!$this->WEBMID && file_exists(BASE_PATH."/".$webm_path)){ $file = new File(); $file->setFilename($webm_path); $file->write(); $this->WEBMID = $file->ID; } if(!$this->OGVID && file_exists(BASE_PATH."/".$ogv_path)){ $file = new File(); $file->setFilename($ogv_path); $file->write(); $this->OGVID = $file->ID; } $this->write(); } // // Duplicated from Images, mainly template helpers // /** * An image exists if it has a filename. * Does not do any filesystem checks. * * @return boolean */ // public function exists() { // if(isset($this->record["Filename"])) { // return true; // } // } // public function onAfterUpload() { // $this->deleteFormattedImages(); // parent::onAfterUpload(); // } // protected function onBeforeDelete() { // parent::onBeforeDelete(); // // $this->deleteFormattedImages(); // } } class Video_Controller extends Controller { private static $allowed_actions = array( "oembed", ); public static function VideoShortCodeHandler($arguments, $content = null, $parser = null, $tagName) { if(!empty($arguments['id']) && $vid = Video::get()->byID((int) $arguments['id'])){ return $vid->customise(array('Content'=>$content))->renderWith('VideoTag'); } else { return; } } public function oembed(SS_HTTPRequest $request){ /*{ * "thumbnail_height": 360, * "author_name": "ZackScott", * "title": "Amazing Nintendo Facts", * "height": 270, * "provider_name": "YouTube", * "width": 480, * "html": "\u003ciframe width=\"480\" height=\"270\" src=\"http:\/\/www.youtube.com\/embed\/M3r2XDceM6A?feature=oembed\" frameborder=\"0\" allowfullscreen\u003e\u003c\/iframe\u003e", * "provider_url": "http:\/\/www.youtube.com\/", * "thumbnail_url": "http:\/\/i.ytimg.com\/vi\/M3r2XDceM6A\/hqdefault.jpg", * "type": "video", * "thumbnail_width": 480, * "author_url": "http:\/\/www.youtube.com\/user\/ZackScott", * "version": "1.0" * } */ /* { "version": "1.0", "type": "video", "provider_name": "YouTube", "provider_url": "http://youtube.com/", "width": 425, "height": 344, "title": "Amazing Nintendo Facts", "author_name": "ZackScott", "author_url": "http://www.youtube.com/user/ZackScott", "html": "<object width=\"425\" height=\"344\"> <param name=\"movie\" value=\"http://www.youtube.com/v/M3r2XDceM6A&fs=1\"></param> <param name=\"allowFullScreen\" value=\"true\"></param> <param name=\"allowscriptaccess\" value=\"always\"></param> <embed src=\"http://www.youtube.com/v/M3r2XDceM6A&fs=1\" type=\"application/x-shockwave-flash\" width=\"425\" height=\"344\" allowscriptaccess=\"always\" allowfullscreen=\"true\"></embed> </object>", }*/ // get video object by ID if($this->request->param('ID') && $vid = Video::get()->byID((int) $this->request->param('ID'))){ // get some references $thumbnail = $vid->Poster(); $html = $vid->renderWith('VideoTag'); // build embed $embed = new stdClass(); $embed->version = "1.0"; $embed->type = "video"; $embed->title = $vid->Name; $embed->width = $thumbnail->getWidth(); $embed->height = $thumbnail->getHeight(); $embed->html = "$html"; $embed->thumbnail_height = $thumbnail->getWidth(); $embed->thumbnail_width = $thumbnail->getHeight(); $embed->thumbnail_url = $thumbnail->getAbsoluteURL(); // Format response with json $response = new SS_HTTPResponse(Convert::raw2json($embed)); $response->addHeader('Content-Type', 'application/json'); return $response; } else { return $this->httpError(404); } } } |