Tytuł brzmi nieco niedorzecznie, co? Język stworzony do tworzenia stron WWW posłuży nam do manipulowania plikami multimedialnymi. Za sprawą Vladimira Goreja i jego skryptu FFmpeg PHP opublikowanego na phpclasses.org jest to możliwe.
Skrypt korzysta z bibliotek ffmpeg (wersji na Windowsa chyba nie ma). Mając duży plik na serwerze możemy wyciągać z niego takie rzeczy jak czas trwania, liczba klatek na sek., szerokość i wysokość, bitrate i inne. Najistotniejszą dla nas funkcją jest możliwość wyciągnięcia danej klatki z pliku i zapisanie go na dysku w postaci pliku jpg.
Zanim zaczniecie cokolwiek z tym robić proszę o poprawienie linii 635 pliku FFmpegMovie.php na
exec('ffmpeg -ss '.$frameTime.' -i '.escapeshellarg($this->movieFile).' -vframes 1 -sameq '.$frameFilePath.' 2>&1');
Zgłaszałem to autorowi kilka dni temu, ale na razie bez odzewu. Okazuje się, że wywołując ffmpeg z konsoli, kolejność podawanych atrybutów ma kolosalne znaczenie w szybkości działania. Jeżeli wyciągamy klatkę z początku filmu to pal sześć, gorzej jak gdzieś z końca!
Sama obsługa skryptu jest bajecznie prosta: tworzymy sobie obiekt FFmpegMovie i używamy funkcji getFrame().
require_once('./libs/FFmpegMovie.php'); require_once('./libs/FFmpegFrame.php'); $ffMovie = new FFmpegMovie('./jakis-plik.avi'); $frameNum = floor($ffMovie->getFrameCount() / 2); // wyciągamy ze środka pliku $ffMovie->getFrame($frameNum);
Mamy tutaj niestety kilka mankamentów:
- klatka nie jest takiej samej jakości jak oryginał,
- klatkę trzeba najpierw wyrzucić jako GD resource za pomocą metody
toGDImage()i potem zapisać funkcjąimagejpeg(), - nie wiemy czy pobrana klatka jest cała czarna (czyli bezużyteczna),
- nie mamy ładnego wyświetlania z którego momentu filmu pobrano klatkę
Na pierwszy zarzut nic nie pomożemy — jest to wbudowane ograniczenie w ffmpeg, ale za to na resztę można coś zaradzić — stworzyć klasę SpiechuSmartFrame dziedziczącą po FFmpegFrame.
class SpiechuSmartFrame extends FFmpegFrame { protected $isBlack = null; /** * @return bool */ public function isBlack() { if ($this->isBlack == null) { $frame = new BlackFrameFinder($this->toGDImage()); $this->isBlack = $frame->isBlack(); } return $this->isBlack; } /** * @return string Returns frame time in hh:mm:ss format */ public function getFrameTimeString() { return gmdate("H:i:s",$this->getPts()); } /** * @param string $filename * @param int $quality quality of jpg file (100 best, 0 worst) * @return bool true if saving to file was success */ public function saveToJpg($filename, $quality = 85) { return imagejpeg($this->toGDImage(), $filename, $quality); } }
Funkcja isBlack() może być dla Was zapewne niezrozumiała. Kod klasy BlackFrameFinder jest na tyle długi, że wkleiłem go do Pastebin. Klasa wykrywa czy obrazek jest czarny w ten sposób:
- skaluje obrazek źródłowy na kwadrat 24x24 px,
- zlicza kolory wszystkich pikseli i przelicza je na kolor w skali szarości,
- zlicza kolory od czarnego do „prawie czarnego” (ja przyjąłem indeksy kolorów od 0–20),
- porównuje czy przekroczono limit czarnych punktów (przyjąłem więcej niż 70% całości obrazka)
Klasa oczywiście nie jest „przyspawana” do wykrywania wyłącznie czarnych klatek z filmów. Działa na dowolnych obrazach. Jak zwykle możecie robić sobie z nią co chcecie pod warunkiem zostawienia komentarza pochwalnego i kliknięcia na „Lubię to”
Nie zapomnijcie zmodyfikować oryginalnego pliku FFmpegMovie.php w linii 651 na
$frame = new SpiechuSmartFrame($gdImage, $frameTime);
Podobne wpisy:

One comment
http://www.videohelp.com/tools/ffmpeg
dla windows