Capturando miniatura de vídeos com PHP

Hoje vamos falar de um assunto bastante divertido e que é de muita utilidade para todos nós. Vamos aprender como capturar a miniatura (thumbnail) de um vídeo em PHP e posteriormente salva-las no HD. Todo serviço que trabalha com algum tipo de mídia precisa de algumas ferramentas para fazer esta manipulação. O PHP não oferece suporte utilizando funções nativas para manipular arquivos de audio ou vídeo. Por isso, vocês precisam de 3 coisas muito importantes que são descritas logo a frente para seguirmos com este artigo.

Requisitos

  • ffmpeg-0.4.9_pre1 ou superior.
  • ffmpeg-php 0.5.3 ou superior.
  • gd-2.0 ou superior. (a versão que vem compilada com o PHP funciona também)

obs: Neste artigo não é meu objetivo ensinar a fazer a instalação destes recursos pois com uma rápida googada você resolve o problema.

O que é o ffmpeg?

O ffmpeg é um conjunto de bibliotecas de uso livre e open-source que oferece um suporte completo para você converter e interagir com praticamente qualquer tipo de mídia.

O que é o ffmpeg-php?

O ffmpeg-php é uma extensão php desenvolvida para que nós, programadores PHP, possamos interagir com o ffmpeg sem utilizarmos a “perigosa” função system() (e derivadas) do PHP. Mas vale lembrar que ela cobre “em partes” as funções do ffmpeg. Você não consegue com ffmpeg-php converter vídeos por exemplo, mas com o ffmpeg você consegue.

Recebendo as informações do vídeo com PHP

Antes de começar a brincar com o vídeo, nós precisamos aprender como pegar as informações do vídeo. O ffmpeg-php permite que você acesse estas informações do video:

//Return the duration of a movie or audio file in seconds.
$movie->getDuration() 
//Return the number of frames in a movie or audio file.
$movie->getFrameCount() 
//Return the frame rate of a movie in fps.
$movie->getFrameRate() 
//Return the path and name of the movie file or audio file.
$movie->getFilename() 
//Return the comment field from the movie or audio file.
$movie->getComment() 
//Return the title field from the movie or audio file.
$movie->getTitle() 
//alias $movie->getArtist()	Return the author field from the movie or the artist ID3 field from an mp3 file.
$movie->getAuthor() 
//Return the copyright field from the movie or audio file.
$movie->getCopyright() 
//Return the artist ID3 field from an mp3 file.
$movie->getArtist() 
//Return the genre ID3 field from an mp3 file.
$movie->getGenre() 
//Return the track ID3 field from an mp3 file.
$movie->getTrackNumber() 
//Return the year ID3 field from an mp3 file.
$movie->getYear() 
 //Return the height of the movie in pixels.
$movie->getFrameHeight()
//Return the width of the movie in pixels.
$movie->getFrameWidth()	
//Return the pixel format of the movie.
$movie->getPixelFormat() 
//Return the bit rate of the movie or audio file in bits per second.
$movie->getBitRate() 
//Return the bit rate of the video in bits per second.
$movie->getVideoBitRate()
//Return the audio bit rate of the media file in bits per second.
$movie->getAudioBitRate() 
//Return the audio sample rate of the media file in bits per second.
$movie->getAudioSampleRate() 
//Return the current frame index.
$movie->getFrameNumber() 
//Return the name of the video codec used to encode this movie as a string.
$movie->getVideoCodec()	
//Return the name of the audio codec used to encode this movie as a string.
$movie->getAudioCodec() 
//Return the number of audio channels in this movie as an integer.
$movie->getAudioChannels() 
//Return boolean value indicating whether the movie has an audio stream.
$movie->hasAudio() 
//Return boolean value indicating whether the movie has a video stream.
$movie->hasVideo() 
//Returns a frame from the movie as an ffmpeg_frame object. 
//Returns false if the frame was not found.
//framenumber - Frame from the movie to return. 
//If no framenumber is specified, returns the next frame of the movie.
$movie->getFrame([Integer framenumber])	
//Returns the next key frame from the movie as an ffmpeg_frame object. 
//Returns false if the frame was not found.
$movie->getNextKeyFrame()

No nosso caso, os únicos métodos que vão nos interessar seram: getFrameRate, getDuration, getFrameCount, getFrameHeight , getFrameWidth e getFrame.

No início do seu script, coloque esta linha só por segurança:

if ( ! extension_loaded ( 'ffmpeg' ) ) exit ( 'ffmpeg não foi carregado!' );

Para receber as informações do vídeo dentro do seu arquivo PHP você precisa utilizar a classe ffmpeg_movie do ffmpeg-php e passar como parametro o caminho do vídeo que você quer manipular.

// instancia a classe ffmpeg_movie para pegarmos as informações que queremos o vídeo
$movie = new ffmpeg_movie($movie_file);
// pegamos a duranção do video em segundos
$duration = round ( $movie->getDuration() , 0 ); 
// recebemos o número de frames do vídeo
$totalFrames = $movie->getFrameCount();
// recebemos a altura do vídeo em pixels
$height = $movie->getFrameHeight ();
// recebemos a largura do vídeo em pixels
$width = $movie->getFrameWidth ();

Recebendo o frame do vídeo e salvando

