em = $em; $this->mainPath = $mainPath; $this->queue = $queue; $this->fis = $fis; } /** * @param FilePreview $preview * @param array $args * @return bool */ public function generate(FilePreview $preview, $args = array()){ $this->initThumbnailService(); switch($this->extractMode($preview->getMainMime())){ case 'video': $ret = $this->generateVideo($preview, $args); break; case 'image': $ret = $this->generateFromImage($preview,$args); break; case 'pdf': $ret = $this->generateFromPdf($preview,$args); break; case 'text': //$this->generateFromText($preview,$args);//used to be "text" but till we find some magic cmd line no preview //break; case 'default': default: $ret = true; //general image } if($ret === false) return false; //save changes try{ if(!$this->em->contains($preview)) $this->em->persist($preview); $this->em->flush(); } catch (OptimisticLockException $o){ return false; } catch (ORMException $e) { return false; } return true; } /** * @param FilePreview $filePreview * @param array $args * @return bool */ public function generateFromImage(FilePreview $filePreview, $args = array()){ if(empty($args)){ $args = array('1080','640','300'); } $fileToDelete = array(); $p = $filePreview->getMainFile(); $k = $filePreview->createNewKey(); $filePreview->setSelected($k); $filePreview->setThumbContainer($this->getThumbDirectory()); if(preg_match('@gif@i',$filePreview->getMainMime())){ $retIn = $p.'[0]'; } else { $retIn = $p; } $ext = '.jpg'; if(preg_match('@png@i',$filePreview->getMainMime()) || preg_match('@svg@i',$filePreview->getMainMime()) || preg_match('@xml@i',$filePreview->getMainMime())){ $ext = '.png'; } if(preg_match('@svg@i',$filePreview->getMainMime()) || preg_match('@xml@i',$filePreview->getMainMime())){ $fileOutput = $this->generateOutputName().$ext; $fileToDelete[] = $this->getThumbDirectory().$fileOutput; $retIn = $this->rasterizeSvg($retIn,$this->getThumbDirectory().$fileOutput); } foreach($args as $q){ $fileOutput = $this->generateOutputName().$ext; $retImMag = $this->resizeImage($retIn,$q,$this->getThumbDirectory().$fileOutput); if(is_string($retImMag)) $filePreview->addInFile($k,$q,$fileOutput); } foreach($fileToDelete as $d){ if(is_file($d)) @unlink($d); } try { if(!$this->em->contains($filePreview)) $this->em->persist($filePreview); $this->em->flush(); } catch (OptimisticLockException $o){ return false; } catch (ORMException $e) { return false; } return true; } /** * @param FilePreview $filePreview * @param array $args * @return bool */ public function generateFromPdf(FilePreview $filePreview, $args = array()){ if(empty($args)){ $args = array('1080','640','300'); } $p = $filePreview->getMainFile(); $k = $filePreview->createNewKey(); $filePreview->setSelected($k); $filePreview->setThumbContainer($this->getThumbDirectory()); $ext = '.jpg'; $retIn = $this->getPdfScreen(0,$p,$this->getThumbDirectory(). $this->generateOutputName().$ext); foreach($args as $q){ $fileOutput = $this->generateOutputName().$ext; $retImMag = $this->resizeImage($retIn,$q,$this->getThumbDirectory().$fileOutput); if(is_string($retImMag)) $filePreview->addInFile($k,$q,$fileOutput); } try { if(!$this->em->contains($filePreview)) $this->em->persist($filePreview); $this->em->flush(); } catch (OptimisticLockException $o){ return false; } catch (ORMException $e) { return false; } return true; } /** * @param FilePreview $filePreview * @param array $args * @return bool */ public function generateVideo(FilePreview $filePreview, $args = array()){ $p = $this->fis->getMediaFileInfo($filePreview->getMainFile()); $duration = $this->fis->getAttribute('Duration',$p); $duration = $this->fis->durationToTime($duration,true); $durationMax = $duration*0.85; $step = $durationMax/3; if(empty($args)){ $args = array( array( 'selected' => false, 'timecode' => $this->fis->convertMsToTimecode($step*1), 'qualities' =>array( '1080','640','300' ) ), array( 'selected' => true, 'timecode' => $this->fis->convertMsToTimecode($step*2), 'qualities' =>array( '1080','640','300' ) ), array( 'selected' => false, 'timecode' => $this->fis->convertMsToTimecode($step*3), 'qualities' =>array( '1080','640','300' ) ), ); } $filePreview->setThumbContainer($this->getThumbDirectory()); foreach($args as $thumbArgs){ $k = $filePreview->createNewKey(); $time = $thumbArgs['timecode']; if(isset($thumbArgs['selected']) && $thumbArgs['selected'] == true) $filePreview->setSelected($k); $fileOutput = $this->generateOutputName().'.jpg'; /** * @var string $ret : absolute path of the screenshots */ $ret = $this->screenVideoAt($time,$filePreview->getMainFile(),$this->getThumbDirectory().$fileOutput); foreach ($thumbArgs['qualities'] as $width){ $fileResizeOutput = $this->generateOutputName().'.jpg'; $retImMag = $this->resizeImage($ret,$width,$this->getThumbDirectory().$fileResizeOutput); if(is_string($retImMag)) $filePreview->addInFile($k,$width,$fileResizeOutput); } @unlink($ret); } try { if(!$this->em->contains($filePreview)) $this->em->persist($filePreview); $this->em->flush(); } catch (OptimisticLockException $o){ return false; } catch (ORMException $e) { return false; } return true; } /** * @param $timecode * @param $file * @param $fileOutput * @return bool */ public function screenVideoAt($timecode,$file,$fileOutput){ $process = new Process(' ffmpeg -i '.$file.' -vframes 1 -ss '.$timecode.' '.$fileOutput); $process->run(); if (!$process->isSuccessful()) { return false; } else return $fileOutput; } /** * generate screen from pdf * * @param $page * @param $file * @param $fileOutput * @return bool */ public function getPdfScreen($page,$file,$fileOutput){ $process = new Process('convert -alpha remove -strip '.$file.'['.$page.'] '.$fileOutput); $process->run(); if (!$process->isSuccessful()) { return false; } else return $fileOutput; } /** * @param $file * @param $fileOutput * @return bool */ public function getTextScreen($file,$fileOutput){ // $process = new Process('convert -size 1980x1080 xc:white -font "FreeMono" -pointsize 12 -fill black -annotate +15+15 "@'.$file.'" -trim -bordercolor "#FFF" -border 10 +repage '.$fileOutput); $process->run(); if (!$process->isSuccessful()) { return false; } else return $fileOutput; } /** * ImageMagick * * @param $fileInput * @param $width * @param $fileOutput * @return bool */ public function resizeImage($fileInput,$width,$fileOutput){ $process = new Process('convert -alpha on "'.$fileInput.'" -quality 75% -resize '.$width.'x1080 "'.$fileOutput.'"'); $process->run(); if (!$process->isSuccessful()) { return false; } else return $fileOutput; } /** * rsvg-convert * * @param $fileInput * @param $fileOutput * @return bool */ public function rasterizeSvg($fileInput,$fileOutput){ $process = new Process('rsvg-convert "'.$fileInput.'" -o "'.$fileOutput.'"'); $process->run(); if (!$process->isSuccessful()) { return false; } else return $fileOutput; } public function generateOutputName(){ return time().$this->generateHumanHash(64); } /** * return working directory * * @return string */ public function getThumbDirectory(){ if(is_file($this->mainPath.'coucou')) return $this->mainPath.'thmb/'; else return $this->queue.'thmb/'; } /** * init folders */ protected function initThumbnailService(){ if(!is_dir($this->getThumbDirectory())){ @mkdir($this->getThumbDirectory(),0755,true); } } /** * @param int $length * @return bool|string */ private function generateHumanHash($length = 64){ $hash = ""; while(strlen($hash) < $length){ $hash .= hash('sha512', random_bytes($length)); } return substr($hash, 0,$length); } /** * return wich function to use for this content * * @param $mime * @return string */ public function extractMode($mime){ $ret = "default"; if(preg_match('@^video/(.+){1,}$@', $mime)) return "video"; // elseif(preg_match('@vnd.adobe.photoshop@i', $mime)) return "default"; elseif(preg_match('@^image/(.+){1,}$@', $mime)) return "image"; elseif(preg_match('@(javascript|xhtml|xml|json|html|plain)@', $mime)) return "text"; elseif ($mime == "application/pdf") return "pdf"; return $ret; } public function generateFromText(FilePreview $filePreview, $args) { if(empty($args)){ $args = array('1080','640','128'); } $p = $filePreview->getMainFile(); $k = $filePreview->createNewKey(); $filePreview->setSelected($k); $filePreview->setThumbContainer($this->getThumbDirectory()); $ext = '.jpg'; $retIn = $this->getTextScreen($p,$this->getThumbDirectory(). $this->generateOutputName().$ext); foreach($args as $q){ $fileOutput = $this->generateOutputName().$ext; $retImMag = $this->resizeImage($retIn,$q,$this->getThumbDirectory().$fileOutput); if(is_string($retImMag)) $filePreview->addInFile($k,$q,$fileOutput); } try { if(!$this->em->contains($filePreview)) $this->em->persist($filePreview); $this->em->flush(); } catch (OptimisticLockException $e) { return false; } catch (ORMException $e) { return false; } return true; } }