canView()) { global $user; ZM\Warning('User '.($user?$user['Username']:'').' cannot view event '.$event->Id()); continue; } if (!isset($events_by_monitor_id[$event->MonitorId()])) $events_by_monitor_id[$event->MonitorId()] = []; $events_by_monitor_id[$event->MonitorId()][] = $event; if (!$event->DefaultVideo()) $event->GenerateVideo(); } $exportFileList = []; foreach (array_keys($events_by_monitor_id) as $mid) { $monitor = ZM\Monitor::find_one(['Id'=>$mid]); if (!$monitor) { ZM\Error("No monitor found for id $mid"); continue; } usort($events_by_monitor_id[$mid], function($a, $b) { return strtotime($a->StartDateTime) <=> strtotime($b->StartDateTime); }); $eventFileList = ''; $minTimeSecs = -1; $minTime = ''; $maxTimeSecs = -1; $maxTime = ''; foreach ($events_by_monitor_id[$mid] as $event) { if ($minTimeSecs == -1 or $minTimeSecs > $event->StartDateTimeSecs()) { $minTimeSecs = $event->StartDateTimeSecs(); $minTime = $event->StartDateTime(); } if ($maxTimeSecs == -1 or $maxTimeSecs < $event->StartDateTimeSecs()) { $maxTimeSecs = $event->StartDateTimeSecs(); $maxTime = $event->StartDateTime(); } $eventFileList .= 'file \''.$event->Path().'/'.$event->DefaultVideo().'\''.PHP_EOL; } $mergedFileName = $monitor->Name().' '.$minTime.' to '.$maxTime.'.mp4'; if (($fp = fopen('event_files.txt', 'w'))) { fwrite($fp, $eventFileList); fclose($fp); } else { ZM\Error("Can't open event images export file 'event_files.txt'"); } $cmd = ZM_PATH_FFMPEG.' -f concat -safe 0 -i event_files.txt -c copy \''.$export_dir.'/'.$mergedFileName. '\' 2>&1'; exec($cmd, $output, $return); ZM\Debug($cmd.' return code: '.$return.' output: '.print_r($output,true)); $exportFileList[] = $mergedFileName; unlink('event_files.txt'); } # end foreach monitor $export_listFile = 'FileList.txt'; $listFile = $export_dir.'/'.$export_listFile; if (!($fp = fopen($listFile, 'w'))) { ZM\Error("Can't open event export list file '$listFile'"); return false; } foreach ($exportFileList as $exportFile) { $exportFile = $export_root.'/'.$exportFile; fwrite($fp, $exportFile.PHP_EOL); } fwrite($fp, $export_listFile.PHP_EOL); fclose($fp); chdir(ZM_DIR_EXPORTS); $archive = ''; if ($exportFormat == 'tar') { $archive = $export_root.'.tar'; $version = @shell_exec('tar --version'); ZM\Debug("Version $version"); $command = 'tar --create --dereference'; if ($exportCompressed) { $archive .= '.gz'; $command .= ' --gzip'; $exportFormat .= '.gz'; } if ($exportStructure == 'flat') { if (preg_match('/BSD/i', $version)) { $command .= ' -s \'#^.*/##\''; } else { $command .= ' --xform=\'s#^.+/##x\''; } } $archive_path = ZM_DIR_EXPORTS.'/'.$archive; $command .= ' --file='.escapeshellarg($archive_path); } else if ($exportFormat == 'zip') { $archive = $export_root.'.zip'; $archive_path = ZM_DIR_EXPORTS.'/'.$archive; $command = 'zip -r '; $command .= ($exportStructure == 'flat' ? ' -j ' : '').escapeshellarg($archive_path); $command .= $exportCompressed ? ' -9' : ' -0'; } // if $exportFormat @unlink($archive_path); # delete it if it exists already $command .= ' '.$export_root.'/'; ZM\Debug($command); exec($command, $output, $status); if ($status) { ZM\Error("Command '$command' returned with status $status"); if (isset($output[0])) { ZM\Error('First line of output is \''.$output[0].'\''); } return false; } // clean up temporary files if (!empty($html_eventMaster)) { unlink($monitorPath.'/'.$html_eventMaster); } return '?view=archive&type='.$exportFormat.'&file='.$archive; } // end function exportEvents