Improve media_updater to prevent it from crashing on video conversions, a=chris

Chris Pollett [2015-01-18 01:Jan:th]
Improve media_updater to prevent it from crashing on video conversions, a=chris
Filename
bin/media_updater.php
lib/crawl_daemon.php
diff --git a/bin/media_updater.php b/bin/media_updater.php
index acb071cb5..7d916a56e 100644
--- a/bin/media_updater.php
+++ b/bin/media_updater.php
@@ -203,91 +203,138 @@ class MediaUpdater implements CrawlConstants
      */
     function mediaConversion()
     {
+        static $to_convert_mp4 = "";
+        static $to_convert_mp4_thumb = "";
+        static $to_convert_webm = "";
+        static $to_convert_webm_thumb = "";
+        static $group_id, $page_id, $locale_tag, $page, $page_name;
         $convert_folder = WORK_DIRECTORY. "/schedules/media_convert";
         if(!defined('FFMPEG') || !file_exists($convert_folder)) { return; }
-        crawlLog("Checking for media files to convert...");
-        $to_convert = glob($convert_folder. "/*.txt");
-        if(!isset($to_convert[0])) {
-            crawlLog("...No media files found.");
-            return;
-        }
-        $convert_file_struct = file($to_convert[0]);
-        unlink($to_convert[0]);
-        if(!isset($convert_file_struct[2])) {
-            crawlLog("...Media conversion file mis-formatted... skipping");
-            return;
-        }
-        $group_model = $this->groupModel;
-        list($page_id, $media_path, $thumb_path, $media_file_name) =
-            $convert_file_struct;
-        $page_id = trim($page_id);
-        $info = $group_model->getPageInfoByPageId($page_id);
-        if(!$info) {
-            crawlLog("...Media page lookup failed ... skipping");
-            return;
-        }
-        $group_id = $info['GROUP_ID'];
-        $locale_tag = $info['LOCALE_TAG'];
-        $page_name = $info['PAGE_NAME'];
-        $full_info = $group_model->getPageInfoByName($group_id, $page_name,
-            $locale_tag, 'edit');
-        if(!$full_info) {
-            crawlLog("...Full Media page lookup failed ... skipping");
+        crawlLog("Entering media files to convert code...");
+        if($to_convert_mp4 == "" && $to_convert_webm == "" ) {
+            $to_convert = glob($convert_folder. "/*.txt");
+            if(!isset($to_convert[0])) {
+                crawlLog("...No media files found.");
+                return;
+            }
+            $convert_file_struct = file($to_convert[0]);
+            unlink($to_convert[0]);
+            if(!isset($convert_file_struct[2])) {
+                crawlLog("...Media conversion file mis-formatted... skipping");
+                return;
+            }
+            $group_model = $this->groupModel;
+            list($page_id, $media_path, $thumb_path, $media_file_name) =
+                $convert_file_struct;
+            $page_id = trim($page_id);
+            $info = $group_model->getPageInfoByPageId($page_id);
+            if(!$info) {
+                crawlLog("...Media page lookup failed ... skipping");
+                return;
+            }
+            $group_id = $info['GROUP_ID'];
+            $locale_tag = $info['LOCALE_TAG'];
+            $page_name = $info['PAGE_NAME'];
+            $full_info = $group_model->getPageInfoByName($group_id, $page_name,
+                $locale_tag, 'edit');
+            if(!$full_info) {
+                crawlLog("...Full Media page lookup failed ... skipping");
+                return;
+            }
+            $page = $full_info["PAGE"];
+            $media_base_name = $media_file_name;
+            $media_path = trim($media_path);
+            $thumb_path = trim($thumb_path);
+            if(($pos = strrpos($media_file_name, ".")) !== false) {
+                $media_base_name = substr($media_file_name, 0, $pos);
+            }
+            $input_media_file = "$media_path/$media_file_name";
+            $mp4_file = "$media_path/$media_base_name.mp4";
+            $webm_file = "$media_path/$media_base_name.webm";
+            if($input_media_file != $mp4_file) {
+                $ffmpeg = FFMPEG . " -i \"$input_media_file\" -y".
+                    " -vcodec h264 -acodec aac -preset veryfast -crf 28 ".
+                    "-strict -2 \"$mp4_file\" 2>&1";
+                crawlLog("Starting job to convert " . $media_file_name .
+                    " to mp4");
+                CrawlDaemon::execInOwnProcess($ffmpeg);
+                $to_convert_mp4 = $mp4_file;
+                $to_convert_mp4_thumb =
+                    "$thumb_path/$media_base_name.mp4.jpg";
+            }
+            if($input_media_file != $webm_file) {
+                $ffmpeg = FFMPEG . " -i \"$input_media_file\" -y".
+                    " -vcodec libvpx \"$webm_file\"";
+                crawlLog("Starting job to convert " . $media_file_name .
+                    " to webm");
+                CrawlDaemon::execInOwnProcess($ffmpeg);
+                $to_convert_webm = $webm_file;
+                $to_convert_webm_thumb =
+                    "$thumb_path/$media_base_name.webm.jpg";
+            }
+            crawlLog("...media file conversions have been started...");
             return;
         }
-        $media_base_name = $media_file_name;
-        $media_path = trim($media_path);
-        $thumb_path = trim($thumb_path);
-        if(($pos = strrpos($media_file_name, ".")) !== false) {
-            $media_base_name = substr($media_file_name, 0, $pos);
+        if($to_convert_mp4 && $this->isNoLongerModified($to_convert_mp4)) {
+                $this->thumbFileFromVideo($to_convert_mp4,
+                    $to_convert_mp4_thumb);
+                crawlLog(".. $to_convert_mp4 converted and thumb made.");
+                $to_convert_mp4 = "";
+                $to_convert_mp4_thumb = "";
         }
-        $input_media_file = "$media_path/$media_file_name";
-        $mp4_file = "$media_path/$media_base_name.mp4";
-        $webm_file = "$media_path/$media_base_name.webm";
-        if($input_media_file != $mp4_file) {
-            $ffmpeg = FFMPEG . " -i \"$input_media_file\" -y".
-                " -vcodec h264 -acodec aac -preset veryfast -crf 28 ".
-                "-strict -2 \"$mp4_file\" 2>&1";
-            crawlLog("Converting " . $media_file_name . " to mp4...");
-            exec($ffmpeg, $output);
-            CrawlDaemon::processHandler(true); //prevent timeout killing process
-            $make_thumb_string =
-                FFMPEG." -i \"$mp4_file\" -vframes 1 -map 0:v:0".
-                " -vf \"scale=".THUMB_DIM.":".THUMB_DIM."\" ".
-                "\"$thumb_path/$media_base_name.mp4.jpg\"";
-            $output = implode ("\n", $output);
-            crawlLog($output);
-            crawlLog("Making thumb with $make_thumb_string");
-            exec($make_thumb_string);
-            clearstatcache("$thumb_path/$media_base_name.mp4.jpg");
+        if($to_convert_webm && $this->isNoLongerModified($to_convert_webm)) {
+            $this->thumbFileFromVideo($to_convert_webm,
+                $to_convert_webm_thumb);
+            crawlLog(".. $to_convert_webm converted and thumb made.");
+            $to_convert_webm = "";
+            $to_convert_webm_thumb = "";
         }
-        if($input_media_file != $webm_file) {
-            $ffmpeg = FFMPEG . " -i \"$input_media_file\" -y".
-                " -vcodec libvpx \"$webm_file\"";
-            crawlLog("Converting " . $media_file_name . " to webm...");
-            exec($ffmpeg, $output);
-            $output = implode ("\n", $output);
-            CrawlDaemon::processHandler(true); //prevent timeout killing process
-            $make_thumb_string =
-                FFMPEG." -i \"$webm_file\" -vframes 1 -map 0:v:0".
-                " -vf \"scale=".THUMB_DIM.":".THUMB_DIM."\" ".
-                "\"$thumb_path/$media_base_name.webm.jpg\" 2>&1";
-
-            crawlLog($output);
-            crawlLog("Making thumb with $make_thumb_string");
-            exec($make_thumb_string);
-            clearstatcache("$thumb_path/$media_base_name.webm.jpg");
+        if($to_convert_mp4 == "" && $to_convert_webm == "" ) {
+            $parser = new WikiParser();
+            $parsed_page = $parser->parse($page);
+            if($parsed_page) {
+                crawlLog("... re-parsing media page $page_name...");
+                $parsed_page = $group_model->insertResourcesParsePage($group_id,
+                    $page_id, $locale_tag, $parsed_page);
+                $sql = "UPDATE GROUP_PAGE SET PAGE=? WHERE ID = ?";
+                $this->group_model->db->execute(
+                    $sql, array($parsed_page, $page_id));
+            }
         }
-        crawlLog("...media file conversion done...");
-        $parser = new WikiParser();
-        $parsed_page = $parser->parse($full_info["PAGE"]);
-        if($parsed_page) {
-            crawlLog("... re-parsing media page...");
-            $parsed_page = $group_model->insertResourcesParsePage($group_id,
-                $page_id, $locale_tag, $parsed_page);
-            $sql = "UPDATE GROUP_PAGE SET PAGE=? WHERE ID = ?";
-            $group_model->db->execute($sql, array($parsed_page, $page_id));
+    }
+    /**
+     * Checks if it has been more than two minutes since the last time
+     * a file was modified
+     *
+     * @param string $file_name file to check
+     * @return bool true if it has been more than two minutes
+     */
+    function isNoLongerModified($file_name)
+    {
+        if(file_exists($file_name)) {
+            clearstatcache($file_name);
+            if(time() < filemtime($file_name) + 2 * ONE_MINUTE) {
+                return false;
+            }
         }
+        return true;
+    }
+    /**
+     * Generates a thumbnail from a video file assuming FFMPEG
+     *
+     * @param string $video_name full name and path of video file to make
+     *      thumbnail from
+     * @param string $thumb_name full name and path for thumbnail file
+     */
+    function thumbFileFromVideo($video_name, $thumb_name)
+    {
+        $make_thumb_string =
+            FFMPEG." -i \"$video_name\" -vframes 1 -map 0:v:0".
+            " -vf \"scale=".THUMB_DIM.":".THUMB_DIM."\" ".
+            "\"$thumb_name\" 2>&1";
+        crawlLog("Making thumb with $make_thumb_string");
+        exec($make_thumb_string);
+        clearstatcache($thumb_name);
     }
 }
 /*
diff --git a/lib/crawl_daemon.php b/lib/crawl_daemon.php
index 28e0fc987..50a2000d2 100644
--- a/lib/crawl_daemon.php
+++ b/lib/crawl_daemon.php
@@ -242,12 +242,9 @@ class CrawlDaemon implements CrawlConstants
                 BASE_DIR."/bin/$name.php' child %s < /dev/null ".
                 " > /dev/null &";
         }
-
         $total_options = "$subname $options";
         $at_job = sprintf($script, $total_options);
-
         pclose(popen($at_job, "r"));
-
         if($exit != 0) {
             file_put_contents($lock_file,  time());
         }
@@ -255,6 +252,20 @@ class CrawlDaemon implements CrawlConstants
             exit();
         }
     }
+    /**
+     * Used to execute a shell command in its own process
+     *
+     * @param string $cmd the command to execute
+     */
+    function execInOwnProcess($cmd)
+    {
+        if(strstr(PHP_OS, "WIN")) {
+            $job = "start /B $cmd ";
+        } else {
+            $job = "$cmd < /dev/null > /dev/null &";
+        }
+        pclose(popen($job, "r"));
+    }
     /**
      * Used to stop a daemon that is running in the background
      *
ViewGit