/** * Configure shell-command * * @param Naf_ShellCmd $c */ function configure(Naf_ShellCmd $c) { $f = $this->info->getFormat(); $c->addOptionIf($f, '-of', $f); $c->addOption('-ovc', $this->info->getVideoCodec()); $c->addOption('-oac', $this->info->getAudioCodec()); }
/** * @param string $filename * @param int | string $start * @param int | string $duration * @return Naf_Media_Info * @throws Naf_Media_Exception */ function convert(&$filename, $start = 0, $duration = null) { $c = new Naf_ShellCmd($this->command); if (($width = $this->outputInfo->getWidth()) && ($height = $this->outputInfo->getHeight())) { // We have to resize the movie. if (!$this->outputInfo->getFormat()) { /* Output format not specified. By default, we should use 'copy', but we're not able actually, since if video-stream is copied (not encoded!), then no scaling will be applied. Force format. */ $ext = substr($this->source, strrpos($this->source, '.') + 1); $this->outputInfo->setFormat($ext); } $c->addOption('-vf', 'scale=' . $width . ':' . $height); } $cfg = $this->createConfigurator(); $filename = $cfg->filename($filename); $c->addOption('-o', $filename); $cfg->configure($c); $c->addOptionIf($start, '-ss', $start); $c->addOptionIf($duration, '-endpos', $duration); $c->setTarget($this->source); try { $c->exec(); } catch (Naf_Exception $e) { throw new Naf_Media_Exception("Mplayer call failed: " . $e->getMessage() . "\nCommand: " . $c->getLastCommannd()); } return Naf_Media::reader()->info($filename); }
function save($filename, $start = 0) { $c = new Naf_ShellCmd($this->command); $c->addOption('-i', $this->source); $c->addOption('-f', 'image2'); $c->addOption('-vframes', 1); $c->addOptionIf($start, '-ss', $start); $c->addOptionIf($this->width && $this->height, '-s', $this->width . 'x' . $this->height); if (null === $filename) { $c->setTarget('-'); // flush picture to STDOUT try { return $c->exec(); } catch (Naf_Exception $e) { throw new Naf_Media_Exception("Snapshot failed! " . $e->getMessage()); } } else { $c->setTarget($filename); // save to file try { $c->exec(); return; } catch (Naf_Exception $e) { throw new Naf_Media_Exception("Snapshot failed! " . $e->getMessage()); } } }
/** * Convert media according to specifications in $this->outputInfo. * * @param string $filename - passed by reference because sometimes there is a need to change the filename, * or otherwise the backend will produce an error * @return Naf_Media_Info - information for the newly created * @throws Naf_Media_Exception */ function convert(&$filename, $start = 0, $duration = null) { $c = new Naf_ShellCmd($this->command); $format = $this->outputInfo->getFormat(); if ($format) { $ext = substr($filename, strrpos($filename, '.') + 1); if ($ext != $format) { $filename .= '.' . $format; } } else { $ext = substr($this->source, strrpos($this->source, '.') + 1); $filename .= '.' . $ext; } $c->addOption('-i', $this->source); $c->setTarget($filename); $c->addOptionIf($start, '-ss', $start); $c->addOptionIf($duration, '-t', $duration); if (($width = $this->outputInfo->getWidth()) && ($height = $this->outputInfo->getHeight())) { $c->addOption('-s', $width . 'x' . $height); } $bitrate = $this->outputInfo->getBitrate(); $c->addOptionIf($bitrate, '-b', (int) $bitrate . "k"); try { $c->exec(); } catch (Naf_Exception $e) { throw new Naf_Media_Exception("Ffmpeg call failed: " . $e->getMessage() . "\nCommand: " . $c->getLastCommannd()); } return Naf_Media::reader()->info($filename); }
/** * Configure shell-command * * @param Naf_ShellCmd $c */ function configure(Naf_ShellCmd $c) { $c->addOption('-ovc', 'lavc'); $vbitrate = $this->info->getBitrate(); if (!$vbitrate) { $vbitrate = 64; } // 64 is default value of ffmpeg. low quality, low size. $c->addOption('-lavcopts', 'vcodec=wmv2:vbitrate=' . $vbitrate); $c->addOption('-oac', $this->info->getAudioCodec()); }
function save($filename, $start = 0) { $c = new Naf_ShellCmd($this->command); $c->setTarget($this->source); $c->addOption('-vo', 'jpeg:outdir=' . $this->tmpDir); $c->addOption('-nosound'); $c->addOption('-frames', 2); $c->addOptionIf($start, '-ss', $start); $c->addOptionIf($this->width && $this->height, '-vf', 'scale=' . $this->width . ':' . $this->height); try { $c->exec(); } catch (Naf_Exception $e) { throw new Naf_Media_Exception("Snapshot failed! " . $e->getMessage()); } @unlink($this->tmpDir . '/00000001.jpg'); $image = $this->tmpDir . '/00000002.jpg'; if ($filename) { rename($image, $filename); return; } else { $return = file_get_contents($image); @unlink($image); return $return; } }
/** * Read media file information. * * @param string filename * @return Naf_Media_Info */ function info($filename) { $i = new Naf_Media_Info($filename); $cmd = new Naf_ShellCmd($this->command); $cmd->addOption('-i', $filename); $infoText = $cmd->exec(true); // need to suppress errors due to ffmpeg producing error in case no output file is specified if (!preg_match("~Input\\s#0,\\s([^,]+)~m", $infoText, $matches1) || !preg_match("~\\s+Duration\\:\\s+(\\d{2}\\:\\d{2}\\:\\-?\\d{1,2}\\.\\d)(?:,\\s+start\\:\\s+\\d+\\.\\d+)?,\\s+bitrate\\:\\s+\\-?(\\d+|N/A)(?:\\s+kb/s)?\\s*~m", $infoText, $matches2)) { throw new Naf_Media_Exception("Unable to read movie info from {$infoText}"); } $i->setFormat($matches1[1]); $i->setDuration($matches2[1]); $bitrate = (int) $matches2[2]; if (!$bitrate) { $bitrate = 200; } $i->setBitrate($bitrate); if (preg_match("~.+Audio\\:\\s+([a-zA-Z0-9\\-\\_]+),\\s+(\\d+)\\s+Hz(?:,\\s+(?:stereo|mono))(?:,\\s+[a-zA-Z0-9_\\-])?,\\s+(\\d+)\\s+kb/s~m", $infoText, $matches)) { $i->setHasAudio(true); $i->setAudioCodec($matches[1]); $i->setSamplingRate($matches[2]); $i->setAudioBitrate($matches[3]); } /*if (preg_match("~.+Video\:\s+(\S+)(?:[,/]\s+\S+)?,\s+(\d+)x(\d+)(?:,\s+\d+\s+kb/s)?(?:,\s+(\d+\.\d+)\s+fps\(r\))?~m", $infoText, $matches)) { $i->setHasVideo(true); $i->setVideoCodec($matches[1]); $i->setPixelSize($matches[2], $matches[3]); $i->setFps($matches[4]); }*/ if (preg_match("~\n([^\n]+Video\\:\\s+(\\S+)[^\n]+)\n~m", $infoText, $matches)) { $videoInfo = $matches[1]; $i->setHasVideo(true); $i->setVideoCodec($matches[2]); if (preg_match("~(\\d{2,})x(\\d+)~", $videoInfo, $matches)) { $i->setPixelSize($matches[1], $matches[2]); } if (preg_match("~(\\d+\\.\\d+)\\s+fps\\(r\\)~", $videoInfo, $matches)) { $i->setFps($matches[1]); } } return $i; }
/** * Configure shell-command * * @param Naf_ShellCmd $c */ function configure(Naf_ShellCmd $c) { $c->addOption('-of', 'lavf'); /* have to add this ugly option due to mencoder bug */ $c->addOption('-lavfopts', 'i_certify_that_my_video_stream_does_not_use_b_frames'); $c->addOption('-ovc', 'lavc'); $vbitrate = $this->info->getBitrate(); if (!$vbitrate) { $vbitrate = 64; } // 64 is default value of ffmpeg. low quality, low size. $c->addOption('-lavcopts', 'vcodec=flv:vbitrate=' . $vbitrate . ':mbd=2:mv0:trell:v4mv:cbp:last_pred=3'); $c->addOption('-oac', 'mp3lame'); $c->addOption('-lameopts', 'abr:br=56'); $c->addOption('-srate', '44100'); // @todo: take this value from info }
/** * Configure shell-command * * @param Naf_ShellCmd $c */ function configure(Naf_ShellCmd $c) { $c->addOption('-ovc', 'lavc'); /* @todo: this code for bitrate detection should be encapsulated in a method */ $vbitrate = $this->info->getBitrate(); if (!$vbitrate) { $vbitrate = 100; } // 100 is orten good enough and small enough $c->addOption('-lavcopts', 'vcodec=mpeg1video:vbitrate=' . $vbitrate); $c->addOption('-of', 'lavf'); /* have to use this ugly option due to a bug in mencoder */ $c->addOption('-lavfopts', 'format=mpg:i_certify_that_my_video_stream_does_not_use_b_frames'); $c->addOption('-oac', $this->info->getAudioCodec()); }
<?php /** * Naf and PHPUnit must be within include_path! */ define('TEST_ROOT', dirname(__FILE__) . '/'); require_once dirname(__FILE__) . "/config.php"; require_once NAF_ROOT . "Naf.php"; Naf::$settings['autoload_map'] = array('Naf' => '', 'PHPUnit' => ''); Naf_ShellCmd::setTmpDir(TEST_TMP_DIR);
static function setTmpDir($dir) { $dir = rtrim($dir); if (!is_dir($dir)) { throw new Naf_Exception("temporary directory is not a directory"); } if (!is_writable($dir)) { throw new Naf_Exception("temporary directory is not writable"); } self::$tmpDir = $dir . '/'; }
/** * Read media file information. * * @param string filename * @return Naf_Media_Info */ function info($filename) { $i = new Naf_Media_Info($filename); $cmd = new Naf_ShellCmd($this->command); $cmd->addOption('-identify'); $cmd->addOption('-frames', 0); $cmd->addOption('-ao', 'null'); $cmd->addOption('-vo', 'null'); $cmd->setTarget($filename); $infoText = $cmd->exec(); $w = $h = 0; foreach (preg_split("/\r\n|\r|\n/", $infoText) as $line) { if (preg_match("/^ID_([^\\=]+)=(.+)\$/", $line, $matches)) { $key = $matches[1]; $value = $matches[2]; if (0 === strpos($key, 'VIDEO')) { $i->setHasVideo(true); } elseif (0 === strpos($key, 'AUDIO')) { $i->setHasAudio(true); } switch ($key) { case "VIDEO_WIDTH": $w = (int) $value; break; case "VIDEO_HEIGHT": $h = (int) $value; break; case "VIDEO_FPS": $i->setFps($value); break; case "AUDIO_BITRATE": $i->setAudioBitrate($value / 1000); break; case "AUDIO_RATE": $i->setSamplingRate($value); break; case "LENGTH": $i->setDuration($value); break; case "AUDIO_CODEC": $i->setAudioCodec($value); break; case "VIDEO_CODEC": $i->setVideoCodec($value); break; default: break; } } elseif (preg_match("/^([^\\s]+) file format detected/", $line, $matches)) { $i->setFormat($matches[1]); } } if ($i->hasVideo()) { $i->setPixelSize($w, $h); $duration = $i->getDuration(); if (0 == $duration) { // experimentally it has been found that 5 seconds will be ok here... $duration = 5; } $i->setBitrate(filesize($filename) / 1024 * 8 / $duration); } return $i; }
/** * Configure shell-command. * * @param Naf_ShellCmd $c */ function configure(Naf_ShellCmd $c) { $c->addOption('-ovc', $this->info->getVideoCodec()); $c->addOption('-oac', $this->info->getAudioCodec()); }