Agora que já temos as informações do vídeo, podemos capturar a miniatura de um determinado frame do vídeo e salva-la em nosso HD. Vamos utilizar outra classe do ffmpeg-php chamada ffmpeg_frame e utilizarmos a função toGDImage para convertermos o frame para uma imagem GD.

Para escolhermos o frame podemos utilizar algumas técnicas:

Miniatura de um segundo especifico:

$thumbnailOf = $movie->getFrameRate() * 5;

Miniatura do meio do vídeo:

$thumbnailOf = round ( $movie->getFrameCount() / 2 );

Neste exemplo vou pegar fazer um calculo para receber um frame do meio do vídeo e salvar no HD.

// precisamos criar uma imagem GD para o ffmpeg-php trabalhar nela
$image = imagecreatetruecolor ( $width , $height ) ;
// criamos a instancia do frame com a classe ffmpeg_frame
$frame = new ffmpeg_frame ( $image );
// escolhemos o frame que queremos salvar como jpeg
$thumbnailOf = (int) round ($movie->getFrameCount() / 2.5);
// recebe o frame
$frame = $movie->getFrame ( $thumbnailOf );
// converte para uma imagem GD
$image = $frame->toGDImage ();
//salva no HD.
imagejpeg($image, $movie_file.'.jpg', 100);

Pronto! Agora não tem desculpa. Vocês já sabem capiturar o frame de um video e salvar uma miniatura dele.

Redimencionando o frame do video

Este capitulo é um bonus. Vocês também podem salvar um frame especifico do video como jpeg e redimenciona-lo antes e salvar no HD. A função resize() da classe ffmpeg_frame faz isso para gente:

$frame->resize(Integer width, Integer height [, Integer crop_top [, Integer crop_bottom [, Integer crop_left [, Integer crop_right ]]]])

Utilizando o mesmo código acima, acrescentando somente uma linha:

// colei esta linha somente como referencia
$frame = $movie->getFrame ( $thumbnailOf ); 
// redimenciona o frame para 200 de lagura por 100 de algura.
$frame->resize ( 200, 100 );

Podemos também, redimencionar esta imagem e fazer um crop nela:

// colei esta linha somente como referencia
$frame = $movie->getFrame ( $thumbnailOf );
// redimencionamos o frame para 200x100 e mas com o acrescimo de um crop de 30x30x30x30.
$frame->resize ( 200, 100, 30, 30, 30, 30 );

É isso aí!

Maiores informações, na documentação oficial do ffmpeg-php.

[]’s
Igor.

software engineer @hole19golf, #javascript #nodejs #ruby #java #php #scala #python

Twitter LinkedIn 

Be Sociable, Share!

Posts Relacionados:

18 thoughts on “Capturando miniatura de vídeos com PHP

  1. Ótimo post, e venho em um bom momento. desenvolvo algumas ferramentas em PHP e uma delas irá trabalhar com vídeos. Vou ficar de olho no rss! Abraços

  2. Pingback: Capturando miniatura de vídeos com PHP – Criar Site

  3. Igor, já tentei de várias maneiras colocar o ffmpeg-php para funcionar com o WAMP. Tb já tentei vários tutoriais, varias versões de DLLs diferentes e mesmo PHP4 e PHP5, APache, IIS, mas não rolou. Vc sabe se ela, de alguma maneira funciona em ambiente Win? Abraço.

  4. Não sei te responder com precisão Victor. Se você não tem condições de ter um servidor linux, configura o seu ambiente em uma VM linux que já resolve o seu problema e você terá um ambiente bem mais flexivel e acessivel de se trabalhar.

  5. Olá pessoal, tive dificuldades em implementar com o imagejpeg(), não funcionava de maneira alguma, então olhei uns exemplos de teste da própria classe e eles usam imagepng(), mudei isso e agora funciona.

  6. Cara, eu nem li seu artigo mais vo salva aqui no favoritos acho que mais a frente vou mexer com isso… o cara ai do primeiro post parece o V sem a mascara AHAHUUAEIAU flws…

  7. Estou com um problema que as imgens geradas ficam azuladas, alguém tem uma ideia do que possa ser?

  8. opa, muito massa o a solução. Tenho algumas dúvidas na instalação. é por ssh? tem outro jeito para instalar no cpanel?

  9. olá, estou retornando com este erro que aparece em meu terminal quando aciono o comando phpize.

    grep: /usr/include/php/main/php.h: No such file or directory
    grep: /usr/include/php/Zend/zend_modules.h: No such file or directory
    grep: /usr/include/php/Zend/zend_extensions.h: No such file or directory
    Configuring for:
    PHP Api Version:
    Zend Module Api No:
    Zend Extension Api No:
    Cannot find autoconf. Please check your autoconf installation and the
    $PHP_AUTOCONF environment variable. Then, rerun this script.

  10. A função imagejpeg não pega, ele retorna como diretorio não encontrado:
    Warning: imagepng(): Unable to open …/MP4/Abertura:%2015.mp4.jpg’ for writing: No such file or directory in …/index.php on line *
    “…” diretorio completo, e * a linha,
    Preciso de ajuda urgentemente.

  11. Agora entendi, o segundo parâmetro, é o novo nome de destino, qual nome que a imagem vai fica, só acho q deveria colocar essa dica para saberem ‘-‘, Oimo post, gostei muito.

Leave a Reply

Your email address will not be published. Required fields are marked *