composer - FFmpegPHP obtiene una miniatura de una URL externa
resize video php (2)
Intento crear miniaturas de videos externos, principalmente MP4 y FLV. Estoy usando FFmpegPHP . Ya tengo la generación de miniaturas funcionando bien, sin embargo, primero necesito cargar el video completamente en mi servidor. ¿Sería posible transmitir solo una pequeña parte del video y luego extraer la miniatura de eso?
Aquí está el código que tengo hasta ahora:
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'');
Alguien tiene una sugerencia?
EDITAR
Como Brad sugirió, aquí está el código actualizado:
$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);
FFMPEG es muy bueno trabajando con streams rotos. Debido a esto, creo que deberías intentar descargar los primeros megas de ese medio remoto e intentar obtener una miniatura del archivo incompleto.
Primero, suelte file_get_contents()
y use cURL. Puede establecer la opción CURLOPT_WRITEFUNCTION
en una función personalizada suya que se escribe en un archivo temporal en disco, fragmento por fragmento. Cuando haya recibido suficientes datos, devuelva 0
de su función y cURL dejará de descargar. Tendrás que experimentar para ver cuál es el tamaño óptimo. Si obtiene muy pocos datos, solo tendrá los marcos más antiguos para trabajar o no tendrá marcos. Demasiado tarde, y está desperdiciando ancho de banda.
Para algunos tipos de contenedores, la información del archivo se encuentra al final del archivo. Para aquellos, no tengo una sugerencia para ti. Después de escribir su propio decodificador y empalmar la información al final con algo desde el principio, no sé de qué manera hacerlo sin descargar todo el archivo.
el código de ejecución con PHP 5, ffmpeg y CURL con estructura basada en clases es el siguiente:
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;