PHP调用ffmpeg对视频截图并拼接脚本实例分享
本文主要介绍了PHP调用ffmpeg对视频截图并拼接脚本,希望能帮助到大家。
PHP脚本调用ffmpeg对视频截图并拼接,供大家参考,具体内容如下
目前支持MKV,MPG,MP4等常见格式的视频,其他格式有待测试
12P 一张截图平均生成时间 1.64s 100个视频,大概需要2分半左右
9P 一张截图平均生成时间 1.13s 100个视频,大概需要2分钟左右
6P 一张截图平均生成时间 0.86s 100个视频,大概需要1分半左右
3P 一张截图平均生成时间 0.54s 100个视频,大概需要1分钟左右
<?php define('DS', DIRECTORY_SEPARATOR); date_default_timezone_set("Asia/Shanghai"); class FileLoader { //路径变量 private $rootdir = ''; private $tmp = "tmp"; //tmp 目录 private $source = "mpg"; //source 目录 private $destination = "screenshoot"; //目标截图路径 private $emptyImageName = "empty.jpg"; //合成的背景图 //文件数组 private $maxShoots = 12; //最大的截图数 private $videoInfo = NULL; private $files = array(); //文件数 private $fileArray = array(); private $extensionArray = array("mpg","mkv","mp4","avi","3gp","mov"); //支持的格式 private $timeArray = array("00:00:10","00:00:20","00:00:30","00:01:00","00:01:30","00:02:00","00:02:30","00:03:00","00:03:30","00:03:40","00:03:50","00:04:00"); //统计变量 private $timeStart = 0; private $timeEnd = 0; private $fileCount = 0; private $successCount = 0; private $failedCount = 0; /** * 初始化信息 */ function __construct() { file_put_contents("log.txt",""); $this->rootdir = dirname(__FILE__); $count = count($this->timeArray); for($i=1;$i<=$count;$i++) { $ii = $i-1; $this->fileArray[$ii] = $this->tmp.DS.$i.".jpg"; } } /** * 当前时间,精确到小数点 */ private static function microtime_float() { list($usec, $sec)= explode(" ", microtime()); return ((float)$usec + (float)$sec); } /** * 00:00:00 时间转秒 */ private static function timeToSec($time) { $p = explode(':',$time); $c = count($p); if ($c>1) { $hour = intval($p[0]); $minute = intval($p[1]); $sec = intval($p[2]); } else { throw new Exception('error time format'); } $secs = $hour * 3600 + $minute * 60 + $sec; return $secs; } /** * 00:00:00 时间转秒 */ private static function secToTime($time) { $hour = floor($time/3600); $min = floor(($time - $hour * 3600)/60); $sec = $time % 60; $timeStr = sprintf("%02d:%02d:%02d",$hour,$min,$sec); return $timeStr; } /** * 获取全部文件 */ private function getFiles($dir) { $files = array(); $dir = rtrim($dir, "/\\") . DS; $dh = opendir($dir); if ($dh == false) { return $files; } while (($file = readdir($dh)) != false) { if ($file{0} == '.') { continue; } $path = $dir . $file; if (is_dir($path)) { $files = array_merge($files, $this->getFiles($path)); } elseif (is_file($path)) { $files[] = $path; } } closedir($dh); return $files; } /** * 搜索路径 */ public function searchDir($sourcePath = NULL) { $this->timeStart = $this->microtime_float(); if ($sourcePath) { $this->rootdir = $sourcePath; } if (file_exists($this->rootdir) && is_dir($this->rootdir)) { $this->files = $this->getFiles($this->rootdir.DS.$this->source); } $this->fileCount = count($this->files); foreach ($this->files as $path) { $fi = pathinfo($path); $flag = array_search(strtolower($fi['extension']),$this->extensionArray); if (!$flag) continue; $this->getScreenShoot(basename($path)); } $this->timeEnd = $this->microtime_float(); $time = $this->timeEnd - $this->timeStart; if($this->fileCount > 0) { $str = sprintf("[TOTAL]: Cost Time:%8s | Total File:[%d] | Successed:[%d] | Failed:[%d] | Speed:%.2fs per file\n",$this->secToTime($time),$this->fileCount,$this->successCount,$this->failedCount,$time/$this->fileCount); file_put_contents("log.txt",$str,FILE_APPEND); } else { $str = sprintf("[TOTAL]: Cost Time:%8s | Total File:[%d] | Successed:[%d] | Failed:[%d] | Speed:%.2fs per file\n",$this->secToTime($time),$this->fileCount,$this->successCount,$this->failedCount,0); file_put_contents("log.txt",$str,FILE_APPEND); } } /** * 获取视频信息 */ private function getVideoInfo($file){ $re = array(); exec(".".DS."ffmpeg -i {$file} 2>&1", $re); $info = implode("\n", $re); if(preg_match("/No such file or directory/i", $info)) { return false; } if(preg_match("/Invalid data/i", $info)){ return false; } $match = array(); preg_match("/\d{2,}x\d+/", $info, $match); list($width, $height) = explode("x", $match[0]); $match = array(); preg_match("/Duration:(.*?),/", $info, $match); if($match) { $duration = date("H:i:s", strtotime($match[1])); }else { $duration = NULL; } $match = array(); preg_match("/bitrate:(.*kb\/s)/", $info, $match); $bitrate = $match[1]; if(!$width && !$height && !$duration && !$bitrate){ return false; }else{ return array( "file" => $file, "width" => $width, "height" => $height, "duration" => $duration, "bitrate" => $bitrate, "secends" => $this->timeToSec($duration) ); } } /** * 设置截图时间 */ private function setShootSecends($secends,$useDefault = NO) { if($useDefault) { if($secends<18) { $time = 1; }else { $time = 5; } $range = floor(($secends - $time)/ ($this->maxShoots)); if ($range < 1) { $range = 1; } $this->timeArray = array(); for($i=0;$i<$this->maxShoots;$i++) { $this->timeArray[$i] = $this->secToTime($time); $time = $time + $range; if ($time > $secends) break; } } } /** * 拼接图片 */ private function getFixedPhoto($fileName) { $target = $this->rootdir.DS.$this->emptyImageName;//背景图片 $target_img = Imagecreatefromjpeg($target); $source= array(); foreach ($this->fileArray as $k=>$v) { $source[$k]['source'] = Imagecreatefromjpeg($v); $source[$k]['size'] = getimagesize($v); } $tmpx=5; $tmpy=5;//图片之间的间距 for ($i=0; $i< count($this->timeArray); $i++) { imagecopy($target_img,$source[$i]['source'],$tmpx,$tmpy,0,0,$source[$i]['size'][0],$source[$i]['size'][1]); $target_img = $this->setTimeLabel($target_img,$tmpx,$tmpy,$source[$i]['size'][0],$source[$i]['size'][1],$this->timeArray[$i]); $tmpx = $tmpx+ $source[$i]['size'][0]; $tmpx = $tmpx+5; if(($i+1) %3 == 0){ $tmpy = $tmpy+$source[$i]['size'][1]; $tmpy = $tmpy+5; $tmpx=5; } } $target_img = $this->setVideoInfoLabel($target_img,$tmpx,$tmpy,$this->videoInfo); Imagejpeg($target_img,$this->rootdir.DS.$this->destination.DS.$fileName.'.jpg'); } /** * 设置时间刻度标签 */ private function setTimeLabel($image,$image_x,$image_y,$image_w,$image_h,$img_text) { imagealphablending($image,true); //设定颜色 $color=imagecolorallocate($image,255,255,255); $ttf_im=imagettfbbox(30 ,0,"Arial.ttf",$this->img_text); $w = $ttf_im[2] - $ttf_im[6]; $h = $ttf_im[3] - $ttf_im[7]; unset($ttf_im); $txt_y =$image_y+$image_h+$h-5; $txt_x =$image_x+$w+5; imagettftext($image,30,0,$txt_x,$txt_y,$color,"Arial.ttf",$img_text); return $image; } /** * 设置视频信息标签 */ private function setVideoInfoLabel($image,$txt_x,$txt_y,$videoInfo) { imagealphablending($image,true); $color=imagecolorallocate($image,0,0,0); imagettftext($image,32,0,100,2000+30,$color,"FZLTHJW.ttf","FileName:".basename($videoInfo["file"])); imagettftext($image,32,0,1600,2000+30,$color,"Arial.ttf","Size:".$videoInfo["width"]."x".$videoInfo["height"]); imagettftext($image,32,0,100,2000+120,$color,"Arial.ttf","Duration:".$videoInfo["duration"]); imagettftext($image,32,0,1600,2000+120,$color,"Arial.ttf","Bitrate:".$videoInfo["bitrate"]); return $image; } /** * 屏幕截图 */ public function getScreenShoot($fileName) { $fi = pathinfo($fileName); $this->videoInfo = $this->getVideoInfo($this->rootdir.DS.$this->source.DS.$fileName); if($this->videoInfo) { $this->setShootSecends($this->videoInfo["secends"]); for ($i=0; $i< count($this->timeArray); $i++ ) { $cmd=".".DS."ffmpeg -ss ". $this->timeArray[$i] ." -i ". $this->rootdir.DS.$this->source.DS.$fileName ." -y -f image2 -s 720*480 -vframes 1 ".$this->rootdir.DS.$this->fileArray[$i]; exec($cmd,$out,$status); } $this->getFixedPhoto($fileName); $str = sprintf("[%s]:OK...........[%s][%2dP]%-30s\n",date("y-m-d h:i:s",time()),$this->videoInfo["duration"],count($this->timeArray),$fileName); file_put_contents("log.txt",$str,FILE_APPEND); $this->successCount += 1; }else { $str = sprintf("[%s]:FAILED.................................[%s][%2dP]%-30s\n",date("y-m-d h:i:s",time()),$this->videoInfo["duration"],count($this->timeArray),$fileName); file_put_contents("log.txt",$str,FILE_APPEND); $this->failedCount += 1; } } /** * TODO: * 截取图片, * 需要配置ffmpeg-php,比较麻烦, * 但是这个类确实挺好用的。 */ public function getScreenShoot2($fileName) { if(extension_loaded('ffmpeg')){//判断ffmpeg是否载入 $mov = new ffmpeg_movie($this->rootdir.DS.$this->source.DS.$fileName);//视频的路径 $count = $mov->getFrameCount(); $ff_frame = $mov->getFrame(floor($count/2)); if($ff_frame) { $gd_image = $ff_frame->toGDImage(); $img=$this->rootdir.DS."test.jpg";//要生成图片的绝对路径 imagejpeg($gd_image, $img);//创建jpg图像 imagedestroy($gd_image);//销毁一图像 } }else{ echo "ffmpeg没有载入"; } } } $fileLoader = new FileLoader(); $fileLoader->searchDir(); ?>
相关推荐:
HTML5/CSS3 诱人的实例 -模仿优酷视频截图功能的详解
js+HTML5实现视频截图的方法_javascript技巧
Atas ialah kandungan terperinci PHP调用ffmpeg对视频截图并拼接脚本实例分享. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



PHP 8.4 membawa beberapa ciri baharu, peningkatan keselamatan dan peningkatan prestasi dengan jumlah penamatan dan penyingkiran ciri yang sihat. Panduan ini menerangkan cara memasang PHP 8.4 atau naik taraf kepada PHP 8.4 pada Ubuntu, Debian, atau terbitan mereka

Untuk bekerja dengan tarikh dan masa dalam cakephp4, kami akan menggunakan kelas FrozenTime yang tersedia.

Untuk mengusahakan muat naik fail, kami akan menggunakan pembantu borang. Di sini, adalah contoh untuk muat naik fail.

CakePHP ialah rangka kerja sumber terbuka untuk PHP. Ia bertujuan untuk menjadikan pembangunan, penggunaan dan penyelenggaraan aplikasi lebih mudah. CakePHP adalah berdasarkan seni bina seperti MVC yang berkuasa dan mudah difahami. Model, Pandangan dan Pengawal gu

Pengesah boleh dibuat dengan menambah dua baris berikut dalam pengawal.

Log masuk CakePHP adalah tugas yang sangat mudah. Anda hanya perlu menggunakan satu fungsi. Anda boleh log ralat, pengecualian, aktiviti pengguna, tindakan yang diambil oleh pengguna, untuk sebarang proses latar belakang seperti cronjob. Mengelog data dalam CakePHP adalah mudah. Fungsi log() disediakan

Kod Visual Studio, juga dikenali sebagai Kod VS, ialah editor kod sumber percuma — atau persekitaran pembangunan bersepadu (IDE) — tersedia untuk semua sistem pengendalian utama. Dengan koleksi sambungan yang besar untuk banyak bahasa pengaturcaraan, Kod VS boleh menjadi c

CakePHP ialah rangka kerja MVC sumber terbuka. Ia menjadikan pembangunan, penggunaan dan penyelenggaraan aplikasi lebih mudah. CakePHP mempunyai beberapa perpustakaan untuk mengurangkan beban tugas yang paling biasa.
