2011-03-31 3 views
1

J'ai écrit l'emballage suivante pour FFMPEG:FFMPEG Bitrate Calcul/Optimisation

function Video($input, $crop = null, $scale = null, $output = null, $extra = null) 
{ 
    $input = @new ffmpeg_movie($input); 

    if ((is_object($input) === true) && ($input->hasVideo() === true)) 
    { 
     $size = array($input->getFrameWidth(), $input->getFrameHeight()); 
     $crop = array_values(array_filter(explode('/', $crop), 'is_numeric')); 
     $scale = array_values(array_filter(explode('*', $scale), 'is_numeric')); 

     if ((is_callable('shell_exec') === true) && (is_executable($ffmpeg = trim(shell_exec('which ffmpeg'))) === true)) 
     { 
      if (count($crop) == 2) 
      { 
       $crop = array($size[0]/$size[1], $crop[0]/$crop[1]); 

       if ($crop[0] > $crop[1]) 
       { 
        $size[0] = round($size[1] * $crop[1]); 
       } 

       else if ($crop[0] < $crop[1]) 
       { 
        $size[1] = round($size[0]/$crop[1]); 
       } 

       $crop = array($input->getFrameWidth() - $size[0], $input->getFrameHeight() - $size[1]); 
      } 

      else 
      { 
       $crop = array(0, 0); 
      } 

      if (count($scale) >= 1) 
      { 
       if (empty($scale[0]) === true) 
       { 
        $scale[0] = round($scale[1] * $size[0]/$size[1]/2) * 2; 
       } 

       else if (empty($scale[1]) === true) 
       { 
        $scale[1] = round($scale[0] * $size[1]/$size[0]/2) * 2; 
       } 
      } 

      else 
      { 
       $scale = array(round($size[0]/2) * 2, round($size[1]/2) * 2); 
      } 

      $result = array(); 

      if (array_product($scale) > 0) 
      { 
       $result[] = sprintf('%s -i %s', escapeshellcmd($ffmpeg), escapeshellarg($input->getFileName())); 

       if (array_sum($crop) > 0) 
       { 
        if (stripos(shell_exec(escapeshellcmd($ffmpeg) . ' -h | grep crop'), 'removed') !== false) 
        { 
         $result[] = sprintf('-vf "crop=in_w-2*%u:in_h-2*%u"', round($crop[0]/4) * 2, round($crop[1]/4) * 2); 
        } 

        else if ($crop[0] > 0) 
        { 
         $result[] = sprintf('-cropleft %u -cropright %u', round($crop[0]/4) * 2, round($crop[0]/4) * 2); 
        } 

        else if ($crop[1] > 0) 
        { 
         $result[] = sprintf('-croptop %u -cropbottom %u', round($crop[1]/4) * 2, round($crop[1]/4) * 2); 
        } 
       } 

       if ($input->hasAudio() === true) 
       { 
        $result[] = sprintf('-ab %u -ar %u', $input->getAudioBitRate(), $input->getAudioSampleRate()); 
       } 

       $result[] = sprintf('-b %u -r %u -s %s', $input->getBitRate(), min(25, $input->getFrameRate()), implode('x', $scale)); 

       if (strlen($format = strtolower(ltrim(strrchr($output, '.'), '.'))) > 0) 
       { 
        $result[] = sprintf('-f %s %s -y %s', $format, escapeshellcmd($extra), escapeshellarg($output . '.ffmpeg')); 

        if ((strncmp('flv', $format, 3) === 0) && (is_executable($flvtool2 = trim(shell_exec('which flvtool2'))) === true)) 
        { 
         $result[] = sprintf('&& %s -U %s %s', escapeshellcmd($flvtool2), escapeshellarg($output . '.ffmpeg'), escapeshellarg($output . '.ffmpeg')); 
        } 

        $result[] = sprintf('&& mv -u %s %s', escapeshellarg($output . '.ffmpeg'), escapeshellarg($output)); 

        if ((is_writable(dirname($output)) === true) && (is_resource($stream = popen('(' . implode(' ', $result) . ') 2>&1 &', 'r')) === true)) 
        { 
         while (($buffer = fgets($stream)) !== false) 
         { 
          if (strpos($buffer, 'to stop encoding') !== false) 
          { 
           return (is_int(pclose($stream)) === true) ? true : false; 
          } 
         } 

         if (is_file($output . '.ffmpeg') === true) 
         { 
          unlink($output . '.ffmpeg'); 
         } 

         pclose($stream); 
        } 
       } 
      } 
     } 
    } 

    return false; 
} 

