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
|
||||
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
|
||||
touch /var/opt/mow/buf/index.html
|
||||
ln -sv /var/opt/mow/buf/index.html /var/opt/mow/web/index.html
|
||||
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
|
||||
touch /var/opt/mow/buf/theme.css
|
||||
ln -sv /var/opt/mow/buf/theme.css /var/opt/mow/web/theme.css
|
||||
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 ./bin/hls.js /var/opt/mow/web/hls.js
|
||||
|
||||
echo "writing /opt/mow/run"
|
||||
printf "#!/bin/sh\n" > /opt/mow/run
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
|
||||
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)
|
||||
{
|
||||
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 + "/img");
|
||||
|
||||
cleanup();
|
||||
|
||||
touch(shared.tmpDir + "/index.html");
|
||||
touch(shared.tmpDir + "/stream.html");
|
||||
touch(shared.tmpDir + "/stream.m3u8");
|
||||
|
||||
QFile::link(shared.tmpDir + "/live", shared.outDir + "/live");
|
||||
QFile::link(shared.tmpDir + "/logs", shared.outDir + "/logs");
|
||||
QFile::link(shared.tmpDir + "/img", shared.outDir + "/img");
|
||||
QFile::link(shared.tmpDir + "/index.html", shared.outDir + "/index.html");
|
||||
QFile::link(shared.tmpDir + "/stream.html", shared.outDir + "/stream.html");
|
||||
QFile::link(shared.tmpDir + "/stream.m3u8", shared.outDir + "/stream.m3u8");
|
||||
QFile::link(shared.outDir + "/events", shared.tmpDir + "/events");
|
||||
QProcess::execute("ln", {"-s", shared.tmpDir + "/live", shared.outDir + "/live"});
|
||||
QProcess::execute("ln", {"-s", shared.tmpDir + "/logs", shared.outDir + "/logs"});
|
||||
QProcess::execute("ln", {"-s", shared.tmpDir + "/img", shared.outDir + "/img"});
|
||||
QProcess::execute("ln", {"-s", shared.tmpDir + "/index.html", shared.outDir + "/index.html"});
|
||||
QProcess::execute("ln", {"-s", shared.tmpDir + "/stream.m3u8", shared.outDir + "/stream.m3u8"});
|
||||
QProcess::execute("ln", {"-s", shared.outDir + "/events", shared.tmpDir + "/events"});
|
||||
|
||||
if (!QDir::setCurrent(shared.tmpDir))
|
||||
{
|
||||
|
@ -142,7 +152,6 @@ void RecLoop::updateCmd()
|
|||
recArgs << "-hls_list_size" << "1000";
|
||||
recArgs << "-hls_flags" << "append_list+omit_endlist";
|
||||
recArgs << "-rtsp_transport" << "tcp";
|
||||
recArgs << "-stimeout" << "3000";
|
||||
recArgs << "-t" << QString::number(heartBeat);
|
||||
recArgs << "stream.m3u8";
|
||||
|
||||
|
@ -152,7 +161,6 @@ void RecLoop::updateCmd()
|
|||
imgArgs << "-strftime_mkdir" << "1";
|
||||
imgArgs << "-vf" << "fps=1,scale=320:240";
|
||||
imgArgs << "-rtsp_transport" << "tcp";
|
||||
imgArgs << "-stimeout" << "3000";
|
||||
imgArgs << "-t" << QString::number(heartBeat);
|
||||
imgArgs << "img/" + QString(STRFTIME_FMT) + ".bmp";
|
||||
|
||||
|
@ -233,10 +241,9 @@ bool Upkeep::exec()
|
|||
enforceMaxImages();
|
||||
enforceMaxVids();
|
||||
|
||||
genHTMLul(".", shared->camName, shared);
|
||||
|
||||
genFrontPage(shared);
|
||||
genCSS(shared);
|
||||
genHTMLul(shared->buffPath, QString(APP_NAME) + " " + QString(APP_VER), shared);
|
||||
genCamPage(shared);
|
||||
|
||||
return Loop::exec();
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ private:
|
|||
|
||||
shared_t shared;
|
||||
|
||||
void cleanup();
|
||||
|
||||
public:
|
||||
|
||||
explicit Camera(QObject *parent = nullptr);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
#define APP_VER "3.2.t2"
|
||||
#define APP_VER "3.2.t3"
|
||||
#define APP_NAME "Motion Watch"
|
||||
#define APP_BIN "mow"
|
||||
#define REC_LOG_NAME "rec_log_lines.html"
|
||||
|
|
150
src/web.cpp
150
src/web.cpp
|
@ -12,12 +12,8 @@
|
|||
|
||||
#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";
|
||||
|
||||
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 += "</head>\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");
|
||||
logNames = lsFilesInDir(outputDir + "/logs", "_log.html");
|
||||
htmlText += " <li><a href='" + dirName + "/index.html'>" + dirName + "</a></li>\n";
|
||||
}
|
||||
|
||||
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 += "<ul>\n";
|
||||
|
@ -49,13 +80,20 @@ void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
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 += "</html>";
|
||||
|
@ -90,51 +115,32 @@ void genHTMLul(const QString &outputDir, const QString &title, shared_t *share)
|
|||
outFile.close();
|
||||
}
|
||||
|
||||
void genHTMLstream(const QString &name)
|
||||
void genHTMLstream(QString &text)
|
||||
{
|
||||
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 += " <script src=\"https://cdn.jsdelivr.net/npm/hls.js@1\">\n";
|
||||
htmlText += " </script>\n";
|
||||
htmlText += " <video width=100% height=100% id=\"video\" controls>\n";
|
||||
htmlText += " </video>\n";
|
||||
htmlText += " <script>\n";
|
||||
htmlText += " var video = document.getElementById('video');\n";
|
||||
htmlText += " if (Hls.isSupported()) {\n";
|
||||
htmlText += " var hls = new Hls({\n";
|
||||
htmlText += " debug: true,\n";
|
||||
htmlText += " });\n";
|
||||
htmlText += " hls.loadSource('" + name + ".m3u8');\n";
|
||||
htmlText += " hls.attachMedia(video);\n";
|
||||
htmlText += " hls.on(Hls.Events.MEDIA_ATTACHED, function () {\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();
|
||||
text += "<script src=\"/hls.js\">\n";
|
||||
text += "</script>\n";
|
||||
text += "<video width=50% height=50% id=\"video\" controls>\n";
|
||||
text += "</video>\n";
|
||||
text += "<script>\n";
|
||||
text += " var video = document.getElementById('video');\n";
|
||||
text += " if (Hls.isSupported()) {\n";
|
||||
text += " var hls = new Hls({\n";
|
||||
text += " debug: true,\n";
|
||||
text += " });\n";
|
||||
text += " hls.loadSource('stream.m3u8');\n";
|
||||
text += " hls.attachMedia(video);\n";
|
||||
text += " hls.on(Hls.Events.MEDIA_ATTACHED, function () {\n";
|
||||
text += " video.muted = true;\n";
|
||||
text += " video.play();\n";
|
||||
text += " });\n";
|
||||
text += " }\n";
|
||||
text += " else if (video.canPlayType('application/vnd.apple.mpegurl')) {\n";
|
||||
text += " video.src = 'stream.m3u8';\n";
|
||||
text += " video.addEventListener('canplay', function () {\n";
|
||||
text += " video.play();\n";
|
||||
text += " });\n";
|
||||
text += " }\n";
|
||||
text += "</script>\n";
|
||||
}
|
||||
|
||||
void genHTMLvod(const QString &name)
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
|
||||
#include "common.h"
|
||||
|
||||
void genHTMLul(const QString &outputDir, const QString &title, shared_t *share);
|
||||
void genHTMLstream(const QString &name);
|
||||
void genFrontPage(shared_t *share);
|
||||
void genCamPage(shared_t *share);
|
||||
void genHTMLstream(QString &text);
|
||||
void genHTMLvod(const QString &name);
|
||||
void genCSS(shared_t *share);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user