* @license PHP License * @package WB * @subpackage vfs */ WBClass::load('WBVFS_Mime'); /** * Virtual File System: Mime_Audio * * Mime handler for audio files. Default file name extension is "mp3" * Also all audio files are guessed to be mp3s * * * @version 0.3.0 * @package WB * @subpackage vfs */ class WBVFS_Mime_Audio extends WBVFS_Mime { /** * file name extension * @var string */ protected $extension = 'mp3'; /** * ffmpeg command * @link http://www.ffmpeg.org/ */ protected static $ffmpeg = 'ffmpeg'; /** * Configuration * @var WBConfig */ private $config; /** * initialize tools * * set command line tools */ public static function staticConstruct() { self::$ffmpeg = WBParam::get('wb/vfs/mime/ffmpeg', self::$ffmpeg); } /** * 2nd constructor * */ protected function init() { $this->config = WBClass::create('WBConfig'); $this->config->load('vfs/transcode/audio'); } /** * get information about this file * * @return array */ public function getInfo() { $ret = null; $out = array(); $cmd = sprintf('%s -hide_banner -vstats -i %s 2>&1', self::$ffmpeg, $this->file); exec($cmd, $out, $ret); $this->info = $this->parseFfprobe($out); return $this->info; } /** * Import File * */ public function import() { } /** * Get File Name of Requested File * * @param bool $redirect whether to redirect * @return string */ protected function doGetRequestedFile(&$redirect) { $this->file = $this->vfile->getPath(); $prefix = strtolower($this->requestedMimeMinor); if (WBVFS::MIME_PLAIN == $prefix) { $prefix = 'ogg'; } $this->extension = $this->config->get($prefix . '/extension', $prefix); if ($prefix == $this->vfile->getMime(WBVFS_File::MIME_MINOR)) { return $this->file; } $this->mimeMinor = $this->config->get($prefix . '/mimeminor', $prefix); $cacheDir = $this->mkCacheDir(); if (!file_exists($cacheDir . '/' . $prefix)) { // this sort of locks the file an prevents multi processings touch($cacheDir . '/' . $prefix); chmod($cacheDir . '/' . $prefix, 0666); $this->transcode($prefix, $cacheDir); } $this->file = $cacheDir . '/' . $prefix; return $this->file; } /** * Execute transcoding * * Set current file to file the one coresponding to requested mime minor type * Find matching transcoding targets in config. Populate and execute transcoding * commands. If there is a faststart tag, execute post processing command * * @param string $prefix * @param string $cacheDir */ private function transcode($prefix, $cacheDir) { $now = WBClock::now(); $cwd = $this->mkWorkingDir('audio'); $des = 'out.' . $prefix; // multi or single pass commands $cmd = $this->config->get($prefix . '/template/cmd', '{FFMPEG} -i {INFILE} -f mp3 -y {OUTFILE} 2>&1'); if (!is_array($cmd)) { $cmd = array($cmd); } $optionA = $this->config->get($prefix . '/option/audio', array()); if (!is_array($optionA)) { $optionA = trim($optionA); if (empty($optionA)) { $optionA = array(); } else { $optionA = array($optionA); } } $vars = array( 'cwd' => $cwd, 'presetdir' => WBParam::get('wb/dir/system') . '/resource/mime/video/ffmpeg', 'ffmpeg' => self::$ffmpeg, 'infile' => $this->file, 'outfile' => $des, 'option_audio' => implode(' ', $optionA) ); $oldcwd = getcwd(); chdir($cwd); // execute all commands foreach ($cmd as $c) { $c = WBString::populate($c, $vars); $out = array(); $ret = null; exec($c, $out, $ret); if ($ret > 0) { $log = array( 'file' => basename($this->file), 'size' => filesize($this->file), 'mime' => 'audio', 'action' => 'convert', 'prefix' => $prefix, 'cmd' => $c ); $this->log->err($log); } } rename($des, $cacheDir . '/' . $prefix); chdir($oldcwd); $this->rmWorkingDir($cwd); chmod($cacheDir . '/' . $prefix, 0666); $log = array( 'file' => basename($this->file), 'size' => filesize($this->file), 'mime' => 'audio', 'action' => 'convert', 'target' => $prefix, 'elapsed' => WBClock::stop($now, 1000, 1) . 'ms' ); $this->log->notice($log); } }