Comme vous pouvez le voir, je suis en utilisant le bitrate audio d'entrée d'origine et de la vidéo dans ma sortie, même si la vidéo d'entrée est recadrées ou redimensionnées , ce qui semble assez inefficace en termes d'espace HD.

Je connais très peu de choses sur ces questions, mais d'après ce que je comprends les débits sont directement liés à la durée, la qualité et la résolution des médias, n'est-ce pas? Si oui, comment puis-je utiliser ces valeurs pour déterminer un débit audio et vidéo approprié pour maintenir la qualité de l'entrée et réduire la taille du fichier?

Merci d'avance!

Répondre

3

En général, vous ne devez pas spécifier de débit. C'est seulement utile pour le streaming, auquel cas vous devez aussi respecter le VBV (qui spécifie un débit maximum dans le temps, ainsi que le débit moyen).

Utilisez x264 crf 23 - son mode par défaut de qualité constante - et soyez heureux. Dans le cas de ffmpeg, cela est quelque chose comme:

ffmpeg -i <file> -vcodec libx264 -vpre slower -acodec copy <outfile> 

Comme pour l'audio, il est préférable directement copié si l'entrée a été compressé. Ce n'est pas possible dans certaines situations, comme si l'entrée était vorbis et la sortie est un fichier .flv. Dans ce cas, je m'en tiendrai à la valeur par défaut de l'encodeur audio sélectionné.

+0

Ce fut la première chose que j'ai essayé, mais la qualité était de la merde. Selon la documentation FFMPEG: ** - b bitrate: Définit le bitrate vidéo en bit/s (par défaut = 200 kb/s) **. En ce qui concerne l'audio, je limite le débit à un maximum de 128ko. Aussi, puisque je suis un peu nouveau à ce sujet, que signifie "crf 23"? –

+0

Facteur de fréquence constant. –

+0

Humm, je pense que je l'ai trouvé dans http: // rob.opendot.cl/index.php/useful-stuff/ffmpeg-x264-encoding-guide/: Facteur de taux constant. Savez-vous ce qu'il fait exactement? Puis-je l'utiliser avec d'autres codecs vidéo? Et qu'en est-il du 23, y a-t-il une échelle? –

0

Vous voulez rechercher le journal de Shannon-Entropy (P)/log (2). C'est le nombre minimum de bits auxquels on peut penser. Mais je ne sais pas si cela vous est utile.

+0

Jamais entendu parler de Shannon-Entropy auparavant, je vais vérifier la page Wikipedia maintenant. –

+0

Je l'ai jeté un coup d'oeil mais je ne comprends pas comment je peux l'appliquer à mon problème avec les variables que j'ai à disposition ... Pourriez-vous nous en dire un peu plus à ce sujet? –

+0

Fondamentalement, mon idée est de compter chaque symbole dans vos données et ensuite le somme avec la formule de Shannon-Entropy pour obtenir le moins de bits comment vos données peuvent être compressées. C'est une limite théorique et cela dépend de vos données et de votre algorithme. Je crois que c'est seulement pour la compression de texte. Mais je suis très sûr que je me trompe parce que j'ai répondu à une question similaire avant http://stackoverflow.com/questions/5450489/how-does-winrar-perform-a-compression-ratio-check/5451331#5451331. user shelwien est un professionnel en compression. – Bytemain

0

J'ai fini par utiliser le -sameq flag, j'ai lu quelque part que cela ne se traduisait pas par la même qualité mais pour le moment c'est mieux que de forcer le débit binaire d'origine.

Quoi qu'il en soit, j'ai rencontré this Bash script qui suggère que ma pensée est juste, je ne sais toujours pas comment calculer le débit binaire de sortie sans avoir la taille de sortie comme une contrainte. Si quelqu'un sait, s'il vous plaît partager!