v2.0.t8
Adjusted the event loop and motion detection to make better stand alone m3u8 files. Hopefully doing this will make browsers treat the recorded events as VODs instead of streams.
This commit is contained in:
parent
3c5dbec24c
commit
baa69da2cd
62
src/common.h
62
src/common.h
|
@ -28,6 +28,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <map>
|
||||
|
||||
#include <opencv4/opencv2/opencv.hpp>
|
||||
#include <opencv4/opencv2/videoio.hpp>
|
||||
|
@ -37,7 +38,7 @@ using namespace std;
|
|||
using namespace std::filesystem;
|
||||
using namespace std::chrono;
|
||||
|
||||
#define APP_VER "2.0.t7"
|
||||
#define APP_VER "2.0.t8"
|
||||
#define APP_NAME "Motion Watch"
|
||||
#define REC_LOG_NAME "rec_log_lines.html"
|
||||
#define DET_LOG_NAME "det_log_lines.html"
|
||||
|
@ -45,39 +46,40 @@ using namespace std::chrono;
|
|||
|
||||
struct pls_t
|
||||
{
|
||||
string fileName;
|
||||
string clipPath;
|
||||
string dstPath;
|
||||
string extINF;
|
||||
uint64_t createTime;
|
||||
Mat thumbnail;
|
||||
string evName;
|
||||
string dstPath;
|
||||
vector<string> srcPaths;
|
||||
vector<string> dstPaths;
|
||||
vector<string> extINFs;
|
||||
uint64_t createTime;
|
||||
Mat thumbnail;
|
||||
};
|
||||
|
||||
struct shared_t
|
||||
{
|
||||
vector<pls_t> recList;
|
||||
string conf;
|
||||
string recLog;
|
||||
string detLog;
|
||||
string upkLog;
|
||||
string recordUrl;
|
||||
string outDir;
|
||||
string postCmd;
|
||||
string camName;
|
||||
string webBg;
|
||||
string webTxt;
|
||||
string webFont;
|
||||
string webRoot;
|
||||
bool skipCmd;
|
||||
bool postCmdRunning;
|
||||
int schSec;
|
||||
int frameGap;
|
||||
int pixThresh;
|
||||
int imgThresh;
|
||||
int maxDays;
|
||||
int maxEvents;
|
||||
int maxLogSize;
|
||||
int retCode;
|
||||
map<string, pls_t> recList;
|
||||
string conf;
|
||||
string recLog;
|
||||
string detLog;
|
||||
string upkLog;
|
||||
string recordUrl;
|
||||
string outDir;
|
||||
string postCmd;
|
||||
string camName;
|
||||
string webBg;
|
||||
string webTxt;
|
||||
string webFont;
|
||||
string webRoot;
|
||||
bool skipCmd;
|
||||
bool postCmdRunning;
|
||||
int schSec;
|
||||
int frameGap;
|
||||
int pixThresh;
|
||||
int imgThresh;
|
||||
int maxDays;
|
||||
int maxEvents;
|
||||
int maxLogSize;
|
||||
int retCode;
|
||||
};
|
||||
|
||||
string genVidNameFromLive(const string &tsPath);
|
||||
|
|
44
src/main.cpp
44
src/main.cpp
|
@ -27,35 +27,37 @@ void eventLoop(shared_t *share)
|
|||
{
|
||||
while (share->retCode == 0)
|
||||
{
|
||||
while (!share->recList.empty())
|
||||
for (auto it = share->recList.begin(); !share->recList.empty();)
|
||||
{
|
||||
auto pls = share->recList[0];
|
||||
auto timeDiff = pls.createTime - genEpoch();
|
||||
auto evName = it->first;
|
||||
auto event = it->second;
|
||||
auto timeDiff = genEpoch() - event.createTime;
|
||||
|
||||
// future time protection. this should never occur but
|
||||
// this is in place in case the system time is incorrect.
|
||||
if (timeDiff < 0) timeDiff = 0;
|
||||
|
||||
// wait at least 6 seconds before processing the event in
|
||||
// queue.
|
||||
if (timeDiff < 6) sleep(6 - timeDiff);
|
||||
|
||||
try
|
||||
if (timeDiff > 0)
|
||||
{
|
||||
wrOutm3u8(pls, share);
|
||||
genHTMLvid(pls.fileName);
|
||||
// wait at least 61 seconds before processing the event in
|
||||
// queue.
|
||||
if (timeDiff < 61) sleep(61 - timeDiff);
|
||||
|
||||
if (!exists(pls.fileName + ".jpg"))
|
||||
try
|
||||
{
|
||||
imwrite(string(pls.fileName + ".jpg").c_str(), pls.thumbnail);
|
||||
}
|
||||
}
|
||||
catch (filesystem_error &ex)
|
||||
{
|
||||
recLog(string("err: ") + ex.what(), share);
|
||||
}
|
||||
wrOutm3u8(event, share);
|
||||
genHTMLvid(evName);
|
||||
|
||||
share->recList.erase(share->recList.begin());
|
||||
if (!exists(evName + ".jpg"))
|
||||
{
|
||||
imwrite(string(evName + ".jpg").c_str(), event.thumbnail);
|
||||
}
|
||||
}
|
||||
catch (filesystem_error &ex)
|
||||
{
|
||||
recLog(string("err: ") + ex.what(), share);
|
||||
}
|
||||
|
||||
share->recList.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
sleep(5);
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
void detectMoInStream(const string &bufPath, shared_t *share)
|
||||
{
|
||||
ifstream fileIn(bufPath);
|
||||
pls_t clip;
|
||||
string tsPath;
|
||||
string extINF;
|
||||
Mat thumbnail;
|
||||
|
||||
auto clipPathFilter = genTimeStr("VIDEO_TS/live/%Y/%j/%H/");
|
||||
|
||||
|
@ -23,25 +25,42 @@ void detectMoInStream(const string &bufPath, shared_t *share)
|
|||
{
|
||||
if (line.starts_with(clipPathFilter))
|
||||
{
|
||||
clip.clipPath = line;
|
||||
tsPath = line;
|
||||
}
|
||||
else if (line.starts_with("#EXTINF"))
|
||||
{
|
||||
clip.extINF = line;
|
||||
extINF = line;
|
||||
}
|
||||
}
|
||||
|
||||
if (!clip.clipPath.empty() && !clip.extINF.empty())
|
||||
if (!tsPath.empty() && !extINF.empty())
|
||||
{
|
||||
if (moDetect(clip.clipPath, clip.thumbnail, share))
|
||||
if (moDetect(tsPath, thumbnail, share))
|
||||
{
|
||||
clip.fileName = genTimeStr("%Y-%j-%H-%M");
|
||||
clip.dstPath = genEventPath(clip.clipPath);
|
||||
clip.createTime = genEpoch();
|
||||
auto eventName = genTimeStr("%Y-%j-%H-%M");
|
||||
|
||||
if (share->recList.find(eventName) != share->recList.end())
|
||||
{
|
||||
share->recList[eventName].srcPaths.push_back(tsPath);
|
||||
share->recList[eventName].dstPaths.push_back(genEventPath(tsPath));
|
||||
share->recList[eventName].extINFs.push_back(extINF);
|
||||
}
|
||||
else
|
||||
{
|
||||
pls_t event;
|
||||
|
||||
event.srcPaths.push_back(tsPath);
|
||||
event.dstPaths.push_back(genEventPath(tsPath));
|
||||
event.extINFs.push_back(extINF);
|
||||
|
||||
event.createTime = genEpoch();
|
||||
event.thumbnail = thumbnail.clone();
|
||||
event.evName = eventName;
|
||||
|
||||
share->recList.insert(pair{eventName, event});
|
||||
}
|
||||
|
||||
share->skipCmd = true;
|
||||
|
||||
share->recList.push_back(clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,38 +136,32 @@ bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
|||
return mod;
|
||||
}
|
||||
|
||||
void wrOutm3u8(const pls_t &pls, shared_t *share)
|
||||
void wrOutm3u8(const pls_t &event, shared_t *share)
|
||||
{
|
||||
recLog("live-to-event-src: " + pls.clipPath, share);
|
||||
recLog("live-to-event-dst: " + pls.dstPath, share);
|
||||
auto plsFile = event.evName + ".m3u8";
|
||||
|
||||
createDirTree(path(pls.dstPath).parent_path().string());
|
||||
copy_file(pls.clipPath, pls.dstPath);
|
||||
ofstream file(plsFile.c_str());
|
||||
|
||||
auto plsFile = pls.fileName + ".m3u8";
|
||||
file << "#EXTM3U" << endl;
|
||||
file << "#EXT-X-VERSION:3" << endl;
|
||||
file << "#EXT-X-TARGETDURATION:10" << endl;
|
||||
file << "#EXT-X-MEDIA-SEQUENCE:0" << endl;
|
||||
file << "#EXT-X-START:TIME-OFFSET=0" << endl;
|
||||
file << "#EXT-X-PLAYLIST-TYPE:VOD" << endl;
|
||||
|
||||
if (exists(plsFile))
|
||||
for (auto i = 0; i < event.extINFs.size(); ++i)
|
||||
{
|
||||
ofstream file(plsFile.c_str(), ofstream::app);
|
||||
auto src = event.srcPaths[i];
|
||||
auto dst = event.dstPaths[i];
|
||||
|
||||
file << endl;
|
||||
file << pls.extINF << endl;
|
||||
file << pls.dstPath;
|
||||
createDirTree(path(dst).parent_path().string());
|
||||
copy_file(src, dst);
|
||||
|
||||
file.close();
|
||||
file << event.extINFs[i] << endl;
|
||||
file << dst << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
ofstream file(plsFile.c_str());
|
||||
|
||||
file << "#EXTM3U" << endl;
|
||||
file << "#EXT-X-VERSION:3" << endl;
|
||||
file << "#EXT-X-TARGETDURATION:10" << endl;
|
||||
file << "#EXT-X-MEDIA-SEQUENCE:0" << endl;
|
||||
file << "#EXT-X-DISCONTINUITY" << endl;
|
||||
file << pls.extINF << endl;
|
||||
file << pls.dstPath;
|
||||
file << "#EXT-X-ENDLIST" << endl;
|
||||
|
||||
file.close();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
|
|
@ -51,10 +51,7 @@ void genHTMLul(const string &outputDir, const string &title, shared_t *share)
|
|||
htmlText += "</ul>\n";
|
||||
htmlText += "<h4>Motion Events</h4>\n";
|
||||
|
||||
if (!exists("stream.html"))
|
||||
{
|
||||
genHTMLvid("stream");
|
||||
}
|
||||
genHTMLvid("stream");
|
||||
}
|
||||
|
||||
for (auto &®Name : regNames)
|
||||
|
@ -71,7 +68,7 @@ void genHTMLul(const string &outputDir, const string &title, shared_t *share)
|
|||
// regName.substr(0, regName.size() - 5) removes .html
|
||||
auto name = regName.substr(0, regName.size() - 5);
|
||||
|
||||
htmlText += "<a href='" + regName + "'><img src='" + name + ".jpg" + "' style='width:12%;height:12%;'</a>\n";
|
||||
htmlText += "<a href='" + regName + "'><img src='" + name + ".jpg" + "' style='width:25%;height:25%;'</a>\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user