v3.2.t3
-the live stream is now a part of the camera's main page. -fixed symm links for the main page not being created on install. -removed deprecated ffmpeg timeout option. -copied hls.js as a local file so live streams will still work without being connected to the internet.
This commit is contained in:
parent
3791b29cf7
commit
8f80ce34f1
2
bin/hls.js
Normal file
2
bin/hls.js
Normal file
File diff suppressed because one or more lines are too long
15
install.sh
15
install.sh
|
@ -23,19 +23,22 @@ if [ ! -d "/var/opt/mow/web" ]; then
|
||||||
mkdir /var/opt/mow/web
|
mkdir /var/opt/mow/web
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f "/var/opt/mow/web/index.html" ]; then
|
if [ -e "/var/opt/mow/web/index.html" ]; then
|
||||||
rm -v /var/opt/mow/web/index.html
|
rm -v /var/opt/mow/web/index.html
|
||||||
touch /var/opt/mow/buf/index.html
|
|
||||||
ln -sv /var/opt/mow/buf/index.html /var/opt/mow/web/index.html
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f "/var/opt/mow/web/theme.css" ]; then
|
if [ -e "/var/opt/mow/web/theme.css" ]; then
|
||||||
rm -v /var/opt/mow/web/theme.css
|
rm -v /var/opt/mow/web/theme.css
|
||||||
touch /var/opt/mow/buf/theme.css
|
|
||||||
ln -sv /var/opt/mow/buf/theme.css /var/opt/mow/web/theme.css
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
touch /var/opt/mow/buf/index.html
|
||||||
|
touch /var/opt/mow/buf/theme.css
|
||||||
|
|
||||||
|
ln -sv /var/opt/mow/buf/index.html /var/opt/mow/web/index.html
|
||||||
|
ln -sv /var/opt/mow/buf/theme.css /var/opt/mow/web/theme.css
|
||||||
|
|
||||||
cp -v ./.build-mow/mow /opt/mow/bin
|
cp -v ./.build-mow/mow /opt/mow/bin
|
||||||
|
cp -v ./bin/hls.js /var/opt/mow/web/hls.js
|
||||||
|
|
||||||
echo "writing /opt/mow/run"
|
echo "writing /opt/mow/run"
|
||||||
printf "#!/bin/sh\n" > /opt/mow/run
|
printf "#!/bin/sh\n" > /opt/mow/run
|
||||||
|
|
|
@ -14,6 +14,16 @@
|
||||||
|
|
||||||
Camera::Camera(QObject *parent) : QObject(parent) {}
|
Camera::Camera(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
|
void Camera::cleanup()
|
||||||
|
{
|
||||||
|
QProcess::execute("rm", {shared.outDir + "/live"});
|
||||||
|
QProcess::execute("rm", {shared.outDir + "/logs"});
|
||||||
|
QProcess::execute("rm", {shared.outDir + "/img"});
|
||||||
|
QProcess::execute("rm", {shared.outDir + "/index.html"});
|
||||||
|
QProcess::execute("rm", {shared.outDir + "/stream.m3u8"});
|
||||||
|
QProcess::execute("rm", {shared.tmpDir + "/events"});
|
||||||
|
}
|
||||||
|
|
||||||
int Camera::start(const QStringList &args)
|
int Camera::start(const QStringList &args)
|
||||||
{
|
{
|
||||||
if (rdConf(getParam("-c", args), &shared))
|
if (rdConf(getParam("-c", args), &shared))
|
||||||
|
@ -26,17 +36,17 @@ int Camera::start(const QStringList &args)
|
||||||
QDir().mkpath(shared.tmpDir + "/logs");
|
QDir().mkpath(shared.tmpDir + "/logs");
|
||||||
QDir().mkpath(shared.tmpDir + "/img");
|
QDir().mkpath(shared.tmpDir + "/img");
|
||||||
|
|
||||||
|
cleanup();
|
||||||
|
|
||||||
touch(shared.tmpDir + "/index.html");
|
touch(shared.tmpDir + "/index.html");
|
||||||
touch(shared.tmpDir + "/stream.html");
|
|
||||||
touch(shared.tmpDir + "/stream.m3u8");
|
touch(shared.tmpDir + "/stream.m3u8");
|
||||||
|
|
||||||
QFile::link(shared.tmpDir + "/live", shared.outDir + "/live");
|
QProcess::execute("ln", {"-s", shared.tmpDir + "/live", shared.outDir + "/live"});
|
||||||
QFile::link(shared.tmpDir + "/logs", shared.outDir + "/logs");
|
QProcess::execute("ln", {"-s", shared.tmpDir + "/logs", shared.outDir + "/logs"});
|
||||||
QFile::link(shared.tmpDir + "/img", shared.outDir + "/img");
|
QProcess::execute("ln", {"-s", shared.tmpDir + "/img", shared.outDir + "/img"});
|
||||||
QFile::link(shared.tmpDir + "/index.html", shared.outDir + "/index.html");
|
QProcess::execute("ln", {"-s", shared.tmpDir + "/index.html", shared.outDir + "/index.html"});
|
||||||
QFile::link(shared.tmpDir + "/stream.html", shared.outDir + "/stream.html");
|
QProcess::execute("ln", {"-s", shared.tmpDir + "/stream.m3u8", shared.outDir + "/stream.m3u8"});
|
||||||
QFile::link(shared.tmpDir + "/stream.m3u8", shared.outDir + "/stream.m3u8");
|
QProcess::execute("ln", {"-s", shared.outDir + "/events", shared.tmpDir + "/events"});
|
||||||
QFile::link(shared.outDir + "/events", shared.tmpDir + "/events");
|
|
||||||
|
|
||||||
if (!QDir::setCurrent(shared.tmpDir))
|
if (!QDir::setCurrent(shared.tmpDir))
|
||||||
{
|
{
|
||||||
|
@ -142,7 +152,6 @@ void RecLoop::updateCmd()
|
||||||
recArgs << "-hls_list_size" << "1000";
|
recArgs << "-hls_list_size" << "1000";
|
||||||
recArgs << "-hls_flags" << "append_list+omit_endlist";
|
recArgs << "-hls_flags" << "append_list+omit_endlist";
|
||||||
recArgs << "-rtsp_transport" << "tcp";
|
recArgs << "-rtsp_transport" << "tcp";
|
||||||
recArgs << "-stimeout" << "3000";
|
|
||||||
recArgs << "-t" << QString::number(heartBeat);
|
recArgs << "-t" << QString::number(heartBeat);
|
||||||
recArgs << "stream.m3u8";
|
recArgs << "stream.m3u8";
|
||||||
|
|
||||||
|
@ -152,7 +161,6 @@ void RecLoop::updateCmd()
|
||||||
imgArgs << "-strftime_mkdir" << "1";
|
imgArgs << "-strftime_mkdir" << "1";
|
||||||
imgArgs << "-vf" << "fps=1,scale=320:240";
|
imgArgs << "-vf" << "fps=1,scale=320:240";
|
||||||
imgArgs << "-rtsp_transport" << "tcp";
|
imgArgs << "-rtsp_transport" << "tcp";
|
||||||
imgArgs << "-stimeout" << "3000";
|
|
||||||
imgArgs << "-t" << QString::number(heartBeat);
|
imgArgs << "-t" << QString::number(heartBeat);
|
||||||
imgArgs << "img/" + QString(STRFTIME_FMT) + ".bmp";
|
imgArgs << "img/" + QString(STRFTIME_FMT) + ".bmp";
|
||||||
|
|
||||||
|
@ -233,10 +241,9 @@ bool Upkeep::exec()
|
||||||
enforceMaxImages();
|
enforceMaxImages();
|
||||||
enforceMaxVids();
|
enforceMaxVids();
|
||||||
|
|
||||||
genHTMLul(".", shared->camName, shared);
|
genFrontPage(shared);
|
||||||
|
|
||||||
genCSS(shared);
|
genCSS(shared);
|
||||||
genHTMLul(shared->buffPath, QString(APP_NAME) + " " + QString(APP_VER), shared);
|
genCamPage(shared);
|
||||||
|
|
||||||
return Loop::exec();
|
return Loop::exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ private:
|
||||||
|
|
||||||
shared_t shared;
|
shared_t shared;
|
||||||
|
|
||||||
|
void cleanup();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit Camera(QObject *parent = nullptr);
|
explicit Camera(QObject *parent = nullptr);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#define APP_VER "3.2.t2"
|
#define APP_VER "3.2.t3"
|
||||||
#define APP_NAME "Motion Watch"
|
#define APP_NAME "Motion Watch"
|
||||||
#define APP_BIN "mow"
|
#define APP_BIN "mow"
|
||||||
#define REC_LOG_NAME "rec_log_lines.html"
|
#define REC_LOG_NAME "rec_log_lines.html"
|
||||||
|
|
150
src/web.cpp
150
src/web.cpp
|
@ -12,12 +12,8 @@
|
||||||
|
|
||||||
#include "web.h"
|
#include "web.h"
|
||||||
|
|
||||||
void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
void genFrontPage(shared_t *share)
|
||||||
{
|
{
|
||||||
QStringList logNames;
|
|
||||||
QStringList eveNames;
|
|
||||||
QStringList dirNames;
|
|
||||||
|
|
||||||
QString htmlText = "<!DOCTYPE html>\n";
|
QString htmlText = "<!DOCTYPE html>\n";
|
||||||
|
|
||||||
htmlText += "<html>\n";
|
htmlText += "<html>\n";
|
||||||
|
@ -29,12 +25,47 @@ void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
||||||
htmlText += "<link rel='stylesheet' href='/theme.css'>\n";
|
htmlText += "<link rel='stylesheet' href='/theme.css'>\n";
|
||||||
htmlText += "</head>\n";
|
htmlText += "</head>\n";
|
||||||
htmlText += "<body>\n";
|
htmlText += "<body>\n";
|
||||||
htmlText += "<h3>" + title + "</h3>\n";
|
htmlText += "<h3>" + QString(APP_NAME) + " " + QString(APP_VER) + "</h3>\n";
|
||||||
|
|
||||||
if (QDir().exists(outputDir + "/live"))
|
auto dirNames = lsDirsInDir(share->buffPath);
|
||||||
|
|
||||||
|
htmlText += "<ul>\n";
|
||||||
|
|
||||||
|
for (auto &&dirName : dirNames)
|
||||||
{
|
{
|
||||||
eveNames = lsFilesInDir(outputDir + "/events", ".html");
|
htmlText += " <li><a href='" + dirName + "/index.html'>" + dirName + "</a></li>\n";
|
||||||
logNames = lsFilesInDir(outputDir + "/logs", "_log.html");
|
}
|
||||||
|
|
||||||
|
htmlText += "</ul>\n";
|
||||||
|
htmlText += "</body>\n";
|
||||||
|
htmlText += "</html>";
|
||||||
|
|
||||||
|
QFile outFile(QDir().cleanPath(share->buffPath) + "/index.html");
|
||||||
|
|
||||||
|
outFile.open(QFile::WriteOnly);
|
||||||
|
outFile.write(htmlText.toUtf8());
|
||||||
|
outFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void genCamPage(shared_t *share)
|
||||||
|
{
|
||||||
|
auto outputDir = QDir().cleanPath(share->tmpDir);
|
||||||
|
QString htmlText = "<!DOCTYPE html>\n";
|
||||||
|
|
||||||
|
htmlText += "<html>\n";
|
||||||
|
htmlText += "<head>\n";
|
||||||
|
htmlText += "<meta http-equiv=\"Cache-Control\" content=\"no-cache, no-store, must-revalidate\" />\n";
|
||||||
|
htmlText += "<meta http-equiv=\"Pragma\" content=\"no-cache\" />\n";
|
||||||
|
htmlText += "<meta http-equiv=\"Expires\" content=\"0\" />\n";
|
||||||
|
htmlText += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n";
|
||||||
|
htmlText += "<link rel='stylesheet' href='/theme.css'>\n";
|
||||||
|
htmlText += "</head>\n";
|
||||||
|
htmlText += "<body>\n";
|
||||||
|
htmlText += "<h3>" + share->camName + "</h3>\n";
|
||||||
|
|
||||||
|
if (QDir().exists(outputDir + "/logs"))
|
||||||
|
{
|
||||||
|
auto logNames = lsFilesInDir(outputDir + "/logs", "_log.html");
|
||||||
|
|
||||||
htmlText += "<h4>Logs</h4>\n";
|
htmlText += "<h4>Logs</h4>\n";
|
||||||
htmlText += "<ul>\n";
|
htmlText += "<ul>\n";
|
||||||
|
@ -49,13 +80,20 @@ void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlText += "</ul>\n";
|
htmlText += "</ul>\n";
|
||||||
htmlText += "<h4>Live</h4>\n";
|
}
|
||||||
htmlText += "<ul>\n";
|
|
||||||
htmlText += " <li><a href='stream.html'>" + share->camName + ":live" + "</a></li>\n";
|
|
||||||
htmlText += "</ul>\n";
|
|
||||||
htmlText += "<h4>Motion Events</h4>\n";
|
|
||||||
|
|
||||||
genHTMLstream("stream");
|
if (QDir().exists(outputDir + "/live"))
|
||||||
|
{
|
||||||
|
htmlText += "<h4>Live</h4>\n";
|
||||||
|
|
||||||
|
genHTMLstream(htmlText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QDir().exists(outputDir + "/events"))
|
||||||
|
{
|
||||||
|
auto eveNames = lsFilesInDir(outputDir + "/events", ".html");
|
||||||
|
|
||||||
|
htmlText += "<h4>Motion Events</h4>\n";
|
||||||
|
|
||||||
for (auto &&eveName : eveNames)
|
for (auto &&eveName : eveNames)
|
||||||
{
|
{
|
||||||
|
@ -66,19 +104,6 @@ void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
||||||
htmlText += "<a href='events/" + eveName + "'><img src='events/" + 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
|
|
||||||
{
|
|
||||||
dirNames = lsDirsInDir(outputDir);
|
|
||||||
|
|
||||||
htmlText += "<ul>\n";
|
|
||||||
|
|
||||||
for (auto &&dirName : dirNames)
|
|
||||||
{
|
|
||||||
htmlText += " <li><a href='" + dirName + "/index.html'>" + dirName + "</a></li>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlText += "</ul>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
htmlText += "</body>\n";
|
htmlText += "</body>\n";
|
||||||
htmlText += "</html>";
|
htmlText += "</html>";
|
||||||
|
@ -90,51 +115,32 @@ void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
||||||
outFile.close();
|
outFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void genHTMLstream(const QString &name)
|
void genHTMLstream(QString &text)
|
||||||
{
|
{
|
||||||
QString htmlText = "<!DOCTYPE html>\n";
|
text += "<script src=\"/hls.js\">\n";
|
||||||
|
text += "</script>\n";
|
||||||
htmlText += "<html>\n";
|
text += "<video width=50% height=50% id=\"video\" controls>\n";
|
||||||
htmlText += "<head>\n";
|
text += "</video>\n";
|
||||||
htmlText += "<meta http-equiv=\"Cache-Control\" content=\"no-cache, no-store, must-revalidate\" />\n";
|
text += "<script>\n";
|
||||||
htmlText += "<meta http-equiv=\"Pragma\" content=\"no-cache\" />\n";
|
text += " var video = document.getElementById('video');\n";
|
||||||
htmlText += "<meta http-equiv=\"Expires\" content=\"0\" />\n";
|
text += " if (Hls.isSupported()) {\n";
|
||||||
htmlText += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n";
|
text += " var hls = new Hls({\n";
|
||||||
htmlText += "<link rel='stylesheet' href='/theme.css'>\n";
|
text += " debug: true,\n";
|
||||||
htmlText += "</head>\n";
|
text += " });\n";
|
||||||
htmlText += "<body>\n";
|
text += " hls.loadSource('stream.m3u8');\n";
|
||||||
htmlText += " <script src=\"https://cdn.jsdelivr.net/npm/hls.js@1\">\n";
|
text += " hls.attachMedia(video);\n";
|
||||||
htmlText += " </script>\n";
|
text += " hls.on(Hls.Events.MEDIA_ATTACHED, function () {\n";
|
||||||
htmlText += " <video width=100% height=100% id=\"video\" controls>\n";
|
text += " video.muted = true;\n";
|
||||||
htmlText += " </video>\n";
|
text += " video.play();\n";
|
||||||
htmlText += " <script>\n";
|
text += " });\n";
|
||||||
htmlText += " var video = document.getElementById('video');\n";
|
text += " }\n";
|
||||||
htmlText += " if (Hls.isSupported()) {\n";
|
text += " else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n";
|
||||||
htmlText += " var hls = new Hls({\n";
|
text += " video.src = 'stream.m3u8';\n";
|
||||||
htmlText += " debug: true,\n";
|
text += " video.addEventListener('canplay', function () {\n";
|
||||||
htmlText += " });\n";
|
text += " video.play();\n";
|
||||||
htmlText += " hls.loadSource('" + name + ".m3u8');\n";
|
text += " });\n";
|
||||||
htmlText += " hls.attachMedia(video);\n";
|
text += " }\n";
|
||||||
htmlText += " hls.on(Hls.Events.MEDIA_ATTACHED, function () {\n";
|
text += "</script>\n";
|
||||||
htmlText += " video.muted = true;\n";
|
|
||||||
htmlText += " video.play();\n";
|
|
||||||
htmlText += " });\n";
|
|
||||||
htmlText += " }\n";
|
|
||||||
htmlText += " else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n";
|
|
||||||
htmlText += " video.src = '" + name + ".m3u8';\n";
|
|
||||||
htmlText += " video.addEventListener('canplay', function () {\n";
|
|
||||||
htmlText += " video.play();\n";
|
|
||||||
htmlText += " });\n";
|
|
||||||
htmlText += " }\n";
|
|
||||||
htmlText += " </script>\n";
|
|
||||||
htmlText += "</body>\n";
|
|
||||||
htmlText += "</html>";
|
|
||||||
|
|
||||||
QFile outFile(name + ".html");
|
|
||||||
|
|
||||||
outFile.open(QFile::WriteOnly);
|
|
||||||
outFile.write(htmlText.toUtf8());
|
|
||||||
outFile.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void genHTMLvod(const QString &name)
|
void genHTMLvod(const QString &name)
|
||||||
|
|
|
@ -15,8 +15,9 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
void genHTMLul(const QString &outputDir, const QString &title, shared_t *share);
|
void genFrontPage(shared_t *share);
|
||||||
void genHTMLstream(const QString &name);
|
void genCamPage(shared_t *share);
|
||||||
|
void genHTMLstream(QString &text);
|
||||||
void genHTMLvod(const QString &name);
|
void genHTMLvod(const QString &name);
|
||||||
void genCSS(shared_t *share);
|
void genCSS(shared_t *share);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user