Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Archive
  • File
  • Filesystem
  • FlushGeneratedImagesTask
  • FLV
  • Folder
  • Folder_UnusedAssetsField
  • GD
  • Image
  • Image_Cached
  • MediawebPage_Image
  • MP3
  • SaveFileSizeTask
  • TarballArchive
  • Upload
  • Upload_Validator
  • VideoFile
  1 <?php
  2 
  3 class FLV extends File {
  4 
  5     public static $allowed_file_types = array(
  6         'flv', 'avi', 'mov', 'mpeg', 'mpg', 'm4a'
  7     );
  8     private static $has_ffmpeg = null;
  9     private $allow_full_screen = true;
 10     private static $ffmpeg_root = "";
 11     private static $termination_code;
 12     public static $player_count = 0;
 13     public static $video_width = 840;
 14     public static $video_height = 525;
 15     public static $default_thumbnail_width = 640;
 16     public static $default_thumbnail_height = 480;
 17     public static $thumbnail_folder = "video_thumbnails";
 18     public static $log_file_path = "dataobject_manager/code/flv/ffmpeg_log.txt";
 19     public static $default_popup_width = 840;
 20     public static $default_popup_height = 525;
 21     public static $thumbnail_seconds = 10;
 22     public static $audio_sampling_rate = 22050;
 23     public static $audio_bit_rate = 32;
 24     public static $play_button_overlay = true;
 25     // .gif is also available to support the IE6 world, or specify your own.
 26     public static $default_video_icon_path = "dataobject_manager/code/flv/images/default_video.png";
 27 
 28     public static function set_ffmpeg_root($path) {
 29         if (substr($path, -1) != "/")
 30             $path .= "/";
 31         self::$ffmpeg_root = $path;
 32     }
 33 
 34     public static function has_ffmpeg() {
 35         // Cache this so we don't have to run a shell command every time.
 36         if (self::$has_ffmpeg !== null)
 37             return self::$has_ffmpeg;
 38 
 39         $success = false;
 40         if (extension_loaded('ffmpeg'))
 41             $success = true;
 42         else {
 43             $output = self::ffmpeg("");
 44             if (self::$termination_code == 1)
 45                 $success = true;
 46         }
 47         self::$has_ffmpeg = $success;
 48         return self::$has_ffmpeg;
 49     }
 50 
 51     public static function echo_ffmpeg_test() {
 52 
 53         echo self::has_ffmpeg() ? "<span style='color:green'>FFMPEG is installed on your server and working properly. Code: " . self::$termination_code . "</span>" :
 54                 "<span class='color:red'>FFMPEG does not appear to be installed on your server. Code: " . self::$termination_code . "</span>";
 55     }
 56 
 57     protected static function ffmpeg($args) {
 58         $descriptorspec = array(
 59             0 => array("pipe", "r"), // stdin is a pipe that the child will read from
 60             1 => array("pipe", "w"), // stdout is a pipe that the child will write to
 61             2 => array("pipe", "w") // stderr is a file to write to
 62         );
 63 
 64         $pipes = array();
 65         $cmd = self::$ffmpeg_root . "ffmpeg " . $args;
 66         self::log_command($cmd);
 67         $process = proc_open($cmd, $descriptorspec, $pipes);
 68 
 69         $output = "";
 70 
 71         if (!is_resource($process))
 72             return false;
 73 
 74         #close child's input immediately
 75         fclose($pipes[0]);
 76 
 77         stream_set_blocking($pipes[1], false);
 78         stream_set_blocking($pipes[2], false);
 79 
 80         $todo = array($pipes[1], $pipes[2]);
 81 
 82         while (true) {
 83             $read = array();
 84             if (!feof($pipes[1]))
 85                 $read[] = $pipes[1];
 86             if (!feof($pipes[2]))
 87                 $read[] = $pipes[2];
 88 
 89             if (!$read)
 90                 break;
 91 
 92             $ready = stream_select($read, $write = NULL, $ex = NULL, 2);
 93 
 94             if ($ready === false) {
 95                 break; #should never happen - something died
 96             }
 97 
 98             foreach ($read as $r) {
 99                 $s = fread($r, 1024);
100                 $output.= $s;
101             }
102         }
103 
104         fclose($pipes[1]);
105         fclose($pipes[2]);
106 
107         self::$termination_code = proc_close($process);
108         self::log_command($output);
109         return $output;
110     }
111 
112     private static function log_command($cmd) {
113         if (self::$log_file_path) {
114             $log = Director::baseFolder() . "/" . self::$log_file_path;
115             $f = @fopen($log, 'a');
116             $entry = "[" . date('Y-m-d H:i:s') . "] " . $cmd . "\n";
117             @fwrite($f, $entry);
118             @fclose($f);
119         }
120     }
121 
122     private function default_thumbnail() {
123         $img = new Image_Cached(self::$default_video_icon_path);
124         $img->ID = $this->ID;
125         return $img;
126     }
127 
128     private function SWFLink() {
129         return Director::absoluteURL('dataobject_manager/code/flv/shadowbox/libraries/mediaplayer/player.swf');
130     }
131 
132     private function AllowFullScreen() {
133         return $this->allow_full_screen ? "true" : "false";
134     }
135 
136     private static function remove_file_extension($filename) {
137         $ext = strrchr($filename, '.');
138         if ($ext !== false)
139             $filename = substr($filename, 0, -strlen($ext));
140         return $filename;
141     }
142 
143     private static function clean_file($str) {
144         $t = strtolower($str);
145         $t = str_replace('&amp;', '-and-', $t);
146         $t = str_replace('&', '-and-', $t);
147         $t = preg_replace('![^A-Za-z0-9]+!', '-', $t);
148         $t = preg_replace('!-+!', '-', $t);
149         return $t;
150     }
151 
152     public function Icon() {
153         return SAPPHIRE_DIR . "/images/app_icons/mov_32.gif";
154     }
155 
156     public function FLVPath() {
157         return self::remove_file_extension($this->Filename) . ".flv";
158     }
159 
160     public function FLVLink() {
161         return Director::absoluteURL($this->FLVPath());
162     }
163 
164     private function absoluteRawVideoLink() {
165         return Director::baseFolder() . "/" . $this->Filename;
166     }
167 
168     private function absoluteFLVPath() {
169         return Director::baseFolder() . "/" . $this->FLVPath();
170     }
171 
172     private function hasFLV() {
173         return Director::fileExists($this->FLVPath());
174     }
175 
176     public function getThumbnail() {
177         if ($img = DataObject::get_one("Image", "Title = 'flv_thumb_{$this->ID}'"))
178             return Director::fileExists($img->Filename) ? $img : false;
179         return false;
180     }
181 
182     private function createFLV() {
183         $args = sprintf("-i %s -ar %d -ab %d -f flv %s",
184                         $this->absoluteRawVideoLink(),
185                         self::$audio_sampling_rate,
186                         self::$audio_bit_rate,
187                         $this->absoluteFLVPath()
188         );
189 
190         $output = self::ffmpeg($args);
191     }
192 
193     private function createThumbnail() {
194         $img_title = "flv_thumb_" . $this->ID;
195         if ($existing = DataObject::get("Image", "Title = '$img_title'")) {
196             foreach ($existing as $file)
197                 $file->delete();
198         }
199         $folder = Folder::findOrMake(self::$thumbnail_folder);
200         $img_filename = self::clean_file(self::remove_file_extension($this->Title)) . ".jpg";
201         $abs_thumb = Director::baseFolder() . "/" . $folder->Filename . $img_filename;
202         $args = sprintf("-y -i %s -an -s %s -ss %d -an -r 1 -vframes 1 -y -vcodec mjpeg -f mjpeg %s",
203                         str_replace(' ', '\ ', $this->absoluteFLVPath()),
204                         self::$default_thumbnail_width . "x" . self::$default_thumbnail_height,
205                         self::$thumbnail_seconds,
206                         $abs_thumb
207         );
208         self::ffmpeg($args);
209 
210         $img = new Image();
211         $img->setField('ParentID', $folder->ID);
212         $img->Filename = $folder->Filename . $img_filename;
213         $img->Title = $img_title;
214         $img->write();
215     }
216 
217     public function onBeforeWrite() {
218         parent::onBeforeWrite();
219         if (!$this->hasFLV())
220             $this->createFLV();
221         if (!$this->getThumbnail())
222             $this->createThumbnail();
223     }
224 
225     public function Player($width = null, $height = null) {
226         if ($width === null)
227             $width = self::$video_width;
228         if ($height === null)
229             $height = self::$video_height;
230         $image = ($thumb = $this->VideoThumbnail()) ? $thumb->CroppedImage($width, $height)->URL : "";
231         self::$player_count++;
232         Requirements::javascript('dataobject_manager/code/flv/swfobject.js');
233         Requirements::customScript(sprintf(
234                                 "swfobject.embedSWF('%s','player-%s','%d','%d','9.0.0','expressInstall.swf',{file : '%s',image : '%s'},{allowscriptaccess : 'true', allowfullscreen : '%s'})",
235                                 $this->SWFLink(),
236                                 self::$player_count,
237                                 $width,
238                                 $height,
239                                 $this->FLVLink(),
240                                 $image,
241                                 $this->AllowFullScreen()
242                         )
243         );
244         return "<div id='player-" . self::$player_count . "'>Loading...</div>";
245     }
246 
247     public function forTemplate() {
248         return $this->Player();
249     }
250 
251     public function VideoThumbnail() {
252         if (self::has_ffmpeg() && !$img = $this->getThumbnail())
253             $this->createThumbnail();
254         $img = $this->getThumbnail();
255         return $img ? $img : $this->default_thumbnail();
256     }
257 
258     /**
259      * SSViewer doesn't accept more than two arguments for template
260      * functions. Here's a hack. If an arg is, e.g. 200x400 it will
261      * split that into width/height for thumb for first arg, and popup
262      * for second arg.
263      *
264      * Examples:
265      * $VideoPopup(450,200) : Returns a video popup with thumbnail
266      *                        450 width, 200 height. Popup is default dimensions
267      *
268      * $VideoPopup(450x200,800x600) : Returns a video popup with thumbnail
269      *                                450 width, 200 height. Popup is 800 width, 600 height.
270      *
271      * $VideoPopup(450x200) : Same as first example.
272      *
273      */
274     public function VideoPopup($arg1 = null, $arg2 = null) {
275         $popup_width = null;
276         $popup_height = null;
277         if ($arg1 !== null && stristr($arg1, "x"))
278             list($thumb_width, $thumb_height) = explode("x", $arg1);
279         else
280             $thumb_width = $arg1;
281 
282         if ($arg2 !== null && stristr($arg2, "x"))
283             list($popup_width, $popup_height) = explode("x", $arg2);
284         else
285             $thumb_height = $arg2;
286 
287         if ($popup_width === null)
288             $popup_width = self::$default_popup_width;
289         if ($popup_height === null)
290             $popup_height = self::$default_popup_height;
291 
292         return $this->customise(array(
293             'PopupWidth' => $popup_width,
294             'PopupHeight' => $popup_height,
295             'ThumbWidth' => $thumb_width,
296             'ThumbHeight' => $thumb_height,
297             'Title' => $this->Title,
298             'Link' => $this->FLVLink(),
299             'Thumbnail' => $this->VideoThumbnail()->CroppedImage($thumb_width, $thumb_height),
300             'PlayButton' => self::$play_button_overlay
301         ))->renderWith(array('FLVpopup'));
302     }
303 
304 }
305 
306 ?>
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0