2012-09-27 3 views
6

J'essaie de créer des miniatures à partir de vidéos externes, principalement des MP4 et des fichiers FLV. J'utilise FFmpegPHP. J'ai déjà la génération de vignettes fonctionnant bien, cependant, je dois d'abord charger la vidéo sur mon serveur. Serait-il possible de diffuser seulement une petite partie de la vidéo, puis d'en extraire la vignette?FFmpegPHP obtenir la vignette de l'URL externe

Voici le code que j'ai jusqu'à présent:

require_once PRIV . 'Vendor/FFmpegPHP/FFmpegAutoloader.php'; 

// Download the whole video. 
$video = file_get_contents($_PUT['video']); 
$file = 'path_to_cache'; 
file_put_contents($file, $video); 

$movie = new FFmpegMovie($file); 

// Generate the thumbnail. 
$thumb = $movie->getFrame($movie->getFrameCount()/2); 
$thumb->resize(320, 240); 
imagejpeg($thumb->toGDImage(), 'path_to_thumb'); 

Toute personne a une suggestion?

EDIT

Comme Brad suggéré, voici le code mis à jour:

$file = CACHE . 'moodboard_video_' . rand(); 
$fh = fopen($file, 'w'); 
$size = 0; 

curl_setopt($ch, CURLOPT_URL, $_PUT['video']); 
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) use($fh, &$size){ 
    $length = fwrite($fh, $data); 

    if($length === FALSE) { 
     return 0; 
    } else { 
     $size += $length; 
    } 

    // Downloads 1MB. 
    return $size < 1024 * 1024 * XXXXXX ? $length : 0; 
}); 

curl_exec($ch); 

fclose($fh); 
curl_close($ch); 

// Create the thumbnail. 
$thumb = $movie->getFrame(XXXXXX); 
$thumb->resize(static::DEFAULT_THUMBNAIL_WIDTH, $thumb->getHeight()/$thumb->getWidth() * static::DEFAULT_THUMBNAIL_WIDTH); 
$image = $thumb->toGDImage(); 
imagejpeg($image, PRIV . static::THUMBNAILS_PATH . $item->getLastInsertIdentifier() . '_' . static::DEFAULT_THUMBNAIL_WIDTH); 

Répondre

3

FFMPEG est très bon de travailler avec des flux brisés. Pour cette raison, je pense que vous devriez essayer de télécharger les premières megs de ce média distant, et essayer d'obtenir une vignette du fichier incomplet.

D'abord, déposez file_get_contents() et utilisez cURL. Vous pouvez définir l'option CURLOPT_WRITEFUNCTION sur une de vos fonctions personnalisées qui écrit dans un fichier temporaire sur le disque, segment par bloc. Lorsque vous avez reçu suffisamment de données, renvoyez 0 à partir de votre fonction et cURL arrêtera le téléchargement. Vous devrez expérimenter pour voir quelle est la taille optimale. Si vous obtenez trop peu de données, vous n'aurez que les premières images à utiliser, ou pas d'images du tout. Trop tard, et vous gaspillez de la bande passante.

Pour certains types de conteneur, les informations de fichier se trouvent à la fin du fichier. Pour ceux-là, je n'ai pas de suggestion pour vous. A part d'écrire votre propre décodeur et d'épisser l'info à la fin avec quelque chose depuis le début, je ne connais pas de moyen de le faire sans télécharger le fichier entier.

+0

, je Jusqu'à présent, peut extraire une vignette sans avoir à télécharger le tout. Cependant, j'espérais obtenir le cadre du milieu (ish) si possible. Puis-je simplement avancer mon flux et écrire 0 jusqu'à ce que j'atteigne le milieu du flux, et juste obtenir des informations autour de cela. Aussi, est-il possible de calculer combien de temps j'ai besoin de télécharger un fichier pour obtenir des informations? – jValdron

+0

@jValdron, Pour les flux MPEG, vous pouvez souvent sauter juste au milieu. Beaucoup d'autres codecs et conteneurs permettent la même chose. Vous pouvez utiliser une requête de plage pour spécifier les octets souhaités. Voir aussi: http://stackoverflow.com/a/8507991/362536 La plupart des serveurs le supportent. Pour obtenir la longueur, vous pouvez faire une demande 'HEAD' (où soutenu), ou' GET', puis annuler après avoir reçu l'en-tête de longueur. – Brad

+0

Merci pour votre temps avec ce Brad. Maintenant, je ai juste besoin de comprendre comment obtenir l'image du milieu :) – jValdron

0

l'exécution de code avec PHP 5, ffmpeg et CURL avec une structure à base de classe est comme ci-dessous:

require_once 'PHP_CURFN/ffmpeg-php-master/FFmpegFrame.php'; 
    require_once 'PHP_CURFN/ffmpeg-php-master/FFmpegAutoloader.php'; 

class MyVideoTest{ 

private $fh=""; 
private $size=0; 
private $ch=""; 

public function __construct(){ 

       $video = 'http://[hosturl]/video/41a669911fd635167475d7530bffcc9f.mp4'; 
       $file = 'PHP_CURFN/cache/tmp_video_' . rand(); 


       $this->ch = curl_init(); 
       $this->fh = fopen ($file, 'w+'); 
       $this->ch = curl_init($video); 

       $this->size = 0; 
       curl_setopt($this->ch, CURLOPT_URL, $video); 
       curl_setopt($this->ch, CURLOPT_HEADER, 0); 


       curl_setopt($this->ch, CURLOPT_WRITEFUNCTION, array($this, "myfunction")); 

       curl_exec($this->ch); 

       fclose($this->fh); 
       curl_close($this->ch); 
       $movie = new FFmpegMovie($file); 
       // Create the thumbnail. 

       $thumb = $movie->getFrame(2); 
       $thumb->resize(320, 240); 
       $image = $thumb->toGDImage(); 
       imagejpeg($image, 'PHP_CURFN/cache' . $item->getLastInsertIdentifier() . '_' . 320); 

} 
function myfunction($ch, $data)  { 
     $length = fwrite($this->fh, $data); 
     $size=&$this->size; 

     if($length === FALSE) { 
      return 0; 
     } else { 
      $size += $length; 
     } 

     // Downloads 1MB. 

     return $size < 1024 * 1024 *1 ? $length : 0; 
} } 


$MyVideoTest= new MyVideoTest(); 
pr($MyVideoTest); 
exit; 
Questions connexes