PageRenderTime 71ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/app/vendors/phpvideotoolkit.php5.php

https://github.com/mariuz/firetube
PHP | 3311 lines | 1748 code | 166 blank | 1397 comment | 259 complexity | a33e3bdf4e68c9038f80644b65dd875a MD5 | raw file
Possible License(s): LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* SVN FILE: $Id$ */
  3. /**
  4. * @author Oliver Lillie (aka buggedcom) <publicmail@buggedcom.co.uk>
  5. *
  6. * @license BSD
  7. * @copyright Copyright (c) 2008 Oliver Lillie <http://www.buggedcom.co.uk>
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
  9. * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
  11. * is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be
  12. * included in all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  15. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  16. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  17. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  18. *
  19. * @package PHPVideoToolkit (was called ffmpeg)
  20. * @version 0.1.5
  21. * @changelog SEE CHANGELOG
  22. * @abstract This class can be used in conjunction with several server binary libraries to manipulate video and audio
  23. * through PHP. It is not intended to solve any particular problems, however you may find it useful. This php class
  24. * is in no way associated with the actual FFmpeg releases. Any mistakes contained in this php class are mine and mine
  25. * alone.
  26. *
  27. * Please Note: There are several prerequisites that are required before this class can be used as an aid to manipulate
  28. * video and audio. You must at the very least have FFMPEG compiled on your server. If you wish to use this class for FLV
  29. * manipulation you must compile FFMPEG with LAME and Ruby's FLVTOOL2. I cannot answer questions regarding the install of
  30. * the server binaries needed by this class. I had too learn the hard way and it isn't easy, however it is a good learning
  31. * experience. For those of you who do need help read the install.txt file supplied along side this class. It wasn't written
  32. * by me however I found it useful when installing ffmpeg for the first time. The original source for the install.txt file
  33. * is located http://www.luar.com.hk/blog/?p=669 and the author is Lunar.
  34. *
  35. * @see install.txt
  36. *
  37. * @uses ffmpeg http://ffmpeg.sourceforge.net/
  38. * @uses lame http://lame.sourceforge.net/
  39. * @uses flvtool2 http://www.inlet-media.de/flvtool2 (and ruby http://www.ruby-lang.org/en/)
  40. *
  41. * @config examples/example-config.php Please edit this files in order for the examples to work.
  42. * @example examples/example01.php Converts video to Flash Video (ie FLV).
  43. * @example examples/example02.php Screen grabs video frames.
  44. * @example examples/example03.php Compile a movie from multiple jpegs
  45. * @example examples/example04.php Watermark a video.
  46. * @example examples/example05.php Access media metadata without using the ffmpeg-php library.
  47. * @example examples/example06.php Extract audio from video.
  48. * @example examples/example07.php Join multiple videos together.
  49. * @example examples/example08.php Easy video conversion to common formats using the adapters.
  50. * @example examples/example09.php Shows you how to access the information about your ffmpeg installation.
  51. * @example examples/example10.php Shows you how to extract a specific frame from a movie.
  52. * @example examples/example11.php Shows you how to use the ffmpeg-php adapters to provide a pure php emulation of ffmpeg-php.
  53. * @example examples/example12.php Shows you how to manipulate/format timecode strings.
  54. * @example examples/example13.php This demonstrates how to simply create a FLV stream script.
  55. */
  56. /**
  57. * Set the ffmpeg binary path
  58. */
  59. if(!defined('PHPVIDEOTOOLKIT_TEMP_DIRECTORY'))
  60. {
  61. define('PHPVIDEOTOOLKIT_TEMP_DIRECTORY', '/tmp/');
  62. }
  63. /**
  64. * Set the ffmpeg binary path
  65. */
  66. if(!defined('PHPVIDEOTOOLKIT_FFMPEG_BINARY'))
  67. {
  68. define('PHPVIDEOTOOLKIT_FFMPEG_BINARY', '/usr/local/bin/ffmpeg');
  69. }
  70. /**
  71. * Set the flvtool2 binary path
  72. */
  73. if(!defined('PHPVIDEOTOOLKIT_FLVTOOLS_BINARY'))
  74. {
  75. define('PHPVIDEOTOOLKIT_FLVTOOLS_BINARY', '/usr/bin/flvtool2');
  76. }
  77. /**
  78. * Set the watermark vhook path
  79. */
  80. if(!defined('PHPVIDEOTOOLKIT_FFMPEG_WATERMARK_VHOOK'))
  81. {
  82. define('PHPVIDEOTOOLKIT_FFMPEG_WATERMARK_VHOOK', '/usr/local/lib/vhook/watermark.so');
  83. }
  84. /**
  85. * Set the memcoder path
  86. */
  87. if(!defined('PHPVIDEOTOOLKIT_MENCODER_BINARY'))
  88. {
  89. define('PHPVIDEOTOOLKIT_MENCODER_BINARY', '/usr/local/bin/mencoder');
  90. }
  91. class PHPVideoToolkit
  92. {
  93. public $version = '0.1.5';
  94. /**
  95. * Error strings
  96. */
  97. private $_messages = array(
  98. 'generic_temp_404' => 'The temporary directory does not exist.',
  99. 'generic_temp_writable' => 'The temporary directory is not write-able by the web server.',
  100. 'getFileInfo_no_input' => 'Input file does not exist so no information can be retrieved.',
  101. 'streamFLV_no_input' => 'Input file has not been set so the FLV cannot be streamed.',
  102. 'streamFLV_passed_eof' => 'You have tried to stream to a point in the file that does not exit.',
  103. 'setInputFile_file_existence' => 'Input file "#file" does not exist',
  104. 'extractAudio_valid_format' => 'Value "#format" set from $toolkit->extractAudio, is not a valid audio format. Valid values ffmpeg self::FORMAT_AAC, PHPVideoToolkit::FORMAT_AIFF, PHPVideoToolkit::FORMAT_MP2, PHPVideoToolkit::FORMAT_MP3, PHPVideoToolkit::FORMAT_MP4, PHPVideoToolkit::FORMAT_MPEG4, PHPVideoToolkit::FORMAT_M4A or PHPVideoToolkit::FORMAT_WAV. If you wish to specifically try to set another format you should use the advanced function $toolkit->addCommand. Set $command to "-f" and $argument to your required value.',
  105. 'extractFrame_video_frame_rate_404' => 'You have attempted to extract a thumbnail from a video while automagically guessing the framerate of the video, but the framerate could not be accessed. You can remove this error by manually setting the frame rate of the video.',
  106. 'extractFrame_video_info_404' => 'You have attempted to extract a thumbnail from a video and check to see if the thumbnail exists, however it was not possible to access the video information. Please check your temporary directory permissions for read/write access by the webserver.',
  107. 'extractFrame_video_frame_count' => 'You have attempted to extract a thumbnail from a video but the thumbnail you are trying to extract does not exist in the video.',
  108. 'extractFrames_video_begin_frame_count' => 'You have attempted to extract thumbnails from a video but the thumbnail you are trying to start the extraction from does not exist in the video.',
  109. 'extractFrames_video_end_frame_count' => 'You have attempted to extract thumbnails from a video but the thumbnail you are trying to end the extraction at does not exist in the video.',
  110. 'setFormat_valid_format' => 'Value "#format" set from $toolkit->setFormat, is not a valid format. Valid values are PHPVideoToolkit::FORMAT_3GP2, PHPVideoToolkit::FORMAT_3GP, PHPVideoToolkit::FORMAT_AAC, PHPVideoToolkit::FORMAT_AIFF, PHPVideoToolkit::FORMAT_AMR, PHPVideoToolkit::FORMAT_ASF, PHPVideoToolkit::FORMAT_AVI, PHPVideoToolkit::FORMAT_FLV, PHPVideoToolkit::FORMAT_GIF, PHPVideoToolkit::FORMAT_MJ2, PHPVideoToolkit::FORMAT_MP2, PHPVideoToolkit::FORMAT_MP3, PHPVideoToolkit::FORMAT_MP4, PHPVideoToolkit::FORMAT_MPEG4, PHPVideoToolkit::FORMAT_M4A, PHPVideoToolkit::FORMAT_MPEG, PHPVideoToolkit::FORMAT_MPEG1, PHPVideoToolkit::FORMAT_MPEG2, PHPVideoToolkit::FORMAT_MPEGVIDEO, PHPVideoToolkit::FORMAT_PSP, PHPVideoToolkit::FORMAT_RM, PHPVideoToolkit::FORMAT_SWF, PHPVideoToolkit::FORMAT_VOB, PHPVideoToolkit::FORMAT_WAV, PHPVideoToolkit::FORMAT_JPG. If you wish to specifically try to set another format you should use the advanced function $toolkit->addCommand. Set $command to "-f" and $argument to your required value.',
  111. 'setAudioSampleFrequency_valid_frequency' => 'Value "#frequency" set from $toolkit->setAudioSampleFrequency, is not a valid integer. Valid values are 11025, 22050, 44100. If you wish to specifically try to set another frequency you should use the advanced function $toolkit->addCommand. Set $command to "-ar" and $argument to your required value.',
  112. 'setAudioFormat_valid_format' => 'Value "#format" set from $toolkit->setAudioFormat, is not a valid format. Valid values are PHPVideoToolkit::FORMAT_AAC, PHPVideoToolkit::FORMAT_AIFF, PHPVideoToolkit::FORMAT_AMR, PHPVideoToolkit::FORMAT_ASF, PHPVideoToolkit::FORMAT_MP2, PHPVideoToolkit::FORMAT_MP3, PHPVideoToolkit::FORMAT_MP4, PHPVideoToolkit::FORMAT_MPEG2, PHPVideoToolkit::FORMAT_RM, PHPVideoToolkit::FORMAT_WAV. If you wish to specifically try to set another format you should use the advanced function $toolkit->addCommand. Set $command to "-acodec" and $argument to your required value.',
  113. 'setVideoFormat_valid_format' => 'Value "#format" set from $toolkit->setAudioFormat, is not a valid format. Valid values are PHPVideoToolkit::FORMAT_3GP2, PHPVideoToolkit::FORMAT_3GP, PHPVideoToolkit::FORMAT_AVI, PHPVideoToolkit::FORMAT_FLV, PHPVideoToolkit::FORMAT_GIF, PHPVideoToolkit::FORMAT_MJ2, PHPVideoToolkit::FORMAT_MP4, PHPVideoToolkit::FORMAT_MPEG4, PHPVideoToolkit::FORMAT_M4A, PHPVideoToolkit::FORMAT_MPEG, PHPVideoToolkit::FORMAT_MPEG1, PHPVideoToolkit::FORMAT_MPEG2, PHPVideoToolkit::FORMAT_MPEGVIDEO. If you wish to specifically try to set another format you should use the advanced function $toolkit->addCommand. Set $command to "-vcodec" and $argument to your required value.',
  114. 'setAudioBitRate_valid_bitrate' => 'Value "#bitrate" set from $toolkit->setAudioBitRate, is not a valid integer. Valid values are 16, 32, 64, 128. If you wish to specifically try to set another bitrate you should use the advanced function $toolkit->addCommand. Set $command to "-ab" and $argument to your required value.',
  115. 'prepareImagesForConversionToVideo_one_img' => 'When compiling a movie from a series of images, you must include at least one image.',
  116. 'prepareImagesForConversionToVideo_img_404' => '"#img" does not exist.',
  117. 'prepareImagesForConversionToVideo_img_copy' => '"#img" can not be copied to "#tmpfile"',
  118. 'prepareImagesForConversionToVideo_img_type' => 'The images can not be prepared for conversion to video. Please make sure all images are of the same type, ie gif, png, jpeg and then try again.',
  119. 'setVideoOutputDimensions_valid_format' => 'Value "#format" set from $toolkit->setVideoOutputDimensions, is not a valid preset dimension. Valid values are PHPVideoToolkit::SIZE_SQCIF, PHPVideoToolkit::SIZE_SAS, PHPVideoToolkit::SIZE_QCIF, PHPVideoToolkit::SIZE_CIF, PHPVideoToolkit::SIZE_4CIF, PHPVideoToolkit::SIZE_QQVGA, PHPVideoToolkit::SIZE_QVGA, PHPVideoToolkit::SIZE_VGA, PHPVideoToolkit::SIZE_SVGA, PHPVideoToolkit::SIZE_XGA, PHPVideoToolkit::SIZE_UXGA, PHPVideoToolkit::SIZE_QXGA, PHPVideoToolkit::SIZE_SXGA, PHPVideoToolkit::SIZE_QSXGA, PHPVideoToolkit::SIZE_HSXGA, PHPVideoToolkit::SIZE_WVGA, PHPVideoToolkit::SIZE_WXGA, PHPVideoToolkit::SIZE_WSXGA, PHPVideoToolkit::SIZE_WUXGA, PHPVideoToolkit::SIZE_WOXGA, PHPVideoToolkit::SIZE_WQSXGA, PHPVideoToolkit::SIZE_WQUXGA, PHPVideoToolkit::SIZE_WHSXGA, PHPVideoToolkit::SIZE_WHUXGA, PHPVideoToolkit::SIZE_CGA, PHPVideoToolkit::SIZE_EGA, PHPVideoToolkit::SIZE_HD480, PHPVideoToolkit::SIZE_HD720, PHPVideoToolkit::SIZE_HD1080. You can also manually set the width and height.',
  120. 'setVideoOutputDimensions_sas_dim' => 'It was not possible to determine the input video dimensions so it was not possible to continue. If you wish to override this error please change the call to setVideoOutputDimensions and add a true argument to the arguments list... setVideoOutputDimensions(PHPVideoToolkit::SIZE_SAS, true);',
  121. 'setVideoOutputDimensions_valid_integer' => 'You tried to set the video output dimensions to an odd number. FFmpeg requires that the video output dimensions are of event value and divisible by 2. ie 2, 4, 6,... etc',
  122. 'setVideoAspectRatio_valid_ratio' => 'Value "#ratio" set from $toolkit->setVideoOutputDimensions, is not a valid preset dimension. Valid values are PHPVideoToolkit::RATIO_STANDARD, PHPVideoToolkit::RATIO_WIDE, PHPVideoToolkit::RATIO_CINEMATIC. If you wish to specifically try to set another video aspect ratio you should use the advanced function $toolkit->addCommand. Set $command to "-aspect" and $argument to your required value.',
  123. 'addWatermark_img_404' => 'Watermark file "#watermark" does not exist.',
  124. 'addWatermark_vhook_disabled' => 'Vhooking is not enabled in your FFmpeg binary. In order to allow video watermarking you must have FFmpeg compiled with --enable-vhook set. You can however watermark any extracted images using GD. To enable frame watermarking, call $toolkit->addGDWatermark($file) before you execute the extraction.',
  125. 'addVideo_file_404' => 'File "#file" does not exist.',
  126. 'setOutput_output_dir_404' => 'Output directory "#dir" does not exist!',
  127. 'setOutput_output_dir_writable' => 'Output directory "#dir" is not writable!',
  128. 'setOutput_%_missing' => 'The output of this command will be images yet you have not included the "%index" or "%timecode" in the $output_name.',
  129. 'setOutput_%d_depreciated' => 'The use of %d in the output file name is now depreciated. Please use %index. Number padding is still supported. You may also use %timecode instead to add a timecode to the filename.',
  130. 'execute_input_404' => 'Execute error. Input file missing.',
  131. 'execute_output_not_set' => 'Execute error. Output not set.',
  132. 'execute_overwrite_process' => 'Execute error. A file exists in the temp directory and is of the same name as this process file. It will conflict with this conversion. Conversion stopped.',
  133. 'execute_overwrite_fail' => 'Execute error. Output file exists. Process halted. If you wish to automatically overwrite files set the third argument in "PHPVideoToolkit::setOutput();" to "PHPVideoToolkit::OVERWRITE_EXISTING".',
  134. 'execute_partial_error' => 'Execute error. Output for file "#input" encountered a partial error. Files were generated, however one or more of them were empty.',
  135. 'execute_image_error' => 'Execute error. Output for file "#input" was not found. No images were generated.',
  136. 'execute_output_404' => 'Execute error. Output for file "#input" was not found. Please check server write permissions and/or available codecs compiled with FFmpeg. You can check the encode decode availability by inspecting the output array from PHPVideoToolkit::getFFmpegInfo().',
  137. 'execute_output_empty' => 'Execute error. Output for file "#input" was found, but the file contained no data. Please check the available codecs compiled with FFmpeg can support this type of conversion. You can check the encode decode availability by inspecting the output array from PHPVideoToolkit::getFFmpegInfo().',
  138. 'execute_image_file_exists' => 'Execute error. There is a file name conflict. The file "#file" already exists in the filesystem. If you wish to automatically overwrite files set the third argument in "PHPVideoToolkit::setOutput();" to "PHPVideoToolkit::OVERWRITE_EXISTING".',
  139. 'execute_result_ok_but_unwritable' => 'Process Partially Completed. The process successfully completed however it was not possible to output to "#output". The output was left in the temp directory "#process" for a manual file movement.',
  140. 'execute_result_ok' => 'Process Completed. The process successfully completed. Output was generated to "#output".',
  141. 'ffmpeg_log_ffmpeg_output' => 'OUTPUT',
  142. 'ffmpeg_log_ffmpeg_result' => 'RESULT',
  143. 'ffmpeg_log_ffmpeg_command' => 'COMMAND',
  144. 'ffmpeg_log_ffmpeg_join_gunk' => 'FFMPEG JOIN OUTPUT',
  145. 'ffmpeg_log_ffmpeg_gunk' => 'FFMPEG OUTPUT',
  146. 'ffmpeg_log_separator' => '-------------------------------'
  147. );
  148. /**
  149. * Process Results from PHPVideoToolkit::execute
  150. */
  151. // any return value with this means everything is ok
  152. const RESULT_OK = true;
  153. // any return value with this means the file has been processed/converted ok however it was
  154. // not able to be written to the output address. If this occurs you will need to move the
  155. // processed file manually from the temp location
  156. const RESULT_OK_BUT_UNWRITABLE = -1;
  157. /**
  158. * Codec support constants
  159. */
  160. const ENCODE = 'encode';
  161. const DECODE = 'decode';
  162. /**
  163. * Overwrite constants used in setOutput
  164. */
  165. const OVERWRITE_FAIL = 'fail';
  166. const OVERWRITE_PRESERVE = 'preserve';
  167. const OVERWRITE_EXISTING = 'existing';
  168. const OVERWRITE_UNIQUE = 'unique';
  169. /**
  170. * Formats supported
  171. * 3g2 3gp2 format
  172. * 3gp 3gp format
  173. * aac ADTS AAC
  174. * aiff Audio IFF
  175. * amr 3gpp amr file format
  176. * asf asf format
  177. * avi avi format
  178. * flv flv format
  179. * gif GIF Animation
  180. * mov mov format
  181. * mov,mp4,m4a,3gp,3g2,mj2 QuickTime/MPEG4/Motion JPEG 2000 format
  182. * mp2 MPEG audio layer 2
  183. * mp3 MPEG audio layer 3
  184. * mp4 mp4 format
  185. * mpeg MPEG1 System format
  186. * mpeg1video MPEG video
  187. * mpeg2video MPEG2 video
  188. * mpegvideo MPEG video
  189. * psp psp mp4 format
  190. * rm rm format
  191. * swf Flash format
  192. * vob MPEG2 PS format (VOB)
  193. * wav wav format
  194. * jpeg mjpeg format
  195. * yuv4mpegpipe yuv4mpegpipe format
  196. */
  197. const FORMAT_3GP2 = '3g2';
  198. const FORMAT_3GP = '3gp';
  199. const FORMAT_AAC = 'aac';
  200. const FORMAT_AIFF = 'aiff';
  201. const FORMAT_AMR = 'amr';
  202. const FORMAT_ASF = 'asf';
  203. const FORMAT_AVI = 'avi';
  204. const FORMAT_FLV = 'flv';
  205. const FORMAT_GIF = 'gif';
  206. const FORMAT_MJ2 = 'mj2';
  207. const FORMAT_MP2 = 'mp2';
  208. const FORMAT_MP3 = 'mp3';
  209. const FORMAT_MP4 = 'mp4';
  210. const FORMAT_MPEG4 = 'mpeg4';
  211. const FORMAT_M4A = 'm4a';
  212. const FORMAT_MPEG = 'mpeg';
  213. const FORMAT_MPEG1 = 'mpeg1video';
  214. const FORMAT_MPEG2 = 'mpeg2video';
  215. const FORMAT_MPEGVIDEO = 'mpegvideo';
  216. const FORMAT_PSP = 'psp';
  217. const FORMAT_RM = 'rm';
  218. const FORMAT_SWF = 'swf';
  219. const FORMAT_VOB = 'vob';
  220. const FORMAT_WAV = 'wav';
  221. const FORMAT_JPG = 'mjpeg';
  222. const FORMAT_Y4MP = 'yuv4mpegpipe';
  223. /**
  224. * Size Presets
  225. */
  226. const SIZE_SAS = 'SameAsSource';
  227. const SIZE_SQCIF = '128x96';
  228. const SIZE_QCIF = '176x144';
  229. const SIZE_CIF = '352x288';
  230. const SIZE_4CIF = '704x576';
  231. const SIZE_QQVGA = '160x120';
  232. const SIZE_QVGA = '320x240';
  233. const SIZE_VGA = '640x480';
  234. const SIZE_SVGA = '800x600';
  235. const SIZE_XGA = '1024x768';
  236. const SIZE_UXGA = '1600x1200';
  237. const SIZE_QXGA = '2048x1536';
  238. const SIZE_SXGA = '1280x1024';
  239. const SIZE_QSXGA = '2560x2048';
  240. const SIZE_HSXGA = '5120x4096';
  241. const SIZE_WVGA = '852x480';
  242. const SIZE_WXGA = '1366x768';
  243. const SIZE_WSXGA = '1600x1024';
  244. const SIZE_WUXGA = '1920x1200';
  245. const SIZE_WOXGA = '2560x1600';
  246. const SIZE_WQSXGA = '3200x2048';
  247. const SIZE_WQUXGA = '3840x2400';
  248. const SIZE_WHSXGA = '6400x4096';
  249. const SIZE_WHUXGA = '7680x4800';
  250. const SIZE_CGA = '320x200';
  251. const SIZE_EGA = '640x350';
  252. const SIZE_HD480 = '852x480';
  253. const SIZE_HD720 = '1280x720';
  254. const SIZE_HD1080 = '1920x1080';
  255. /**
  256. * Ratio Presets
  257. */
  258. const RATIO_STANDARD = '4:3';
  259. const RATIO_WIDE = '16:9';
  260. const RATIO_CINEMATIC = '1.85';
  261. /**
  262. * A public var that is to the information available about
  263. * the current ffmpeg compiled binary.
  264. * @var mixed
  265. * @access public
  266. */
  267. public static $ffmpeg_info = false;
  268. /**
  269. * A private var that contains the info of any file that is accessed by PHPVideoToolkit::getFileInfo();
  270. * @var array
  271. * @access private
  272. */
  273. private static $_file_info = array();
  274. /**
  275. * Determines what happens when an error occurs
  276. * @var boolean If true then the script will die, if not false is return by the error
  277. * @access public
  278. */
  279. public $on_error_die = false;
  280. /**
  281. * Holds the log file name
  282. * @var string
  283. * @access private
  284. */
  285. private $_log_file = null;
  286. /**
  287. * Determines if when outputting image frames if the outputted files should have the %d number
  288. * replaced with the frames timecode.
  289. * @var boolean If true then the files will be renamed.
  290. * @access public
  291. */
  292. public $image_output_timecode = true;
  293. /**
  294. * Holds the timecode separator for when using $image_output_timecode = true
  295. * Not all systems allow ':' in filenames.
  296. * @var string
  297. * @access public
  298. */
  299. public $timecode_seperator_output = '-';
  300. /**
  301. * Holds the starting time code when outputting image frames.
  302. * @var string The timecode hh(n):mm:ss:ff
  303. * @access private
  304. */
  305. private $_image_output_timecode_start = '00:00:00.00';
  306. /**
  307. * The format in which the image %timecode placeholder string is outputted.
  308. * - %hh (hours) representative of hours
  309. * - %mm (minutes) representative of minutes
  310. * - %ss (seconds) representative of seconds
  311. * - %fn (frame number) representative of frames (of the current second, not total frames)
  312. * - %ms (milliseconds) representative of milliseconds (of the current second, not total milliseconds) (rounded to 3 decimal places)
  313. * - %ft (frames total) representative of total frames (ie frame number)
  314. * - %st (seconds total) representative of total seconds (rounded).
  315. * - %sf (seconds floored) representative of total seconds (floored).
  316. * - %mt (milliseconds total) representative of total milliseconds. (rounded to 3 decimal places)
  317. * NOTE; there are special characters that will be replace by PHPVideoToolkit::$timecode_seperator_output, these characters are
  318. * - :
  319. * - .
  320. * @var string
  321. * @access public
  322. */
  323. private $image_output_timecode_format = '%hh-%mm-%ss-%fn';
  324. /**
  325. * Holds the fps of image extracts
  326. * @var integer
  327. * @access private
  328. */
  329. private $_image_output_timecode_fps = 1;
  330. /**
  331. * Holds the current execute commands that will need to be combined
  332. * @var array
  333. * @access private
  334. */
  335. private $_commands = array();
  336. /**
  337. * Holds the commands executed
  338. * @var array
  339. * @access private
  340. */
  341. private $_processed = array();
  342. /**
  343. * Holds the file references to those that have been processed
  344. * @var array
  345. * @access private
  346. */
  347. private $_files = array();
  348. /**
  349. * Holds the errors encountered
  350. * @access private
  351. * @var array
  352. */
  353. private $_errors = array();
  354. /**
  355. * Holds the input file / input file sequence
  356. * @access private
  357. * @var string
  358. */
  359. private $_input_file = null;
  360. /**
  361. * Holds the output file / output file sequence
  362. * @access private
  363. * @var string
  364. */
  365. private $_output_address = null;
  366. /**
  367. * Holds the process file / process file sequence
  368. * @access private
  369. * @var string
  370. */
  371. private $_process_address = null;
  372. /**
  373. * Temporary filename prefix
  374. * @access private
  375. * @var string
  376. */
  377. private $_tmp_file_prefix = 'tmp_';
  378. /**
  379. * Holds the temporary directory name
  380. * @access private
  381. * @var string
  382. */
  383. private $_tmp_directory = null;
  384. /**
  385. * Holds the directory paths that need to be removed by the ___destruct function
  386. * @access private
  387. * @var array
  388. */
  389. private $_unlink_dirs = array();
  390. /**
  391. * Holds the file paths that need to be deleted by the ___destruct function
  392. * @access private
  393. * @var array
  394. */
  395. private $_unlink_files = array();
  396. /**
  397. * Holds the timer start micro-float.
  398. * @access private
  399. * @var integer
  400. */
  401. private $_timer_start = 0;
  402. /**
  403. * Holds the times taken to process each file.
  404. * @access private
  405. * @var array
  406. */
  407. private $_timers = array();
  408. /**
  409. * Holds the times taken to process each file.
  410. * @access private
  411. * @var constant
  412. */
  413. private $_overwrite_mode = null;
  414. /**
  415. * Holds a integer value that flags if the image extraction is just a single frame.
  416. * @access private
  417. * @var integer
  418. */
  419. private $_single_frame_extraction = null;
  420. /**
  421. * Holds the watermark file that is used to watermark any outputted images via GD.
  422. * @access private
  423. * @var string
  424. */
  425. private $_watermark_url = null;
  426. /**
  427. * Holds the watermark options used to watermark any outputted images via GD.
  428. * @access private
  429. * @var array
  430. */
  431. private $_watermark_options = null;
  432. /**
  433. * Holds the number of files processed per run.
  434. * @access private
  435. * @var integer
  436. */
  437. private $_process_file_count = 0;
  438. /**
  439. * Holds the times taken to process each file.
  440. * @access private
  441. * @var array
  442. */
  443. private $_post_processes = array();
  444. /**
  445. * Holds the times taken to process each file.
  446. * @access private
  447. * @var array
  448. */
  449. private static $_static = true;
  450. /**
  451. * Holds commands should be sent added to the exec before the input file, this is by no means a definitive list
  452. * of all the ffmpeg commands, as it only utilizes the ones in use by this class. Also only commands that have
  453. * specific required places are entered in the arrays below. Anything not in these arrays will be treated as an
  454. * after-input item.
  455. * @access private
  456. * @var array
  457. */
  458. // private $_cmds_before_input = array();
  459. private $_cmds_before_input = array('-inputr');
  460. // private $_cmds_before_input = array('-r', '-f');
  461. /**
  462. * Constructs the class and sets the temporary directory.
  463. *
  464. * @access private
  465. * @param string $tmp_directory A full absolute path to you temporary directory
  466. */
  467. function __construct($tmp_directory='/tmp/')
  468. {
  469. $this->_tmp_directory = $tmp_directory;
  470. PHPVideoToolkit::$_static = false;
  471. }
  472. public static function microtimeFloat()
  473. {
  474. list($usec, $sec) = explode(" ", microtime());
  475. return ((float) $usec + (float) $sec);
  476. }
  477. /**
  478. * Resets the class
  479. *
  480. * @access public
  481. * @param boolean $keep_input_file Determines whether or not to reset the input file currently set.
  482. */
  483. public function reset($keep_input_file=false, $keep_processes=false)
  484. {
  485. if($keep_input_file === false)
  486. {
  487. $this->_input_file = null;
  488. }
  489. if($keep_processes === false)
  490. {
  491. $this->_post_processes = array();
  492. }
  493. $this->_single_frame_extraction = null;
  494. $this->_output_address = null;
  495. $this->_process_address = null;
  496. $this->_log_file = null;
  497. $this->_commands = array();
  498. $this->_timer_start = 0;
  499. $this->_process_file_count = 0;
  500. $this->__destruct();
  501. }
  502. /**
  503. * Returns information about the specified file without having to use ffmpeg-php
  504. * as it consults the ffmpeg binary directly.
  505. *
  506. * @access public
  507. * @param string $tmp_directory A full absolute path to you temporary directory. Only needed in a static call.
  508. * @return mixed false on error encountered, true otherwise
  509. **/
  510. public function getFFmpegInfo($tmp_directory='/tmp/')
  511. {
  512. // check to see if the info has already been cached
  513. if(PHPVideoToolkit::$ffmpeg_info !== false)
  514. {
  515. return PHPVideoToolkit::$ffmpeg_info;
  516. }
  517. // check to see if this is a static call
  518. if(PHPVideoToolkit::$_static === true)
  519. {
  520. $toolkit = new PHPVideoToolkit($tmp_directory);
  521. return $toolkit->getFFmpegInfo();
  522. }
  523. $format = '';
  524. // $info_file = $this->_tmp_directory.$this->unique('ffinfo').'.info';
  525. // execute the ffmpeg lookup
  526. // exec(PHPVIDEOTOOLKIT_FFMPEG_BINARY.' -formats &> '.$info_file);
  527. exec(PHPVIDEOTOOLKIT_FFMPEG_BINARY.' -formats 2>&1', $buffer);
  528. $buffer = implode("\r\n", $buffer);
  529. // die($buffer);
  530. // $data = false;
  531. // try to open the file
  532. // $handle = fopen($info_file, 'r');
  533. // if($handle)
  534. // {
  535. $data = array();
  536. // $buffer = '';
  537. // loop through the lines of data and collect the buffer
  538. // while (!feof($handle))
  539. // {
  540. // $buffer .= fgets($handle, 4096);
  541. // }
  542. // echo($buffer);
  543. $data['compiler'] = array();
  544. $look_ups = array('configuration'=>'configuration: ', 'formats'=>'File formats:', 'codecs'=>'Codecs:', 'filters'=>'Bitstream filters:', 'protocols'=>'Supported file protocols:', 'abbreviations'=>'Frame size, frame rate abbreviations:', 'Note:');
  545. $total_lookups = count($look_ups);
  546. $pregs = array();
  547. $indexs = array();
  548. foreach($look_ups as $key=>$reg)
  549. {
  550. if(strpos($buffer, $reg) !== false)
  551. {
  552. $index = array_push($pregs, $reg);
  553. $indexs[$key] = $index;
  554. }
  555. }
  556. preg_match('/'.implode('(.*)', $pregs).'/s', $buffer, $matches);
  557. $configuration = trim($matches[$indexs['configuration']]);
  558. // grab the ffmpeg configuration flags
  559. preg_match_all('/--[a-zA-Z0-9\-]+/', $configuration, $config_flags);
  560. $data['compiler']['configuration'] = $config_flags[0];
  561. $data['compiler']['vhook-support'] = in_array('--enable-vhook', $config_flags[0]) && !in_array('--disable-vhook', $config_flags[0]);
  562. // grab the versions
  563. $data['compiler']['versions'] = array();
  564. preg_match_all('/([a-zA-Z0-9\-]+) version: ([0-9\.]+)/', $configuration, $versions);
  565. for($i=0, $a=count($versions[0]); $i<$a; $i++)
  566. {
  567. $data['compiler']['versions'][strtolower(trim($versions[1][$i]))] = $versions[2][$i];
  568. }
  569. // grab the ffmpeg compile info
  570. preg_match('/built on (.*), gcc: (.*)/', $configuration, $conf);
  571. if(count($conf) > 0)
  572. {
  573. $data['compiler']['gcc'] = $conf[2];
  574. $data['compiler']['build_date'] = $conf[1];
  575. $data['compiler']['build_date_timestamp'] = strtotime($conf[1]);
  576. }
  577. // grab the file formats available to ffmpeg
  578. preg_match_all('/ (DE|D|E) (.*) {1,} (.*)/', trim($matches[$indexs['formats']]), $formats);
  579. $data['formats'] = array();
  580. // loop and clean
  581. for($i=0, $a=count($formats[0]); $i<$a; $i++)
  582. {
  583. $data['formats'][strtolower(trim($formats[2][$i]))] = array(
  584. 'encode' => $formats[1][$i] == 'DE' || $formats[1][$i] == 'E',
  585. 'decode' => $formats[1][$i] == 'DE' || $formats[1][$i] == 'D',
  586. 'fullname' => $formats[3][$i]
  587. );
  588. }
  589. // grab the bitstream filters available to ffmpeg
  590. $data['filters'] = array();
  591. if(isset($indexs['filters']) && isset($matches[$indexs['filters']]))
  592. {
  593. $filters = trim($matches[$indexs['filters']]);
  594. if(empty($filters))
  595. {
  596. $data['filters'] = explode(' ', $filters);
  597. }
  598. }
  599. // grab the file prototcols available to ffmpeg
  600. $data['filters'] = array();
  601. if(isset($indexs['protocols']) && isset($matches[$indexs['protocols']]))
  602. {
  603. $protocols = trim($matches[$indexs['protocols']]);
  604. if(empty($protocols))
  605. {
  606. $data['protocols'] = explode(' ', str_replace(':', '', $protocols));
  607. }
  608. }
  609. // grab the abbreviations available to ffmpeg
  610. $data['abbreviations'] = array();
  611. if(isset($indexs['abbreviations']) && isset($matches[$indexs['abbreviations']]))
  612. {
  613. $abbreviations = trim($matches[$indexs['abbreviations']]);
  614. if(empty($abbreviations))
  615. {
  616. $data['abbreviations'] = explode(' ', $abbreviations);
  617. }
  618. }
  619. PHPVideoToolkit::$ffmpeg_info = $data;
  620. // }
  621. // fclose($handle);
  622. // if(is_file($info_file))
  623. // {
  624. // if the info file exists remove it
  625. // unlink($info_file);
  626. // }
  627. $data['ffmpeg-php-support'] = $this->hasFFmpegPHPSupport();
  628. return $data;
  629. }
  630. /**
  631. * Determines if your ffmpeg has particular codec support for encode or decode.
  632. *
  633. * @access public
  634. * @param string $codec The name of the codec you are checking for.
  635. * @param const $support PHPVideoToolkit::ENCODE or PHPVideoToolkit::DECODE, depending on which functionality is desired.
  636. * @return mixed. Boolean false if there is no support, true if there is support.
  637. */
  638. public function hasCodecSupport($codec, $support=PHPVideoToolkit::ENCODE)
  639. {
  640. $codec = strtolower($codec);
  641. $data = $this->getFFmpegInfo();
  642. return isset($data['formats'][$codec]) ? $data['formats'][$codec][$support] : false;
  643. }
  644. /**
  645. * Determines the type of support that exists for the FFmpeg-PHP module.
  646. *
  647. * @access public
  648. * @return mixed. Boolean false if there is no support, String 'module' if the actuall
  649. * FFmpeg-PHP module is loaded, or String 'emulated' if the FFmpeg-PHP classes
  650. * can be emulated through the adapter classes.
  651. */
  652. public function hasFFmpegPHPSupport()
  653. {
  654. return extension_loaded('ffmpeg') ? 'module' : (is_file(dirname(__FILE__).DIRECTORY_SEPARATOR.'adapters'.DIRECTORY_SEPARATOR.'ffmpeg-php'.DIRECTORY_SEPARATOR.'ffmpeg_movie.php') && is_file(dirname(__FILE__).DIRECTORY_SEPARATOR.'adapters'.DIRECTORY_SEPARATOR.'ffmpeg-php'.DIRECTORY_SEPARATOR.'ffmpeg_frame.php') && is_file(dirname(__FILE__).DIRECTORY_SEPARATOR.'adapters'.DIRECTORY_SEPARATOR.'ffmpeg-php'.DIRECTORY_SEPARATOR.'ffmpeg_animated_gif.php') ? 'emulated' : false);
  655. }
  656. /**
  657. * Determines if the ffmpeg binary has been compiled with vhook support.
  658. *
  659. * @access public
  660. * @return mixed. Boolean false if there is no support, true there is support.
  661. */
  662. public function hasVHookSupport()
  663. {
  664. $info = $this->getFFmpegInfo();
  665. return $info['compiler']['vhook-support'];
  666. }
  667. /**
  668. * Returns information about the specified file without having to use ffmpeg-php
  669. * as it consults the ffmpeg binary directly. This idea for this function has been borrowed from
  670. * a French ffmpeg class located: http://www.phpcs.com/codesource.aspx?ID=45279
  671. *
  672. * @access public
  673. * @todo Change the search from string explode to a regex based search
  674. * @param string $file The absolute path of the file that is required to be manipulated.
  675. * @return mixed false on error encountered, true otherwise
  676. **/
  677. public function getFileInfo($file=false, $tmp_directory='/tmp/')
  678. {
  679. // check to see if this is a static call
  680. if($file !== false && PHPVideoToolkit::$_static === true)
  681. {
  682. $toolkit = new PHPVideoToolkit($tmp_directory);
  683. return $toolkit->getFileInfo($file);
  684. }
  685. // if the file has not been specified check to see if an input file has been specified
  686. if($file === false)
  687. {
  688. if(!$this->_input_file)
  689. {
  690. // input file not valid
  691. return $this->_raiseError('getFileInfo_no_input');
  692. //<- exits
  693. }
  694. $file = $this->_input_file;
  695. }
  696. $file = escapeshellarg($file);
  697. // die($file);
  698. // create a hash of the filename
  699. $hash = md5($file);
  700. // check to see if the info has already been generated
  701. if(isset(self::$_file_info[$hash]))
  702. {
  703. return self::$_file_info[$hash];
  704. }
  705. // generate a random filename
  706. $info_file = $this->_tmp_directory.$this->unique($hash).'.info';
  707. // execute the ffmpeg lookup
  708. // exec(PHPVIDEOTOOLKIT_FFMPEG_BINARY.' -i '.$file.' &> '.$info_file);
  709. exec(PHPVIDEOTOOLKIT_FFMPEG_BINARY.' -i '.$file.' 2>&1', $buffer);
  710. $buffer = implode("\r\n", $buffer);
  711. // $data = false;
  712. // try to open the file
  713. // $handle = fopen($info_file, 'r');
  714. // if($handle)
  715. // {
  716. $data = array();
  717. // $buffer = '';
  718. // loop through the lines of data and collect the buffer
  719. // while (!feof($handle))
  720. // {
  721. // $buffer .= fgets($handle, 4096);
  722. // }
  723. // die($buffer);
  724. // grab the duration and bitrate data
  725. preg_match_all('/Duration: (.*)/', $buffer, $matches);
  726. if(count($matches) > 0)
  727. {
  728. $parts = explode(', ', trim($matches[1][0]));
  729. $data['duration'] = array();
  730. $timecode = $parts[0];
  731. $data['duration']['seconds'] = $this->timecodeToSeconds($timecode);
  732. $data['bitrate'] = intval(ltrim($parts[2], 'bitrate: '));
  733. $data['duration']['start'] = ltrim($parts[1], 'start: ');
  734. $data['duration']['timecode'] = array();
  735. $data['duration']['timecode']['rounded'] = substr($timecode, 0, 8);
  736. $data['duration']['timecode']['seconds'] = array();
  737. $data['duration']['timecode']['seconds']['exact'] = $timecode;
  738. $data['duration']['timecode']['seconds']['excess'] = intval(substr($timecode, 9));
  739. }
  740. // match the video stream info
  741. preg_match('/Stream(.*): Video: (.*)/', $buffer, $matches);
  742. if(count($matches) > 0)
  743. {
  744. $data['video'] = array();
  745. // get the dimension parts
  746. // print_r($matches);
  747. preg_match('/([0-9]{1,5})x([0-9]{1,5})/', $matches[2], $dimensions_matches);
  748. // print_r($dimensions_matches);
  749. $dimensions_value = $dimensions_matches[0];
  750. $data['video']['dimensions'] = array(
  751. 'width' => floatval($dimensions_matches[1]),
  752. 'height' => floatval($dimensions_matches[2])
  753. );
  754. // get the framerate
  755. preg_match('/([0-9\.]+) (fps|tb)\(r\)/', $matches[0], $fps_matches);
  756. $data['video']['frame_rate'] = floatval($fps_matches[1]);
  757. $fps_value = $fps_matches[0];
  758. // get the ratios
  759. preg_match('/\[PAR ([0-9\:\.]+) DAR ([0-9\:\.]+)\]/', $matches[0], $ratio_matches);
  760. if(count($ratio_matches))
  761. {
  762. $data['video']['pixel_aspect_ratio'] = $ratio_matches[1];
  763. $data['video']['display_aspect_ratio'] = $ratio_matches[2];
  764. }
  765. // work out the number of frames
  766. if(isset($data['duration']) && isset($data['video']))
  767. {
  768. // set the total frame count for the video
  769. $data['video']['frame_count'] = ceil($data['duration']['seconds'] * $data['video']['frame_rate']);
  770. // set the framecode
  771. $frames = ceil($data['video']['frame_rate']*($data['duration']['timecode']['seconds']['excess']/10));
  772. $data['duration']['timecode']['frames'] = array();
  773. $data['duration']['timecode']['frames']['exact'] = $data['duration']['timecode']['rounded'].'.'.$frames;
  774. $data['duration']['timecode']['frames']['excess'] = $frames;
  775. $data['duration']['timecode']['frames']['total'] = $data['video']['frame_count'];
  776. }
  777. // formats should be anything left over, let me know if anything else exists
  778. $parts = explode(',', $matches[2]);
  779. $other_parts = array($dimensions_value, $fps_value);
  780. $formats = array();
  781. foreach($parts as $key=>$part)
  782. {
  783. $part = trim($part);
  784. if(!in_array($part, $other_parts))
  785. {
  786. array_push($formats, $part);
  787. }
  788. }
  789. $data['video']['pixel_format'] = $formats[1];
  790. $data['video']['codec'] = $formats[0];
  791. }
  792. // match the audio stream info
  793. preg_match('/Stream(.*): Audio: (.*)/', $buffer, $matches);
  794. if(count($matches) > 0)
  795. {
  796. // setup audio values
  797. $data['audio'] = array(
  798. 'stereo' => -1,
  799. 'sample_rate' => -1,
  800. 'sample_rate' => -1
  801. );
  802. $other_parts = array();
  803. // get the stereo value
  804. preg_match('/(stereo|mono)/i', $matches[0], $stereo_matches);
  805. if(count($stereo_matches))
  806. {
  807. $data['audio']['stereo'] = $stereo_matches[0];
  808. array_push($other_parts, $stereo_matches[0]);
  809. }
  810. // get the sample_rate
  811. preg_match('/([0-9]{3,6}) Hz/', $matches[0], $sample_matches);
  812. if(count($sample_matches))
  813. {
  814. $data['audio']['sample_rate'] = count($sample_matches) ? floatval($sample_matches[1]) : -1;
  815. array_push($other_parts, $sample_matches[0]);
  816. }
  817. // get the bit rate
  818. preg_match('/([0-9]{1,3}) kb\/s/', $matches[0], $bitrate_matches);
  819. if(count($bitrate_matches))
  820. {
  821. $data['audio']['bitrate'] = count($bitrate_matches) ? floatval($bitrate_matches[1]) : -1;
  822. array_push($other_parts, $bitrate_matches[0]);
  823. }
  824. // formats should be anything left over, let me know if anything else exists
  825. $parts = explode(',', $matches[2]);
  826. $formats = array();
  827. foreach($parts as $key=>$part)
  828. {
  829. $part = trim($part);
  830. if(!in_array($part, $other_parts))
  831. {
  832. array_push($formats, $part);
  833. }
  834. }
  835. $data['audio']['codec'] = $formats[0];
  836. }
  837. // check that some data has been obtained
  838. if(!count($data))
  839. {
  840. $data = false;
  841. }
  842. else
  843. {
  844. $data['_raw_info'] = $buffer;
  845. }
  846. // fclose($handle);
  847. // }
  848. // if(is_file($info_file))
  849. // {
  850. // if the info file exists remove it
  851. // unlink($info_file);
  852. // }
  853. // cache info and return
  854. return self::$_file_info[$hash] = $data;
  855. }
  856. /**
  857. * Sets the input file that is going to be manipulated.
  858. *
  859. * @access public
  860. * @param string $file The absolute path of the file that is required to be manipulated.
  861. * @param mixed $input_frame_rate If 0 (default) then no input frame rate is set, if false it is automatically retreived, otherwise
  862. * any other integer will be set as the incoming frame rate.
  863. * @return boolean false on error encountered, true otherwise
  864. */
  865. public function setInputFile($file, $input_frame_rate=0)
  866. {
  867. $files_length = count($file);
  868. // if the total number of files entered is 1 then only one file is being processed
  869. if($files_length == 1)
  870. {
  871. // check the input file, if there is a %d in there or a similar %03d then the file inputted is a sequence, if neither of those is found
  872. // then qheck to see if the file exists
  873. if(!preg_match('/\%([0-9]+)d/', $file) && strpos($file, '%d') === false && !is_file($file))
  874. {
  875. // input file not valid
  876. return $this->_raiseError('setInputFile_file_existence', array('file'=>$file));
  877. //<- exits
  878. }
  879. $escaped_name = $file;
  880. // $escaped_name = escapeshellarg($files[0]);
  881. $this->_input_file = $escaped_name;
  882. $this->_input_file_id = md5($escaped_name);
  883. // the -inputr is a hack for -r to come before the input
  884. if($input_frame_rate !== 0)
  885. {
  886. $info = $this->getFileInfo();
  887. if(isset($info['video']))
  888. {
  889. if($input_frame_rate === false)
  890. {
  891. $input_frame_rate = $info['video']['frame_rate'];
  892. }
  893. // input frame rate is a command hack
  894. $this->addCommand('-inputr', $input_frame_rate);
  895. }
  896. }
  897. }
  898. else
  899. {
  900. // more than one video is being added as input so we must join them all
  901. call_user_func_array(array(&$this, 'addVideo'), array($file, $input_frame_rate));
  902. }
  903. return true;
  904. }
  905. /**
  906. * A shortcut for converting video to FLV.
  907. *
  908. * @access public
  909. * @param integer $audio_sample_frequency
  910. * @param integer $audio_bitrate
  911. */
  912. public function setFormatToFLV($audio_sample_frequency=44100, $audio_bitrate=64)
  913. {
  914. $this->addCommand('-sameq');
  915. $this->setAudioFormat(self::FORMAT_MP3);
  916. // adjust the audio rates
  917. $this->setAudioBitRate($audio_bitrate);
  918. $this->setAudioSampleFrequency($audio_sample_frequency);
  919. // set the video format
  920. $this->setFormat(self::FORMAT_FLV);
  921. // flag that the flv has to have meta data added after the excecution of this command
  922. // register the post tidy process
  923. $this->registerPostProcess('_addMetaToFLV', $this);
  924. }
  925. /**
  926. * When converting video to FLV the meta data has to be added by a ruby program called FLVTools2.
  927. * This is a second exec call only after the video has been converted to FLV
  928. * http://inlet-media.de/flvtool2
  929. *
  930. * @access private
  931. */
  932. private function _addMetaToFLV($files)
  933. {
  934. $file = array_pop($files);
  935. // prepare the command suitable for exec
  936. $exec_string = $this->_prepareCommand(PHPVIDEOTOOLKIT_FLVTOOLS_BINARY, '-U '.$file);
  937. // execute the command
  938. exec($exec_string);
  939. if(is_array($this->_processed[0]))
  940. {
  941. array_push($this->_processed[0], $exec_string);
  942. }
  943. else
  944. {
  945. $this->_processed[0] = array($this->_processed[0], $exec_string);
  946. }
  947. return true;
  948. }
  949. /**
  950. * Streams a FLV file from a given point. You can control bandwidth, cache and session options.
  951. * Inspired by xmoov-php
  952. * @see xmoov-php,
  953. * - @link http://xmoov.com/
  954. * - @author Eric Lorenzo Benjamin jr
  955. * @access public
  956. * @param integer $seek_pos The position in the file to seek to.
  957. * @param array|boolean $bandwidth_options If a boolean value, false then no bandwidth limiting will take place.
  958. * If true then bandwidth limiting will take place with packet_size = 90 and packet_interval = 0.3.
  959. * If an array the following values are default packet_size = 90 and packet_interval = 0.3, you will also
  960. * have to set active = true, ie array('active'=>true, 'packet_size'=>90, 'packet_interval'=>0.3)
  961. * @param boolean $allow_cache If true the file will be allowed to cache in the browser, if false then it won't
  962. * @return boolean
  963. */
  964. public function flvStreamSeek($seek_pos=0, $bandwidth_options=array(), $allow_cache=true)
  965. {
  966. // check for input file
  967. if(!$this->_input_file)
  968. {
  969. // input file not valid
  970. return $this->_raiseError('streamFLV_no_input');
  971. //<- exits
  972. }
  973. // make the pos safe
  974. $seek_pos = intval($seek_pos);
  975. // absorb the bandwidth options
  976. $bandwidth_options = is_array($bandwidth_options) ? array_merge(array('active'=>false, 'packet_size'=>90, 'packet_interval'=>0.3), $bandwidth_options) : array('active'=>$bandwidth_options, 'packet_size'=>90, 'packet_interval'=>0.3);
  977. // if this file is not allowed to be cached send cache headers for all browsers.
  978. if(!$allow_cache)
  979. {
  980. session_cache_limiter('nocache');
  981. header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
  982. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  983. header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
  984. header('Pragma: no-cache');
  985. }
  986. // open file
  987. $handle = fopen($this->_input_file, 'rb');
  988. $file_size = filesize($this->_input_file) - (($seek_pos > 0) ? $seek_pos + 1 : 0);
  989. // send the flv headers
  990. header('Content-Type: video/x-flv');
  991. header('Content-Disposition: attachment; filename="'.basename($this->_input_file).'"');
  992. header('Content-Length: '.$file_size);
  993. // flv format header
  994. if($seek_pos != 0)
  995. {
  996. print('FLV');
  997. print(pack('C', 1));
  998. print(pack('C', 1));
  999. print(pack('N', 9));
  1000. print(pack('N', 9));
  1001. }
  1002. // seek to the required point
  1003. if(fseek($handle, $seek_pos) === -1)
  1004. {
  1005. // input file not valid
  1006. return $this->_raiseError('streamFLV_passed_eof');
  1007. //<- exits
  1008. }
  1009. // if bandwidth control is active then workout the options
  1010. if($bandwidth_options['active'])
  1011. {
  1012. $packet_interval = intval($bandwidth_options['packet_interval']);
  1013. $packet_size = intval($bandwidth_options['packet_size']) * 1042;
  1014. }
  1015. // output the file
  1016. while(!feof($handle))
  1017. {
  1018. // limit the bandwidth
  1019. if($bandwidth_options['active'] && $packet_interval > 0)
  1020. {
  1021. // output the required packet
  1022. $time_start = self::microtimeFloat();
  1023. echo fread($handle, $packet_size);
  1024. $time_stop = self::microtimeFloat();
  1025. // delay the output
  1026. $time_difference = $time_stop - $time_start;
  1027. if($time_difference < $packet_interval)
  1028. {
  1029. usleep(($packet_interval * 1000000) - ($time_difference * 1000000));
  1030. }
  1031. }
  1032. // no bandwidth limiting
  1033. else
  1034. {
  1035. echo fread($handle, $file_size);
  1036. }
  1037. }
  1038. // close the file
  1039. fclose($handle);
  1040. return true;
  1041. }
  1042. /**
  1043. * This is an alias for setFormat, but restricts it to audio only formats.
  1044. *
  1045. * @access public
  1046. * @param integer $format A supported audio format.
  1047. * @param integer $audio_sample_frequency
  1048. * @param integer $audio_bitrate
  1049. **/
  1050. public function extractAudio($format=PHPVideoToolkit::FORMAT_MP3, $audio_sample_frequency=44100, $audio_bitrate=64)
  1051. {
  1052. // check the format is one of the audio formats
  1053. if(!in_array($format, array(self::FORMAT_AAC, self::FORMAT_AIFF, self::FORMAT_MP2, self::FORMAT_MP3, self::FORMAT_MP4, self::FORMAT_MPEG4, self::FORMAT_M4A, self::FORMAT_WAV)))
  1054. {
  1055. return $this->_raiseError('extractAudio_valid_format', array('format'=>$format));
  1056. //<- exits
  1057. }
  1058. $this->setFormat($format);
  1059. // adjust the audio rates
  1060. $this->setAudioBitRate($audio_bitrate);
  1061. $this->setAudioSampleFrequency($audio_sample_frequency);
  1062. }
  1063. /**
  1064. * Sets the new video format.
  1065. *
  1066. * @access public
  1067. * @param defined $format The format should use one of the defined variables stated below.
  1068. * PHPVideoToolkit::FORMAT_3GP2 - 3g2
  1069. * PHPVideoToolkit::FORMAT_3GP - 3gp
  1070. * PHPVideoToolkit::FORMAT_AAC - aac
  1071. * PHPVideoToolkit::FORMAT_AIFF - aiff
  1072. * PHPVideoToolkit::FORMAT_AMR - amr
  1073. * PHPVideoToolkit::FORMAT_ASF - asf
  1074. * PHPVideoToolkit::FORMAT_AVI - avi
  1075. * PHPVideoToolkit::FORMAT_FLV - flv
  1076. * PHPVideoToolkit::FORMAT_GIF - gif
  1077. * PHPVideoToolkit::FORMAT_MJ2 - mj2
  1078. * PHPVideoToolkit::FORMAT_MP2 - mp2
  1079. * PHPVideoToolkit::FORMAT_MP3 - mp3
  1080. * PHPVideoToolkit::FORMAT_MP4 - mp4
  1081. * PHPVideoToolkit::FORMAT_MPEG4 - mpeg4
  1082. * PHPVideoToolkit::FORMAT_M4A - m4a
  1083. * PHPVideoToolkit::FORMAT_MPEG - mpeg
  1084. * PHPVideoToolkit::FORMAT_MPEG1 - mpeg1video
  1085. * PHPVideoToolkit::FORMAT_MPEG2 - mpeg2video
  1086. * PHPVideoToolkit::FORMAT_MPEGVIDEO - mpegvideo
  1087. * PHPVideoToolkit::FORMAT_PSP - psp
  1088. * PHPVideoToolkit::FORMAT_RM - rm
  1089. * PHPVideoToolkit::FORMAT_SWF - swf
  1090. * PHPVideoToolkit::FORMAT_VOB - vob
  1091. * PHPVideoToolkit::FORMAT_WAV - wav
  1092. * PHPVideoToolkit::FORMAT_JPG - jpg
  1093. * @return boolean false on error encountered, true otherwise
  1094. */
  1095. public function setFormat($format)
  1096. {
  1097. // validate input
  1098. if(!in_array($format, array(self::FORMAT_3GP2, self::FORMAT_3GP, s

Large files files are truncated, but you can click here to view the full file