Spaces:
Paused
Paused
blenders
commited on
Commit
·
5afa8d3
1
Parent(s):
383b262
new
Browse files- Dockerfile +88 -0
- init.sh +119 -0
- mime.types +73 -0
- nginx.conf +106 -0
- stat.xsl +0 -0
- www/index.html +20 -0
- www/script.js +41 -0
Dockerfile
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM ubuntu:22.04
|
| 2 |
+
|
| 3 |
+
# Build args (change if upstream playit repo changes)
|
| 4 |
+
ARG PLAYIT_GPG_URL="https://playit-cloud.github.io/ppa/key.gpg"
|
| 5 |
+
ARG PLAYIT_APT_LINE="deb [signed-by=/etc/apt/trusted.gpg.d/playit.gpg] https://playit-cloud.github.io/ppa/data ./"
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
ENV DEBIAN_FRONTEND=noninteractive \
|
| 9 |
+
TZ=Etc/UTC \
|
| 10 |
+
LANG=C.UTF-8
|
| 11 |
+
|
| 12 |
+
USER root
|
| 13 |
+
# Install dependencies
|
| 14 |
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
| 15 |
+
build-essential \
|
| 16 |
+
libpcre3 libpcre3-dev \
|
| 17 |
+
libssl-dev \
|
| 18 |
+
zlib1g-dev \
|
| 19 |
+
wget \
|
| 20 |
+
nginx \
|
| 21 |
+
ffmpeg \
|
| 22 |
+
git \
|
| 23 |
+
build-essential \
|
| 24 |
+
libpcre3 libpcre3-dev \
|
| 25 |
+
libssl-dev \
|
| 26 |
+
wget \
|
| 27 |
+
curl \
|
| 28 |
+
unzip \
|
| 29 |
+
openssl \
|
| 30 |
+
apt-transport-https \
|
| 31 |
+
ca-certificates \
|
| 32 |
+
gnupg \
|
| 33 |
+
dirmngr \
|
| 34 |
+
tzdata \
|
| 35 |
+
gettext-base \
|
| 36 |
+
; \
|
| 37 |
+
# ensure tzdata doesn't prompt (already set TZ env); configure timezone non-interactively
|
| 38 |
+
ln -fs /usr/share/zoneinfo/$TZ /etc/localtime; \
|
| 39 |
+
dpkg-reconfigure --frontend noninteractive tzdata || true; \
|
| 40 |
+
# prepare apt trusted key location
|
| 41 |
+
mkdir -p /etc/apt/trusted.gpg.d; \
|
| 42 |
+
# fetch playit GPG key and dearmor it for apt
|
| 43 |
+
curl -fsSL "${PLAYIT_GPG_URL}" -o /tmp/playit.key.gpg; \
|
| 44 |
+
gpg --dearmor --batch --yes -o /etc/apt/trusted.gpg.d/playit.gpg /tmp/playit.key.gpg; \
|
| 45 |
+
rm -f /tmp/playit.key.gpg; \
|
| 46 |
+
# add apt source list
|
| 47 |
+
echo "${PLAYIT_APT_LINE}" > /etc/apt/sources.list.d/playit-cloud.list; \
|
| 48 |
+
apt-get update; \
|
| 49 |
+
# Install playit, telling dpkg to accept default config answers if asked
|
| 50 |
+
apt-get install -y --no-install-recommends -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" playit; \
|
| 51 |
+
# cleanup apt caches
|
| 52 |
+
apt-get clean; \
|
| 53 |
+
rm -rf /var/lib/apt/lists/* /tmp/*
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# Install Nginx with RTMP module
|
| 58 |
+
RUN mkdir -p /opt/nginx && \
|
| 59 |
+
cd /opt/nginx && \
|
| 60 |
+
git clone https://github.com/arut/nginx-rtmp-module.git && \
|
| 61 |
+
wget http://nginx.org/download/nginx-1.25.0.tar.gz && \
|
| 62 |
+
tar -zxvf nginx-1.25.0.tar.gz && \
|
| 63 |
+
cd nginx-1.25.0 && \
|
| 64 |
+
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module && \
|
| 65 |
+
make && make install
|
| 66 |
+
|
| 67 |
+
RUN mkdir -p /tmp/nginx /tmp/nginx/logs /tmp/nginx/proxy_temp /tmp/nginx/html /tmp/nginx/html/media/hls /tmp/nginx/html/media/rhls /tmp/nginx/html/media/recordings \
|
| 68 |
+
&& chmod -R 777 /tmp/nginx /tmp/nginx/html
|
| 69 |
+
RUN chmod -R 755 /tmp/nginx/html/media
|
| 70 |
+
# Copy configs and web UI
|
| 71 |
+
COPY nginx.conf /tmp/nginx/nginx.conf
|
| 72 |
+
COPY www/ /tmp/nginx/html/
|
| 73 |
+
COPY mime.types /tmp/nginx/mime.types
|
| 74 |
+
|
| 75 |
+
# Copy entrypoint
|
| 76 |
+
COPY init.sh /tmp/nginx/entrypoint.sh
|
| 77 |
+
RUN chmod +x /tmp/nginx/entrypoint.sh
|
| 78 |
+
RUN chmod +x /tmp/nginx/logs
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
# Expose only HF Spaces allowed port
|
| 82 |
+
EXPOSE 7860/tcp
|
| 83 |
+
|
| 84 |
+
# Workdir
|
| 85 |
+
WORKDIR /tmp/app
|
| 86 |
+
USER root
|
| 87 |
+
ENTRYPOINT ["/tmp/nginx/entrypoint.sh"]
|
| 88 |
+
CMD []
|
init.sh
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
set -euo pipefail
|
| 3 |
+
|
| 4 |
+
LOG_PREFIX="[playit-entrypoint]"
|
| 5 |
+
PLAYIT_ENV_BIN="${PLAYIT_BIN:-}"
|
| 6 |
+
CANDIDATE_PATHS=(
|
| 7 |
+
"/usr/bin/playit"
|
| 8 |
+
"/usr/local/bin/playit"
|
| 9 |
+
"/opt/playit/playit"
|
| 10 |
+
)
|
| 11 |
+
PLAYIT_LOG="/tmp/playit.log"
|
| 12 |
+
PLAYIT_SECRET_VAR="${PLAYIT_SECRET:-}"
|
| 13 |
+
# cp "/usr/local/nginx/sbin/nginx" "/tmp/nginx/sbin/nginx"
|
| 14 |
+
# NGINX_BIN="/tmp/nginx/sbin/nginx"
|
| 15 |
+
NGINX_CONF="/tmp/nginx/nginx.conf"
|
| 16 |
+
NGINX_ORIG_CONF_DIR="/usr/local/nginx/conf"
|
| 17 |
+
LOG_DIR="/tmp/nginx/logs"
|
| 18 |
+
PROXY_TEMP="/tmp/nginx/proxy_temp"
|
| 19 |
+
if [ -x "/usr/local/nginx/sbin/nginx" ]; then
|
| 20 |
+
mkdir -p /tmp/nginx/sbin
|
| 21 |
+
|
| 22 |
+
# Copy mime.types and stat.xsl for nginx http block
|
| 23 |
+
cp "${NGINX_ORIG_CONF_DIR}/mime.types" /tmp/nginx/mime.types
|
| 24 |
+
cp "${NGINX_ORIG_CONF_DIR}/stat.xsl" /tmp/nginx/stat.xsl
|
| 25 |
+
# Then copy the binary
|
| 26 |
+
cp /usr/local/nginx/sbin/nginx /tmp/nginx/sbin/nginx
|
| 27 |
+
chmod +x /tmp/nginx/sbin/nginx
|
| 28 |
+
NGINX_BIN="/tmp/nginx/sbin/nginx"
|
| 29 |
+
else
|
| 30 |
+
echo "$LOG_PREFIX nginx binary not found at /usr/local/nginx/sbin/nginx" >&2
|
| 31 |
+
exit 1
|
| 32 |
+
fi
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
echo "$LOG_PREFIX starting entrypoint..."
|
| 36 |
+
|
| 37 |
+
determine_playit_bin() {
|
| 38 |
+
if [ -n "${PLAYIT_ENV_BIN:-}" ]; then
|
| 39 |
+
if [ -x "$PLAYIT_ENV_BIN" ]; then
|
| 40 |
+
echo "$PLAYIT_ENV_BIN"
|
| 41 |
+
return 0
|
| 42 |
+
else
|
| 43 |
+
echo "$LOG_PREFIX PLAYIT_BIN is set but not executable: $PLAYIT_ENV_BIN" >&2
|
| 44 |
+
return 1
|
| 45 |
+
fi
|
| 46 |
+
fi
|
| 47 |
+
|
| 48 |
+
if command -v playit >/dev/null 2>&1; then
|
| 49 |
+
command -v playit
|
| 50 |
+
return 0
|
| 51 |
+
fi
|
| 52 |
+
|
| 53 |
+
for p in "${CANDIDATE_PATHS[@]}"; do
|
| 54 |
+
if [ -x "$p" ]; then
|
| 55 |
+
echo "$p"
|
| 56 |
+
return 0
|
| 57 |
+
fi
|
| 58 |
+
done
|
| 59 |
+
|
| 60 |
+
return 1
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
# Find binary
|
| 64 |
+
if PLAYIT_BIN_PATH="$(determine_playit_bin)"; then
|
| 65 |
+
echo "$LOG_PREFIX playit binary found: $PLAYIT_BIN_PATH"
|
| 66 |
+
else
|
| 67 |
+
echo "$LOG_PREFIX playit binary NOT found. Will continue but playit won't run." >&2
|
| 68 |
+
PLAYIT_BIN_PATH=""
|
| 69 |
+
fi
|
| 70 |
+
|
| 71 |
+
# Prepare playit log
|
| 72 |
+
rm -f "$PLAYIT_LOG" || true
|
| 73 |
+
touch "$PLAYIT_LOG"
|
| 74 |
+
chmod 600 "$PLAYIT_LOG" || true
|
| 75 |
+
|
| 76 |
+
PLAYIT_PID=0
|
| 77 |
+
|
| 78 |
+
start_playit() {
|
| 79 |
+
if [ -n "${PLAYIT_BIN_PATH}" ] && [ -n "${PLAYIT_SECRET_VAR}" ]; then
|
| 80 |
+
echo "$LOG_PREFIX starting playit agent..."
|
| 81 |
+
# quote secret to avoid word-splitting; use nohup so it doesn't die when shell exits
|
| 82 |
+
nohup "$PLAYIT_BIN_PATH" --secret "$PLAYIT_SECRET_VAR" start >>"$PLAYIT_LOG" 2>&1 &
|
| 83 |
+
PLAYIT_PID=$!
|
| 84 |
+
echo "$LOG_PREFIX Playit agent started with PID=$PLAYIT_PID"
|
| 85 |
+
else
|
| 86 |
+
if [ -z "${PLAYIT_BIN_PATH}" ]; then
|
| 87 |
+
echo "$LOG_PREFIX playit binary not available; skipping playit startup"
|
| 88 |
+
else
|
| 89 |
+
echo "$LOG_PREFIX PLAYIT_SECRET not provided; skipping playit startup"
|
| 90 |
+
fi
|
| 91 |
+
fi
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
stop_playit() {
|
| 95 |
+
if [ "$PLAYIT_PID" -ne 0 ] && kill -0 "$PLAYIT_PID" >/dev/null 2>&1; then
|
| 96 |
+
echo "$LOG_PREFIX stopping playit (pid=$PLAYIT_PID)"
|
| 97 |
+
kill "$PLAYIT_PID" || true
|
| 98 |
+
sleep 1
|
| 99 |
+
kill -9 "$PLAYIT_PID" 2>/dev/null || true
|
| 100 |
+
fi
|
| 101 |
+
}
|
| 102 |
+
|
| 103 |
+
# Trap termination to stop playit cleanly
|
| 104 |
+
trap 'echo "$LOG_PREFIX received termination signal"; stop_playit; exit 0' TERM INT
|
| 105 |
+
|
| 106 |
+
# Start playit (if configured)
|
| 107 |
+
start_playit
|
| 108 |
+
|
| 109 |
+
echo "$LOG_PREFIX starting nginx..."
|
| 110 |
+
|
| 111 |
+
mkdir -p /tmp/nginx/{logs,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp,sbin,html}
|
| 112 |
+
# chmod 1777 /tmp/nginx/logs /tmp/nginx/proxy_temp
|
| 113 |
+
# chmod 1777 /tmp/nginx/fastcgi_temp /tmp/nginx/uwsgi_temp /tmp/nginx/scgi_temp
|
| 114 |
+
#chmod 1777 /tmp/nginx /tmp/media
|
| 115 |
+
|
| 116 |
+
NGINX_PREFIX="/tmp/nginx"
|
| 117 |
+
exec "$NGINX_BIN" -c "$NGINX_CONF" -p "$NGINX_PREFIX" -g "daemon off;"
|
| 118 |
+
# exec "$NGINX_BIN" -c "$NGINX_CONF" -g "daemon off;"
|
| 119 |
+
echo "$LOG_PREFIX nginx started"
|
mime.types
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Basic mime.types for Nginx
|
| 2 |
+
types {
|
| 3 |
+
text/html html htm shtml;
|
| 4 |
+
text/css css;
|
| 5 |
+
text/xml xml rss;
|
| 6 |
+
image/gif gif;
|
| 7 |
+
image/jpeg jpeg jpg;
|
| 8 |
+
application/javascript js;
|
| 9 |
+
application/atom+xml atom;
|
| 10 |
+
text/mathml mml;
|
| 11 |
+
text/plain txt;
|
| 12 |
+
text/vnd.sun.j2me.app-descriptor jad;
|
| 13 |
+
text/vnd.wap.wml wml;
|
| 14 |
+
text/x-component htc;
|
| 15 |
+
image/png png;
|
| 16 |
+
image/tiff tif tiff;
|
| 17 |
+
image/vnd.wap.wbmp wbmp;
|
| 18 |
+
image/x-icon ico;
|
| 19 |
+
image/x-jng jng;
|
| 20 |
+
image/x-ms-bmp bmp;
|
| 21 |
+
image/svg+xml svg svgz;
|
| 22 |
+
image/webp webp;
|
| 23 |
+
application/font-woff woff;
|
| 24 |
+
application/java-archive jar war ear;
|
| 25 |
+
application/json json;
|
| 26 |
+
application/mac-binhex40 hqx;
|
| 27 |
+
application/msword doc;
|
| 28 |
+
application/pdf pdf;
|
| 29 |
+
application/postscript ps eps ai;
|
| 30 |
+
application/rtf rtf;
|
| 31 |
+
application/vnd.ms-excel xls;
|
| 32 |
+
application/vnd.ms-powerpoint ppt;
|
| 33 |
+
application/vnd.wap.wmlc wmlc;
|
| 34 |
+
application/vnd.google-earth.kml+xml kml;
|
| 35 |
+
application/vnd.google-earth.kmz kmz;
|
| 36 |
+
application/x-7z-compressed 7z;
|
| 37 |
+
application/x-cocoa cco;
|
| 38 |
+
application/x-java-archive-diff jardiff;
|
| 39 |
+
application/x-java-jnlp-file jnlp;
|
| 40 |
+
application/x-makeself run;
|
| 41 |
+
application/x-perl pl pm;
|
| 42 |
+
application/x-pilot prc pdb;
|
| 43 |
+
application/x-rar-compressed rar;
|
| 44 |
+
application/x-redhat-package-manager rpm;
|
| 45 |
+
application/x-sea sea;
|
| 46 |
+
application/x-shockwave-flash swf;
|
| 47 |
+
application/x-stuffit sit;
|
| 48 |
+
application/x-tcl tcl tk;
|
| 49 |
+
application/x-x509-ca-cert der pem crt;
|
| 50 |
+
application/x-xpinstall xpi;
|
| 51 |
+
application/xhtml+xml xhtml;
|
| 52 |
+
application/zip zip;
|
| 53 |
+
application/octet-stream bin exe dll;
|
| 54 |
+
application/octet-stream deb;
|
| 55 |
+
application/octet-stream dmg;
|
| 56 |
+
application/octet-stream iso img;
|
| 57 |
+
application/octet-stream msi msp msm;
|
| 58 |
+
audio/midi mid midi kar;
|
| 59 |
+
audio/mpeg mp3;
|
| 60 |
+
audio/ogg ogg;
|
| 61 |
+
audio/x-m4a m4a;
|
| 62 |
+
audio/x-realaudio ra;
|
| 63 |
+
video/3gpp 3gpp 3gp;
|
| 64 |
+
video/mp2t ts;
|
| 65 |
+
video/mp4 mp4;
|
| 66 |
+
video/mpeg mpeg mpg;
|
| 67 |
+
video/quicktime mov;
|
| 68 |
+
video/webm webm;
|
| 69 |
+
video/x-flv flv;
|
| 70 |
+
video/x-m4v m4v;
|
| 71 |
+
video/x-ms-wmv wmv;
|
| 72 |
+
video/x-msvideo avi;
|
| 73 |
+
}
|
nginx.conf
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
worker_processes 1;
|
| 2 |
+
pid /tmp/nginx/nginx.pid;
|
| 3 |
+
|
| 4 |
+
events {
|
| 5 |
+
worker_connections 1024;
|
| 6 |
+
}
|
| 7 |
+
|
| 8 |
+
rtmp {
|
| 9 |
+
server {
|
| 10 |
+
listen 1935;
|
| 11 |
+
chunk_size 4096;
|
| 12 |
+
|
| 13 |
+
application live {
|
| 14 |
+
live on;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
application hls {
|
| 18 |
+
live on;
|
| 19 |
+
hls on;
|
| 20 |
+
hls_type live;
|
| 21 |
+
#hls_nested on;
|
| 22 |
+
hls_path /tmp/nginx/html/media/hls;
|
| 23 |
+
hls_fragment 3;
|
| 24 |
+
hls_playlist_length 9;
|
| 25 |
+
hls_variant _subsd BANDWIDTH=400000;
|
| 26 |
+
hls_variant _sd BANDWIDTH=1000000;
|
| 27 |
+
hls_variant _hd BANDWIDTH=5000000;
|
| 28 |
+
allow publish all;
|
| 29 |
+
allow play all;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
application rhls {
|
| 33 |
+
live on;
|
| 34 |
+
hls on;
|
| 35 |
+
#hls_nested on;
|
| 36 |
+
hls_type live;
|
| 37 |
+
hls_path /tmp/nginx/html/media/rhls;
|
| 38 |
+
hls_fragment 3;
|
| 39 |
+
hls_playlist_length 9;
|
| 40 |
+
record all;
|
| 41 |
+
record_path /tmp/nginx/html/media/recordings;
|
| 42 |
+
record_unique on;
|
| 43 |
+
record_append off;
|
| 44 |
+
hls_variant _subsd BANDWIDTH=400000;
|
| 45 |
+
hls_variant _sd BANDWIDTH=1000000;
|
| 46 |
+
hls_variant _hd BANDWIDTH=5000000;
|
| 47 |
+
|
| 48 |
+
allow publish all;
|
| 49 |
+
allow play all;
|
| 50 |
+
}
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
http {
|
| 55 |
+
include /tmp/nginx/mime.types;
|
| 56 |
+
default_type application/octet-stream;
|
| 57 |
+
sendfile on;
|
| 58 |
+
keepalive_timeout 65;
|
| 59 |
+
|
| 60 |
+
# Writable logs
|
| 61 |
+
error_log /tmp/nginx/error.log info;
|
| 62 |
+
access_log /tmp/nginx/access.log;
|
| 63 |
+
|
| 64 |
+
# Temp path must be inside http block
|
| 65 |
+
#client_body_temp_path /tmp/nginx/proxy_temp;
|
| 66 |
+
|
| 67 |
+
server {
|
| 68 |
+
listen 7860;
|
| 69 |
+
# Serve HLS from /tmp/media/hls
|
| 70 |
+
|
| 71 |
+
location / {
|
| 72 |
+
root /tmp/nginx/html;
|
| 73 |
+
index index.html;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
location /hls/ {
|
| 77 |
+
root /tmp/nginx/html/media/hls/;
|
| 78 |
+
types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
|
| 79 |
+
add_header Cache-Control no-cache;
|
| 80 |
+
add_header Access-Control-Allow-Origin *;
|
| 81 |
+
autoindex on;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
location /rhls/ {
|
| 85 |
+
root /tmp/nginx/html/media/rhls/;
|
| 86 |
+
types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; }
|
| 87 |
+
add_header Cache-Control no-cache;
|
| 88 |
+
add_header Access-Control-Allow-Origin *;
|
| 89 |
+
autoindex on;
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
location /recordings/ {
|
| 93 |
+
root /tmp/nginx/html/media/recordings/;
|
| 94 |
+
add_header Cache-Control no-cache;
|
| 95 |
+
autoindex on;
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
location /stat {
|
| 102 |
+
rtmp_stat all;
|
| 103 |
+
rtmp_stat_stylesheet stat.xsl;
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
}
|
stat.xsl
ADDED
|
File without changes
|
www/index.html
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>RTMP Live Dashboard</title>
|
| 7 |
+
<style>
|
| 8 |
+
body { font-family: sans-serif; margin: 0; padding: 0; background: #111; color: #fff; }
|
| 9 |
+
h1 { text-align: center; padding: 10px; }
|
| 10 |
+
#grid { display: grid; gap: 10px; padding: 10px; }
|
| 11 |
+
video { width: 100%; height: auto; background: #000; }
|
| 12 |
+
button { margin-top: 5px; padding: 5px; }
|
| 13 |
+
</style>
|
| 14 |
+
</head>
|
| 15 |
+
<body>
|
| 16 |
+
<h1>Live Streams</h1>
|
| 17 |
+
<div id="grid"></div>
|
| 18 |
+
<script src="scripts.js"></script>
|
| 19 |
+
</body>
|
| 20 |
+
</html>
|
www/script.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const grid = document.getElementById("grid");
|
| 2 |
+
|
| 3 |
+
async function fetchStreams() {
|
| 4 |
+
try {
|
| 5 |
+
const res = await fetch("/stat"); // You may need a JSON stat endpoint
|
| 6 |
+
const text = await res.text();
|
| 7 |
+
// Simple parsing to get stream keys from the rtmp_stat XML
|
| 8 |
+
const parser = new DOMParser();
|
| 9 |
+
const xml = parser.parseFromString(text, "text/xml");
|
| 10 |
+
const streams = Array.from(xml.getElementsByTagName("stream")).map(s => s.getAttribute("name"));
|
| 11 |
+
renderStreams(streams);
|
| 12 |
+
} catch (e) {
|
| 13 |
+
console.error(e);
|
| 14 |
+
}
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
function renderStreams(streams) {
|
| 18 |
+
grid.innerHTML = "";
|
| 19 |
+
const columns = Math.ceil(Math.sqrt(streams.length));
|
| 20 |
+
grid.style.gridTemplateColumns = `repeat(${columns}, 1fr)`;
|
| 21 |
+
streams.forEach(stream => {
|
| 22 |
+
const container = document.createElement("div");
|
| 23 |
+
const video = document.createElement("video");
|
| 24 |
+
video.src = `/live/${stream}.flv`; // Use HLS/FLV player if needed
|
| 25 |
+
video.controls = true;
|
| 26 |
+
video.autoplay = true;
|
| 27 |
+
video.muted = false;
|
| 28 |
+
|
| 29 |
+
const btn = document.createElement("button");
|
| 30 |
+
btn.textContent = "Play/Pause";
|
| 31 |
+
btn.onclick = () => video.paused ? video.play() : video.pause();
|
| 32 |
+
|
| 33 |
+
container.appendChild(video);
|
| 34 |
+
container.appendChild(btn);
|
| 35 |
+
grid.appendChild(container);
|
| 36 |
+
});
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
// Refresh every 5 seconds
|
| 40 |
+
setInterval(fetchStreams, 5000);
|
| 41 |
+
fetchStreams();
|