-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:
Zii 2023-08-26 09:52:51 -04:00
parent 3791b29cf7
commit 8f80ce34f1
7 changed files with 115 additions and 94 deletions

2
bin/hls.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -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

View File

@ -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();
}

View File

@ -25,6 +25,8 @@ private:
shared_t shared;
void cleanup();
public:
explicit Camera(QObject *parent = nullptr);

View File

@ -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"

View File

@ -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)

View File

@ -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);