From 5b9467ca92850a7d25074859ec4c4c6777d1530e Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Thu, 15 Aug 2019 14:38:39 +0300 Subject: initial --- README.md | 15 ++++++++++ init.php | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 README.md create mode 100644 init.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f5a992 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +## Fills missing posters of HTML5 video elements + +Requires ffmpeg to be usable. Using this in production is probably a terrible +idea. + +As a side effect, both video stream and generated poster are cached locally. + +## Installation + +1. git clone to ``plugins.local/af_z_video_fill_poster`` +2. Enable plugin + +## License + +GPLv3 diff --git a/init.php b/init.php new file mode 100644 index 0000000..6d713b7 --- /dev/null +++ b/init.php @@ -0,0 +1,95 @@ +host = $host; + $this->cache = new DiskCache("images"); + + $host->add_hook($host::HOOK_ARTICLE_FILTER, $this); + } + + private function ffmpeg_thumbnail($input_filename, $output_filename) { + $cmdline_tpl = "ffmpeg -ss 00:00:01 -i %s -frames:v 1 ". + "-f singlejpeg %s 2>/dev/null"; + + $rc = -1; + $cmdline = sprintf($cmdline_tpl, escapeshellarg($input_filename), escapeshellarg($output_filename)); + + exec($cmdline, $output, $rc);; + + return $rc === 0; + } + + function hook_article_filter($article) { + $need_saving = false; + $doc = new DOMDocument(); + + if (@$doc->loadHTML('' . $article["content"])) { + $xpath = new DOMXPath($doc); + $videos = $xpath->query('(//video)'); + + foreach ($videos as $video) { + if (!$video->hasAttribute("poster")) { + $source = $xpath->query("//source[@src]", $video)->item(0); + + if ($source) { + $video_url = $source->getAttribute("src"); + $local_filename = sha1($video_url); + $thumb_filename = $local_filename . "-POSTER"; + + if ($this->cache->exists($thumb_filename)) { + $video->setAttribute("poster", $this->cache->getUrl($thumb_filename)); + $need_saving = true; + + } else { + if ($this->cache->exists($local_filename)) { + if ($this->ffmpeg_thumbnail( + $this->cache->getFullPath($local_filename), + $this->cache->getFullPath($thumb_filename))) { + + $video->setAttribute("poster", $this->cache->getUrl($thumb_filename)); + $need_saving = true; + } + } else { + $data = fetch_file_contents(["url" => $video_url, "max_size" => MAX_CACHE_FILE_SIZE]); + + if ($data) { + if ($this->cache->put($local_filename, $data)) { + if ($this->ffmpeg_thumbnail( + $this->cache->getFullPath($local_filename), + $this->cache->getFullPath($thumb_filename))) { + + $video->setAttribute("poster", $this->cache->getUrl($thumb_filename)); + $need_saving = true; + } + } + } + } + } + } + } + } + + if ($need_saving) + $article["content"] = $doc->saveHTML(); + } + + return $article; + } + + function api_version() { + return 2; + } +} -- cgit v1.2.3