v2.0.t13
Fixed the crashing issue by adding tcp timeout args to ffmpeg and having the app handle empty frames from a disconnected camera better. Reformed the directory structure by having live, logs and events in seperate directories. schLoop() no longer exists, postCmd is now handled by detectMoInStream() to ensure motion detection is not done while the command is running.
This commit is contained in:
parent
93723bb7b1
commit
83b206c06c
|
@ -134,16 +134,17 @@ void cleanupStream(const string &plsPath)
|
||||||
|
|
||||||
void enforceMaxEvents(shared_t *share)
|
void enforceMaxEvents(shared_t *share)
|
||||||
{
|
{
|
||||||
auto names = lsFilesInDir(".", ".mp4");
|
auto names = lsFilesInDir("events", ".mp4");
|
||||||
|
|
||||||
while (names.size() > share->maxEvents)
|
while (names.size() > share->maxEvents)
|
||||||
{
|
{
|
||||||
// removes the playlist file extension.
|
// removes the video file extension (.mp4).
|
||||||
auto nameOnly = names[0].substr(0, names[0].size() - 4);
|
auto nameOnly = "events/" + names[0].substr(0, names[0].size() - 4);
|
||||||
auto imgFile = nameOnly + ".jpg";
|
auto mp4File = nameOnly + string(".mp4");
|
||||||
auto webFile = nameOnly + ".html";
|
auto imgFile = nameOnly + string(".jpg");
|
||||||
|
auto webFile = nameOnly + string(".html");
|
||||||
|
|
||||||
if (exists(names[0])) remove(names[0]);
|
if (exists(mp4File)) remove(mp4File);
|
||||||
if (exists(imgFile)) remove(imgFile);
|
if (exists(imgFile)) remove(imgFile);
|
||||||
if (exists(webFile)) remove(webFile);
|
if (exists(webFile)) remove(webFile);
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ using namespace std;
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
#define APP_VER "2.0.t12"
|
#define APP_VER "2.0.t13"
|
||||||
#define APP_NAME "Motion Watch"
|
#define APP_NAME "Motion Watch"
|
||||||
#define REC_LOG_NAME "rec_log_lines.html"
|
#define REC_LOG_NAME "rec_log_lines.html"
|
||||||
#define DET_LOG_NAME "det_log_lines.html"
|
#define DET_LOG_NAME "det_log_lines.html"
|
||||||
|
@ -67,8 +67,9 @@ struct shared_t
|
||||||
string webTxt;
|
string webTxt;
|
||||||
string webFont;
|
string webFont;
|
||||||
string webRoot;
|
string webRoot;
|
||||||
|
mutex detMutex;
|
||||||
bool skipCmd;
|
bool skipCmd;
|
||||||
bool postCmdRunning;
|
int procTime;
|
||||||
int schSec;
|
int schSec;
|
||||||
int frameGap;
|
int frameGap;
|
||||||
int pixThresh;
|
int pixThresh;
|
||||||
|
|
|
@ -38,7 +38,7 @@ void enforceMaxLogSize(const string &filePath, shared_t *share)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpLogs(const char *fileName, const string &lines)
|
void dumpLogs(const string &fileName, const string &lines)
|
||||||
{
|
{
|
||||||
if (!lines.empty())
|
if (!lines.empty())
|
||||||
{
|
{
|
||||||
|
@ -46,11 +46,11 @@ void dumpLogs(const char *fileName, const string &lines)
|
||||||
|
|
||||||
if (exists(fileName))
|
if (exists(fileName))
|
||||||
{
|
{
|
||||||
outFile.open(fileName, ofstream::app);
|
outFile.open(fileName.c_str(), ofstream::app);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outFile.open(fileName);
|
outFile.open(fileName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile << lines;
|
outFile << lines;
|
||||||
|
@ -116,7 +116,7 @@ void initLogFrontPage(const string &filePath, const string &logLinesFile)
|
||||||
|
|
||||||
void initLogFrontPages(shared_t *share)
|
void initLogFrontPages(shared_t *share)
|
||||||
{
|
{
|
||||||
initLogFrontPage("recording_log.html", REC_LOG_NAME);
|
initLogFrontPage("logs/recording_log.html", REC_LOG_NAME);
|
||||||
initLogFrontPage("detection_log.html", DET_LOG_NAME);
|
initLogFrontPage("logs/detection_log.html", DET_LOG_NAME);
|
||||||
initLogFrontPage("upkeep_log.html", UPK_LOG_NAME);
|
initLogFrontPage("logs/upkeep_log.html", UPK_LOG_NAME);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
void recLog(const string &line, shared_t *share);
|
void recLog(const string &line, shared_t *share);
|
||||||
void detLog(const string &line, shared_t *share);
|
void detLog(const string &line, shared_t *share);
|
||||||
void upkLog(const string &line, shared_t *share);
|
void upkLog(const string &line, shared_t *share);
|
||||||
void dumpLogs(const char *fileName, const string &lines);
|
void dumpLogs(const string &fileName, const string &lines);
|
||||||
void enforceMaxLogSize(const string &filePath, shared_t *share);
|
void enforceMaxLogSize(const string &filePath, shared_t *share);
|
||||||
void initLogFrontPages(shared_t *share);
|
void initLogFrontPages(shared_t *share);
|
||||||
|
|
||||||
|
|
88
src/main.cpp
Executable file → Normal file
88
src/main.cpp
Executable file → Normal file
|
@ -27,24 +27,26 @@ void eventLoop(shared_t *share)
|
||||||
{
|
{
|
||||||
while (share->retCode == 0)
|
while (share->retCode == 0)
|
||||||
{
|
{
|
||||||
for (auto it = share->recList.begin(); !share->recList.empty();)
|
while (!share->recList.empty())
|
||||||
{
|
{
|
||||||
|
auto it = share->recList.begin();
|
||||||
auto evName = it->first;
|
auto evName = it->first;
|
||||||
auto event = it->second;
|
auto event = it->second;
|
||||||
auto timeDiff = genEpoch() - event.createTime;
|
auto timeDiff = genEpoch() - event.createTime;
|
||||||
|
|
||||||
// wait at least 61 seconds before processing the event in
|
// wait at least 62 seconds before processing the event in
|
||||||
// queue.
|
// queue.
|
||||||
if ((timeDiff > 0) && (timeDiff > 60))
|
if ((timeDiff > 0) && (timeDiff > 62))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
createDirTree("events");
|
||||||
wrOutVod(event, share);
|
wrOutVod(event, share);
|
||||||
genHTMLvod(evName);
|
genHTMLvod(evName);
|
||||||
|
|
||||||
if (!exists(evName + ".jpg"))
|
if (!exists("events/" + evName + ".jpg"))
|
||||||
{
|
{
|
||||||
imwrite(string(evName + ".jpg").c_str(), event.thumbnail);
|
imwrite(string("events/" + evName + ".jpg").c_str(), event.thumbnail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (filesystem_error &ex)
|
catch (filesystem_error &ex)
|
||||||
|
@ -54,36 +56,11 @@ void eventLoop(shared_t *share)
|
||||||
|
|
||||||
share->recList.erase(it);
|
share->recList.erase(it);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sleep(5);
|
sleep(5);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void schLoop(shared_t *share)
|
sleep(5);
|
||||||
{
|
|
||||||
if (!share->postCmd.empty())
|
|
||||||
{
|
|
||||||
while (share->retCode == 0)
|
|
||||||
{
|
|
||||||
sleep(share->schSec);
|
|
||||||
|
|
||||||
if (!share->skipCmd)
|
|
||||||
{
|
|
||||||
share->postCmdRunning = true;
|
|
||||||
|
|
||||||
detLog("no motion detected, running post command: " + share->postCmd, share);
|
|
||||||
system(share->postCmd.c_str());
|
|
||||||
|
|
||||||
share->postCmdRunning = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
share->skipCmd = false;
|
|
||||||
|
|
||||||
detLog("motion detected, skipping the post command.", share);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,13 +68,17 @@ void upkeep(shared_t *share)
|
||||||
{
|
{
|
||||||
while (share->retCode == 0)
|
while (share->retCode == 0)
|
||||||
{
|
{
|
||||||
enforceMaxLogSize(REC_LOG_NAME, share);
|
createDirTree("live");
|
||||||
enforceMaxLogSize(DET_LOG_NAME, share);
|
createDirTree("events");
|
||||||
enforceMaxLogSize(UPK_LOG_NAME, share);
|
createDirTree("logs");
|
||||||
|
|
||||||
dumpLogs(REC_LOG_NAME, share->recLog);
|
enforceMaxLogSize(string("logs/") + REC_LOG_NAME, share);
|
||||||
dumpLogs(DET_LOG_NAME, share->detLog);
|
enforceMaxLogSize(string("logs/") + DET_LOG_NAME, share);
|
||||||
dumpLogs(UPK_LOG_NAME, share->upkLog);
|
enforceMaxLogSize(string("logs/") + UPK_LOG_NAME, share);
|
||||||
|
|
||||||
|
dumpLogs(string("logs/") + REC_LOG_NAME, share->recLog);
|
||||||
|
dumpLogs(string("logs/") + DET_LOG_NAME, share->detLog);
|
||||||
|
dumpLogs(string("logs/") + UPK_LOG_NAME, share->upkLog);
|
||||||
|
|
||||||
share->recLog.clear();
|
share->recLog.clear();
|
||||||
share->detLog.clear();
|
share->detLog.clear();
|
||||||
|
@ -105,7 +86,6 @@ void upkeep(shared_t *share)
|
||||||
|
|
||||||
initLogFrontPages(share);
|
initLogFrontPages(share);
|
||||||
enforceMaxEvents(share);
|
enforceMaxEvents(share);
|
||||||
cleanupEmptyDirs("VIDEO_TS");
|
|
||||||
|
|
||||||
genHTMLul(".", share->camName, share);
|
genHTMLul(".", share->camName, share);
|
||||||
|
|
||||||
|
@ -134,14 +114,19 @@ void recLoop(shared_t *share)
|
||||||
{
|
{
|
||||||
while (share->retCode == 0)
|
while (share->retCode == 0)
|
||||||
{
|
{
|
||||||
auto cmd = "ffmpeg -hide_banner -i " +
|
if (exists("live"))
|
||||||
|
{
|
||||||
|
remove_all("live");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cmd = "ffmpeg -hide_banner -rtsp_transport tcp -timeout 3000000 -i " +
|
||||||
share->recordUrl +
|
share->recordUrl +
|
||||||
" -strftime 1" +
|
" -strftime 1" +
|
||||||
" -strftime_mkdir 1" +
|
" -strftime_mkdir 1" +
|
||||||
" -hls_segment_filename 'VIDEO_TS/live/%Y/%j/%H/%M%S.ts'" +
|
" -hls_segment_filename 'live/%Y-%j-%H-%M-%S.ts'" +
|
||||||
|
" -hls_flags delete_segments" +
|
||||||
" -y -vcodec copy" +
|
" -y -vcodec copy" +
|
||||||
" -f hls -hls_time 6 -hls_list_size " +
|
" -f hls -hls_time 10 -hls_list_size 400" +
|
||||||
to_string((share->maxDays * 86400) / 6) + // 86400 seconds in a day.
|
|
||||||
" stream.m3u8";
|
" stream.m3u8";
|
||||||
|
|
||||||
recLog("ffmpeg_run: " + cmd, share);
|
recLog("ffmpeg_run: " + cmd, share);
|
||||||
|
@ -155,7 +140,7 @@ void recLoop(shared_t *share)
|
||||||
recLog("err: ffmpeg returned non zero, indicating failure. please check stderr output.", share);
|
recLog("err: ffmpeg returned non zero, indicating failure. please check stderr output.", share);
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(60);
|
sleep(10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,27 +169,20 @@ int main(int argc, char** argv)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sharedRes.retCode = 0;
|
sharedRes.retCode = 0;
|
||||||
|
sharedRes.procTime = 0;
|
||||||
sharedRes.skipCmd = false;
|
sharedRes.skipCmd = false;
|
||||||
sharedRes.postCmdRunning = false;
|
|
||||||
|
|
||||||
rdConf(&sharedRes);
|
rdConf(&sharedRes);
|
||||||
|
|
||||||
if (exists("VIDEO_TS/live"))
|
|
||||||
{
|
|
||||||
remove_all("VIDEO_TS/live");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto thr1 = thread(recLoop, &sharedRes);
|
auto thr1 = thread(recLoop, &sharedRes);
|
||||||
auto thr2 = thread(upkeep, &sharedRes);
|
auto thr2 = thread(upkeep, &sharedRes);
|
||||||
//auto thr3 = thread(detectMo, &sharedRes);
|
auto thr3 = thread(detectMo, &sharedRes);
|
||||||
//auto thr4 = thread(eventLoop, &sharedRes);
|
auto thr4 = thread(eventLoop, &sharedRes);
|
||||||
auto thr5 = thread(schLoop, &sharedRes);
|
|
||||||
|
|
||||||
thr1.join();
|
thr1.join();
|
||||||
thr2.join();
|
thr2.join();
|
||||||
//thr3.join();
|
thr3.join();
|
||||||
//thr4.join();
|
thr4.join();
|
||||||
thr5.join();
|
|
||||||
|
|
||||||
return sharedRes.retCode;
|
return sharedRes.retCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,17 +12,31 @@
|
||||||
|
|
||||||
#include "mo_detect.h"
|
#include "mo_detect.h"
|
||||||
|
|
||||||
void detectMoInStream(const string &bufPath, shared_t *share)
|
void detectMoInStream(const string &streamFile, shared_t *share)
|
||||||
{
|
{
|
||||||
ifstream fileIn(bufPath);
|
if (share->procTime >= share->schSec)
|
||||||
|
{
|
||||||
|
if (!share->skipCmd)
|
||||||
|
{
|
||||||
|
detLog("no motion detected, running post command: " + share->postCmd, share);
|
||||||
|
system(share->postCmd.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
share->skipCmd = false;
|
||||||
|
share->procTime = 0;
|
||||||
|
|
||||||
|
detLog("motion detected, skipping the post command.", share);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ifstream fileIn(streamFile);
|
||||||
string tsPath;
|
string tsPath;
|
||||||
Mat thumbnail;
|
Mat thumbnail;
|
||||||
|
|
||||||
auto clipPathFilter = genTimeStr("VIDEO_TS/live/%Y/%j/%H/");
|
|
||||||
|
|
||||||
for (string line; getline(fileIn, line); )
|
for (string line; getline(fileIn, line); )
|
||||||
{
|
{
|
||||||
if (line.starts_with(clipPathFilter))
|
if (line.starts_with("live/"))
|
||||||
{
|
{
|
||||||
tsPath = line;
|
tsPath = line;
|
||||||
}
|
}
|
||||||
|
@ -53,31 +67,35 @@ void detectMoInStream(const string &bufPath, shared_t *share)
|
||||||
|
|
||||||
share->skipCmd = true;
|
share->skipCmd = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
share->procTime += 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool imgDiff(Mat &prev, Mat &next, shared_t *share)
|
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share)
|
||||||
{
|
{
|
||||||
auto ret = false;
|
Mat prevGray;
|
||||||
|
Mat nextGray;
|
||||||
|
|
||||||
cvtColor(prev, prev, COLOR_BGR2GRAY);
|
cvtColor(prev, prevGray, COLOR_BGR2GRAY);
|
||||||
cvtColor(next, next, COLOR_BGR2GRAY);
|
cvtColor(next, nextGray, COLOR_BGR2GRAY);
|
||||||
|
|
||||||
Mat diff;
|
Mat diff;
|
||||||
|
|
||||||
absdiff(prev, next, diff);
|
absdiff(prevGray, nextGray, diff);
|
||||||
threshold(diff, diff, share->pixThresh, 255, THRESH_BINARY);
|
threshold(diff, diff, share->pixThresh, 255, THRESH_BINARY);
|
||||||
|
|
||||||
auto diffScore = countNonZero(diff);
|
score = countNonZero(diff);
|
||||||
|
|
||||||
detLog("diff_score: " + to_string(diffScore), share);
|
detLog("diff_score: " + to_string(score) + " tresh: " + to_string(share->imgThresh), share);
|
||||||
|
|
||||||
return diffScore >= share->imgThresh;
|
return score >= share->imgThresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
||||||
{
|
{
|
||||||
auto mod = false;
|
auto maxScore = 0;
|
||||||
|
auto score = 0;
|
||||||
|
|
||||||
detLog("stream_clip: " + buffFile, share);
|
detLog("stream_clip: " + buffFile, share);
|
||||||
|
|
||||||
|
@ -100,13 +118,18 @@ bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
||||||
{
|
{
|
||||||
capture.retrieve(next);
|
capture.retrieve(next);
|
||||||
|
|
||||||
if (!share->postCmdRunning)
|
lock_guard<mutex> guard(share->detMutex);
|
||||||
{
|
|
||||||
if (imgDiff(prev, next, share))
|
|
||||||
{
|
|
||||||
resize(next, vidThumb, Size(720, 480), INTER_LINEAR);
|
|
||||||
|
|
||||||
mod = true; break;
|
if (!next.empty())
|
||||||
|
{
|
||||||
|
if (imgDiff(prev, next, score, share))
|
||||||
|
{
|
||||||
|
if (score > maxScore)
|
||||||
|
{
|
||||||
|
maxScore = score;
|
||||||
|
|
||||||
|
resize(next, vidThumb, Size(720, 480), INTER_LINEAR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +147,7 @@ bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share)
|
||||||
|
|
||||||
capture.release();
|
capture.release();
|
||||||
|
|
||||||
return mod;
|
return maxScore > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrOutVod(const pls_t &event, shared_t *share)
|
void wrOutVod(const pls_t &event, shared_t *share)
|
||||||
|
@ -140,6 +163,6 @@ void wrOutVod(const pls_t &event, shared_t *share)
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
system(string("ffmpeg -f concat -safe 0 -i " + concat + " -c copy " + event.evName + ".mp4").c_str());
|
system(string("ffmpeg -f concat -safe 0 -i " + concat + " -c copy events/" + event.evName + ".mp4").c_str());
|
||||||
remove(concat);
|
remove(concat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
|
||||||
bool imgDiff(Mat &prev, Mat &next, shared_t *share);
|
bool imgDiff(const Mat &prev, const Mat &next, int &score, shared_t *share);
|
||||||
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share);
|
bool moDetect(const string &buffFile, Mat &vidThumb, shared_t *share);
|
||||||
void detectMoInStream(const string &bufPath, shared_t *share);
|
void detectMoInStream(const string &streamFile, shared_t *share);
|
||||||
void wrOutVod(const pls_t &pls, shared_t *share);
|
void wrOutVod(const pls_t &pls, shared_t *share);
|
||||||
|
|
||||||
#endif // MO_DETECT_H
|
#endif // MO_DETECT_H
|
||||||
|
|
54
src/web.cpp
54
src/web.cpp
|
@ -15,8 +15,8 @@
|
||||||
void genHTMLul(const string &outputDir, const string &title, shared_t *share)
|
void genHTMLul(const string &outputDir, const string &title, shared_t *share)
|
||||||
{
|
{
|
||||||
vector<string> logNames;
|
vector<string> logNames;
|
||||||
vector<string> regNames = lsFilesInDir(outputDir);
|
vector<string> eveNames;
|
||||||
vector<string> dirNames = lsDirsInDir(outputDir);
|
vector<string> dirNames;
|
||||||
|
|
||||||
string htmlText = "<!DOCTYPE html>\n";
|
string htmlText = "<!DOCTYPE html>\n";
|
||||||
|
|
||||||
|
@ -31,20 +31,23 @@ void genHTMLul(const string &outputDir, const string &title, shared_t *share)
|
||||||
htmlText += "<body>\n";
|
htmlText += "<body>\n";
|
||||||
htmlText += "<h3>" + title + "</h3>\n";
|
htmlText += "<h3>" + title + "</h3>\n";
|
||||||
|
|
||||||
if (!dirNames.empty() && !exists(outputDir + "/VIDEO_TS"))
|
if (exists(outputDir + "/live"))
|
||||||
{
|
{
|
||||||
|
eveNames = lsFilesInDir(outputDir + "/events", ".html");
|
||||||
|
logNames = lsFilesInDir(outputDir + "/logs", "_log.html");
|
||||||
|
|
||||||
|
htmlText += "<h4>Logs</h4>\n";
|
||||||
htmlText += "<ul>\n";
|
htmlText += "<ul>\n";
|
||||||
|
|
||||||
for (auto &&dirName : dirNames)
|
for (auto &&logName : logNames)
|
||||||
{
|
{
|
||||||
htmlText += " <li><a href='" + dirName + "/index.html'>" + dirName + "</a></li>\n";
|
// name.substr(0, name.size() - 9) removes _log.html
|
||||||
|
auto name = logName.substr(0, logName.size() - 9);
|
||||||
|
|
||||||
|
htmlText += " <li><a href='logs/" + logName + "'>" + name + "</a></li>\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlText += "</ul>\n";
|
htmlText += "</ul>\n";
|
||||||
}
|
|
||||||
|
|
||||||
if (exists(outputDir + "/VIDEO_TS"))
|
|
||||||
{
|
|
||||||
htmlText += "<h4>Live</h4>\n";
|
htmlText += "<h4>Live</h4>\n";
|
||||||
htmlText += "<ul>\n";
|
htmlText += "<ul>\n";
|
||||||
htmlText += " <li><a href='stream.html'>" + share->camName + ":live" + "</a></li>\n";
|
htmlText += " <li><a href='stream.html'>" + share->camName + ":live" + "</a></li>\n";
|
||||||
|
@ -52,35 +55,24 @@ void genHTMLul(const string &outputDir, const string &title, shared_t *share)
|
||||||
htmlText += "<h4>Motion Events</h4>\n";
|
htmlText += "<h4>Motion Events</h4>\n";
|
||||||
|
|
||||||
genHTMLstream("stream");
|
genHTMLstream("stream");
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &®Name : regNames)
|
for (auto &&eveName : eveNames)
|
||||||
{
|
|
||||||
if (regName.ends_with("_log.html"))
|
|
||||||
{
|
|
||||||
logNames.push_back(regName);
|
|
||||||
}
|
|
||||||
else if (regName.ends_with(".html") &&
|
|
||||||
!regName.ends_with("index.html") &&
|
|
||||||
!regName.ends_with("stream.html") &&
|
|
||||||
!regName.ends_with("_log_lines.html"))
|
|
||||||
{
|
{
|
||||||
// regName.substr(0, regName.size() - 5) removes .html
|
// regName.substr(0, regName.size() - 5) removes .html
|
||||||
auto name = regName.substr(0, regName.size() - 5);
|
auto name = eveName.substr(0, eveName.size() - 5);
|
||||||
|
|
||||||
htmlText += "<a href='" + regName + "'><img src='" + name + ".jpg" + "' style='width:25%;height:25%;'</a>\n";
|
htmlText += "<a href='events/" + eveName + "'><img src='events/" + name + ".jpg" + "' style='width:25%;height:25%;'</a>\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!logNames.empty())
|
|
||||||
{
|
{
|
||||||
htmlText += "<h4>Logs</h4>\n";
|
dirNames = lsDirsInDir(outputDir);
|
||||||
|
|
||||||
htmlText += "<ul>\n";
|
htmlText += "<ul>\n";
|
||||||
|
|
||||||
for (auto &&name : logNames)
|
for (auto &&dirName : dirNames)
|
||||||
{
|
{
|
||||||
// name.substr(0, name.size() - 9) removes _log.html
|
htmlText += " <li><a href='" + dirName + "/index.html'>" + dirName + "</a></li>\n";
|
||||||
htmlText += " <li><a href='" + name + "'>" + name.substr(0, name.size() - 9) + "</a></li>\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlText += "</ul>\n";
|
htmlText += "</ul>\n";
|
||||||
|
@ -119,7 +111,7 @@ void genHTMLstream(const string &name)
|
||||||
htmlText += " var hls = new Hls({\n";
|
htmlText += " var hls = new Hls({\n";
|
||||||
htmlText += " debug: true,\n";
|
htmlText += " debug: true,\n";
|
||||||
htmlText += " });\n";
|
htmlText += " });\n";
|
||||||
htmlText += " hls.loadSource('stream.m3u8');\n";
|
htmlText += " hls.loadSource('" + name + ".m3u8');\n";
|
||||||
htmlText += " hls.attachMedia(video);\n";
|
htmlText += " hls.attachMedia(video);\n";
|
||||||
htmlText += " hls.on(Hls.Events.MEDIA_ATTACHED, function () {\n";
|
htmlText += " hls.on(Hls.Events.MEDIA_ATTACHED, function () {\n";
|
||||||
htmlText += " video.muted = true;\n";
|
htmlText += " video.muted = true;\n";
|
||||||
|
@ -127,7 +119,7 @@ void genHTMLstream(const string &name)
|
||||||
htmlText += " });\n";
|
htmlText += " });\n";
|
||||||
htmlText += " }\n";
|
htmlText += " }\n";
|
||||||
htmlText += " else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n";
|
htmlText += " else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n";
|
||||||
htmlText += " video.src = 'stream.m3u8';\n";
|
htmlText += " video.src = '" + name + ".m3u8';\n";
|
||||||
htmlText += " video.addEventListener('canplay', function () {\n";
|
htmlText += " video.addEventListener('canplay', function () {\n";
|
||||||
htmlText += " video.play();\n";
|
htmlText += " video.play();\n";
|
||||||
htmlText += " });\n";
|
htmlText += " });\n";
|
||||||
|
@ -162,7 +154,7 @@ void genHTMLvod(const string &name)
|
||||||
htmlText += "</body>\n";
|
htmlText += "</body>\n";
|
||||||
htmlText += "</html>";
|
htmlText += "</html>";
|
||||||
|
|
||||||
ofstream file(string(name + ".html").c_str());
|
ofstream file(string("events/" + name + ".html").c_str());
|
||||||
|
|
||||||
file << htmlText << endl;
|
file << htmlText << endl;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user