api.modet.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. /**
  3. * Basic records motion detection/filtering implementation
  4. */
  5. class MoDet {
  6. /**
  7. * CLI abstraction layer
  8. *
  9. * @var object
  10. */
  11. protected $cliFF = '';
  12. /**
  13. * Stardust instance
  14. *
  15. * @var object
  16. */
  17. protected $process = '';
  18. /**
  19. * some predefined stuff
  20. */
  21. const PROCESS_PID = 'MOTIONDETECTOR';
  22. const OPTION_ENABLE = 'MODET_ENABLED';
  23. const FILTERED_MARK = 'motion';
  24. const WRAPPER = '/bin/wrapi';
  25. public function __construct() {
  26. $this->initStarDust();
  27. $this->initCliFF();
  28. }
  29. /**
  30. * Inits CLI abstraction layer instance
  31. *
  32. * @return void
  33. */
  34. protected function initCliFF() {
  35. $this->cliFF = new CliFF();
  36. }
  37. /**
  38. * Inits StarDust process manager for further usage
  39. *
  40. * @return void
  41. */
  42. protected function initStarDust() {
  43. $this->process = new StarDust(self::PROCESS_PID);
  44. }
  45. /**
  46. * Returns new recording filename with filtered motion
  47. *
  48. * @param string $filePath
  49. *
  50. * @return string
  51. */
  52. protected function getFilteredFileName($filePath) {
  53. $result = '';
  54. if (!empty($filePath)) {
  55. $result .= str_replace(Export::RECORDS_EXT, '_' . self::FILTERED_MARK . Export::RECORDS_EXT, $filePath);
  56. }
  57. return ($result);
  58. }
  59. /**
  60. * Returns current user recordings path
  61. *
  62. * @return void
  63. */
  64. protected function getUserRecordingsDir() {
  65. $result = '';
  66. $userLogin = whoami();
  67. if (!empty($userLogin)) {
  68. $fullUserPath = Export::PATH_RECORDS . $userLogin;
  69. if (file_exists($fullUserPath)) {
  70. $result = $fullUserPath . '/'; //with ending slash
  71. }
  72. }
  73. return ($result);
  74. }
  75. /**
  76. * Runs motion detection filtering process
  77. *
  78. * @param string $filePathEnc
  79. * @param int $threshold
  80. * @param int $timeScale
  81. *
  82. * @return void
  83. */
  84. public function startMotionFilteringProcess($filePathEnc, $threshold = 0, $timeScale = 0) {
  85. $filePath = @base64_decode($filePathEnc);
  86. $threshold = ubRouting::filters($threshold, 'int');
  87. $timeScale = ubRouting::filters($timeScale, 'int');
  88. if (!empty($filePath)) {
  89. if (file_exists($filePath)) {
  90. if ($this->process->notRunning()) {
  91. $newFilePath = $this->getFilteredFileName($filePath);
  92. if ($newFilePath) {
  93. if (!file_exists($newFilePath)) {
  94. if (!ispos($filePath, '_' . self::FILTERED_MARK . Export::RECORDS_EXT)) {
  95. $this->process->start();
  96. log_register('MOTION FILTERING `' . $filePath . '` STARTED');
  97. if ($threshold and $timeScale) {
  98. $this->cliFF->setMoDetParams($threshold, $timeScale);
  99. }
  100. $command = $this->cliFF->getFFmpegPath() . ' -i ' . $filePath . ' ' . $this->cliFF->getMoDetOpts() . ' ' . $newFilePath;
  101. shell_exec($command);
  102. log_register('MOTION FILTERING `' . $newFilePath . '` FINISHED');
  103. $this->process->stop();
  104. //few checks
  105. if (file_exists($newFilePath)) {
  106. if (filesize($newFilePath) < 1024) {
  107. rcms_delete_files($newFilePath);
  108. log_register('MOTION FILTERING `' . $newFilePath . '` FAILED CORRUPTED');
  109. }
  110. } else {
  111. log_register('MOTION FILTERING `' . $newFilePath . '` FAILED NOT EXISTS');
  112. }
  113. }
  114. }
  115. }
  116. }
  117. }
  118. }
  119. }
  120. /**
  121. * Schedules background motion detection process for background execution
  122. *
  123. * @param string $fileNameEnc
  124. * @param int $threshold
  125. * @param int $timeScale
  126. *
  127. * @return void
  128. */
  129. public function runMotionFiltering($fileNameEnc, $threshold = 0, $timeScale = 0) {
  130. $result = '';
  131. $userRecordingsDir = $this->getUserRecordingsDir();
  132. $fileName = @base64_decode($fileNameEnc);
  133. $threshold = ubRouting::filters($threshold, 'int');
  134. $timeScale = ubRouting::filters($timeScale, 'int');
  135. if (!empty($fileName)) {
  136. $filePath = $userRecordingsDir . $fileName;
  137. $newFileName = $this->getFilteredFileName($fileName);
  138. $newFilePath = $userRecordingsDir . $newFileName;
  139. if (file_exists($filePath)) {
  140. if (!file_exists($newFilePath)) {
  141. if ($this->process->notRunning()) {
  142. if ($newFilePath) {
  143. if (!ispos($filePath, '_' . self::FILTERED_MARK . Export::RECORDS_EXT)) {
  144. $bgUrl = '"';
  145. $bgUrl .= 'modet&mdfp=' . base64_encode($filePath);
  146. if ($threshold and $timeScale) {
  147. $bgUrl .= '&th=' . $threshold . '&ts=' . $timeScale;
  148. }
  149. $bgUrl .= '"';
  150. $procCmd = self::WRAPPER . ' ' . $bgUrl;
  151. $this->process->runBackgroundProcess($procCmd, 0);
  152. log_register('MOTION FILTERING `' . $newFileName . '` SENS `' . $threshold . '` TSCALE `' . $timeScale . '` SCHEDULED');
  153. } else {
  154. $result .= __('Something went wrong') . ' - ' . __('Record') . ' ' . __('already filtered');
  155. }
  156. } else {
  157. $result .= __('Something went wrong');
  158. }
  159. } else {
  160. $result .= __('Motion filtering service is busy at this moment') . '. ' . __('Please try again later') . '.';
  161. }
  162. } else {
  163. $result .= __('Motion filtering') . ' ' . __('for this record') . ' - ' . __('already exists');
  164. }
  165. } else {
  166. $result .= __('File not exists');
  167. }
  168. } else {
  169. $result .= __('Path') . ' ' . __('is empty');
  170. }
  171. return ($result);
  172. }
  173. /**
  174. * Just renders successfull motion detection schedule notification and confirmation
  175. *
  176. *
  177. * @return string
  178. */
  179. public function renderScheduledNotify() {
  180. $result = '';
  181. $notification = '';
  182. $notification .= wf_tag('center') . wf_img('skins/checked.png') . wf_tag('center', true);
  183. $notification .= wf_delimiter(0);
  184. $notification .= __('Motion filtering for your video is running in the background. It may take some time.') . '.';
  185. $notification .= wf_delimiter();
  186. $notification .= wf_tag('center') . wf_Link(Export::URL_RECORDS, __('Got it') . '!', true, 'confirmagree') . wf_tag('center', true);
  187. $result .= wf_modalOpenedAuto(__('Motion filtering'), $notification);
  188. return ($result);
  189. }
  190. }