2010-04-07 6 views
6

J'essaie de générer des vignettes à partir de points aléatoires dans un film en utilisant l'extension FFMPEG et FFMPEG-PHP.Génération de vignettes aléatoires avec PHP + FFMPEG

Mon script fonctionne bien .. mais prend 20 minutes juste pour générer 5-10 miniatures !!

Le script fonctionne en générant des nombres aléatoires qui sont utilisés ultérieurement comme numéros d'image. Tous les nombres générés sont compris dans le nombre d'images de films.

Pouvez-vous expliquer pourquoi ce script prend 20 minutes pour terminer? Sinon, une meilleure solution?

<?php 

//Dont' timeout 
set_time_limit(0); 

//Load the file (This can be any file - still takes ages) 
$mov = new ffmpeg_movie('1486460.mp4'); 

//Get the total frames within the movie 
$total_frames = $mov->getFrameCount(); 

//Loop 5-10 times to generate random frames 5-10 times 
for ($i = 1; $i <= 5;) { 
    // Generate a number within 200 and the total number of frames. 
$frame = mt_rand(200,$total_frames); 
$getframe = $mov->getFrame($frame); 
// Check if the frame exists within the movie 
// If it does, place the frame number inside an array and break the current loop 
if($getframe){ 
    $frames[$frame] = $getframe ; 
    $i++; 
} 
} 

//For each frame found generate a thumbnail 
foreach ($frames as $key => $getframe) { 
$gd_image = $getframe->toGDImage(); 
imagejpeg($gd_image, "images/shot_".$key.'.jpeg'); 
imagedestroy($gd_image); 
echo $key.'<br/>'; 
} 

?> 

Le script DEVRAIT générer des numéros de trame valides? Quelque chose dans START - END devrait être des numéros de châssis valides? Pourtant, la boucle prend des années!

+0

30 minutes? Qu'est-ce que le? Je convertirais 1 To de vidéo. –

Répondre

4

Vous pouvez invoquer ffmpeg de la ligne de commande, en utilisant le commutateur -ss chercher à un approrpriate commencer point (dans le temps, et non en nombre de cadres) et -vframes 1 dire pour extraire exactement une image, par exemple:

ffmpeg -i 1486460.mp4 -ss 10 -vframes 1 images/shot_10.jpg 

extraira un cadre de 10 secondes et l'appeler images/shot_10.jpg

0

Je ne sais pas beaucoup de choses sur les formats de film, mais étant donné que la compression repose probablement sur une seule compression delta passe avec des cadres de référence, si la position des cadres de référence i s non défini, cela signifie que le système doit lire le film complet pour atteindre un décalage particulier. Il serait facile de vérifier cela en chargeant toujours, par exemple, en recherchant une image entre le décalage 20 et le nombre d'images divisées par une certaine valeur. En supposant que c'est le cas, vous avez un autre problème dans la façon dont vous avez conçu votre algorithme, vous devez revenir en arrière au début et chercher en avant pour chacune des 5 images - si vous avez généré vos décalages à l'avance , puis trié la liste, ffmpeg peut être en mesure d'aller chercher les images en un seul passage.

HTH

C.

1

Le problème est ici le mot aléatoire. J'ai réussi à obtenir la durée de la vidéo et ensuite essayer d'obtenir une image avec cette durée aléatoire. Facilement modifiable pour plus de cadres:

$cmd = "ffmpeg -i {$src} 2>&1 |grep Duration"; 

    $output = array(); 

    exec($cmd, $output); 

    if(count($output)) { 
     $duration = explode(':', trim(str_replace('Duration:', NULL, current(explode(',', current($output)))))); 
     list($hour, $min, $sec) = $duration; 
     $sec = sprintf("%02d:%02d:%02d", rand(0, $hour), rand(0, $min), rand(0, $sec)); 
    } else { 
     $sec = "00:00:12"; //12sec it's ok :) 
    } 

    $cmd = "ffmpeg -ss {$sec} -i {$src} -s {$w}x{$h} -f image2 -vframes 1 {$destination}"; 

    $output = array(); 

    exec($cmd, $output); 
+0

ce très bon codage :) – danielad

+0

Je pense que mettre la chose if (count (output)) sur une boucle pour ... rend la valeur aléatoire avec plus de vignettes à droite? – danielad

-5

Vous avez écrit une erreur dans votre boucle.

if($getframe) { 
    $frames[$frame] = $getframe; 
    $i++; 
} 

Disons que la boucle for s'exécute à l'infini jusqu'à ce qu'elle soit cassée. Si l'instruction if est fausse la première fois, alors $i++ ne peut pas être atteint et la boucle est alors infinie.

Vous devez placer le $i++ en bas de la boucle for, puis l'exécution sera de 2 secondes au lieu de 20 minutes.

+0

Le comportement est prévu.La boucle est supposée s'exécuter jusqu'à ce que cinq trames aient été sélectionnées, de sorte que le compte ne s'incrémente que lorsqu'une trame sélectionnée au hasard existe. – joequincy

Questions connexes