diff --git a/src/modules/octopi/config b/src/modules/octopi/config index fcca2e09..e0d0e7d5 100755 --- a/src/modules/octopi/config +++ b/src/modules/octopi/config @@ -21,6 +21,9 @@ [ -n "$OCTOPI_MJPGSTREAMER_REPO_DEPTH" ] || OCTOPI_MJPGSTREAMER_REPO_DEPTH=1 [ -n "$OCTOPI_INCLUDE_MJPGSTREAMER" ] || OCTOPI_INCLUDE_MJPGSTREAMER=yes +# FFMPEG HLS +[ -n "$OCTOPI_INCLUDE_FFMPEG_HLS" ] || OCTOPI_INCLUDE_FFMPEG_HLS=yes + # HAProxy [ -n "$OCTOPI_INCLUDE_HAPROXY" ] || OCTOPI_INCLUDE_HAPROXY=yes diff --git a/src/modules/octopi/filesystem/boot/octopi.txt b/src/modules/octopi/filesystem/boot/octopi.txt index 12557d9a..b81a1f3f 100644 --- a/src/modules/octopi/filesystem/boot/octopi.txt +++ b/src/modules/octopi/filesystem/boot/octopi.txt @@ -72,3 +72,11 @@ # #camera_http_webroot="./www-octopi" #camera_http_options="-n" + +### EXPERIMENTAL +# Support for different streamer types. +# +# Available options: +# mjpeg [default] - stable MJPG-streamer +# hls - experimental FFMPEG HLS streamer +#camera_streamer=mjpeg diff --git a/src/modules/octopi/filesystem/home/root/bin/streamer_select b/src/modules/octopi/filesystem/home/root/bin/streamer_select new file mode 100755 index 00000000..9d965140 --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/streamer_select @@ -0,0 +1,32 @@ +#!/bin/bash + +# Exit on any error. +set -e + +CONFIG_FILE=/boot/octopi.txt +MJPEG_TYPE=mjpeg +HLS_TYPE=hls +MJPEG_SERVICE=webcamd.service +HLS_SERVICE=ffmpeg_hls.service +DEFAULT_TYPE=${MJPEG_TYPE} +FLAG_DIRECTORY=/etc/octopi_streamer + +source ${CONFIG_FILE} + +if [ -z ${camera_streamer+x} ]; then + echo "No streamer type is set. Defaulting to '${DEFAULT_TYPE}'." + camera_streamer=${DEFAULT_TYPE} +fi + +rm -rf ${FLAG_DIRECTORY} +mkdir -p ${FLAG_DIRECTORY} + +echo "Setting streamer type '${camera_streamer}'." +if [ "${camera_streamer}" = "${MJPEG_TYPE}" ]; then + touch ${FLAG_DIRECTORY}/${MJPEG_TYPE} +elif [ "${camera_streamer}" = "${HLS_TYPE}" ]; then + touch ${FLAG_DIRECTORY}/${HLS_TYPE} +else + echo "Streamer type '${camera_streamer}' is not supported." + exit 1 +fi \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default b/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default new file mode 100644 index 00000000..251348f2 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default @@ -0,0 +1,11 @@ +server { + listen 8051 default_server; + + root /tmp/webcam; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } +} \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service b/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service new file mode 100644 index 00000000..520b35be --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service @@ -0,0 +1,33 @@ +[Unit] +Description=FFMPEG HLS webcam streaming service +ConditionPathExists=/etc/octopi_streamer/hls + +[Service] +User=webcam +Restart=always +RestartSec=5 +Nice=10 +ExecStartPre=/bin/rm -rf /tmp/webcam +ExecStartPre=/bin/mkdir -p /tmp/webcam/hls +ExecStartPre=/bin/mkdir -p /tmp/webcam/jpeg + +ExecStart=/usr/bin/ffmpeg \ + \ + -framerate 30 -video_size 800x600 \ + -i /dev/video0 \ + \ + -c:v mjpeg -q:v 0 \ + -f image2 -update 1 \ + /tmp/webcam/jpeg/frame.jpg \ + \ + -c:v h264_omx -profile:v high \ + -b:v 2048k -flags +cgop \ + -g 30 -keyint_min 30 \ + \ + -f hls -hls_time 1 -hls_flags delete_segments \ + -hls_allow_cache 1 -hls_segment_type fmp4 \ + -hls_list_size 32 -hls_delete_threshold 64 \ + /tmp/webcam/hls/stream.m3u8 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service b/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service new file mode 100644 index 00000000..402fd512 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service @@ -0,0 +1,10 @@ +[Unit] +Description=OctoPi streamer selector +Before=webcamd.service ffmpeg_hls.service nginx.service + +[Service] +Type=oneshot +ExecStart=/root/bin/streamer_select + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service b/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service index 0586c8ac..53363805 100644 --- a/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service @@ -1,5 +1,6 @@ [Unit] Description=the OctoPi webcam daemon with the user specified config +ConditionPathExists=/etc/octopi_streamer/mjpeg [Service] WorkingDirectory=/root/bin diff --git a/src/modules/octopi/filesystem/root/lib/systemd/system/nginx.service b/src/modules/octopi/filesystem/root/lib/systemd/system/nginx.service new file mode 100644 index 00000000..8ef64228 --- /dev/null +++ b/src/modules/octopi/filesystem/root/lib/systemd/system/nginx.service @@ -0,0 +1,20 @@ +# NGINX service definition based on Debian buster version. +[Unit] +Description=NGINX server for serving HLS and JPEG frames +Documentation=man:nginx(8) +After=network.target nss-lookup.target +ConditionPathExists=/etc/octopi_streamer/hls + +[Service] +Type=forking +PIDFile=/run/nginx.pid +ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' +ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' +ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload +ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid +TimeoutStopSec=5 +KillMode=mixed +Nice=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/modules/octopi/start_chroot_script b/src/modules/octopi/start_chroot_script index ea6ca79d..de87db3f 100755 --- a/src/modules/octopi/start_chroot_script +++ b/src/modules/octopi/start_chroot_script @@ -11,6 +11,8 @@ export LC_ALL=C source /common.sh +WEBCAM_USER=webcam + ### Script #### unpack /filesystem/home/pi /home/pi pi @@ -29,7 +31,6 @@ apt-get -y --force-yes install python2.7 python-virtualenv python-dev git screen echo " - Reinstall iputils-ping" apt-get install --reinstall iputils-ping - pushd /home/pi # build virtualenv @@ -99,6 +100,14 @@ EOT popd popd fi + + # FFMPEG HLS + if [ "$OCTOPI_INCLUDE_FFMPEG_HLS" == "yes" ] + then + apt-get install -y --force-yes --no-install-recommends ffmpeg nginx + useradd ${WEBCAM_USER} + usermod -aG video ${WEBCAM_USER} + fi #CuraEngine if [ "$OCTOPI_INCLUDE_CURAENGINE" == "yes" ] @@ -234,6 +243,10 @@ then sudo -u pi sed -i -e "s@cura_engine: /usr/local/bin/cura_engine@cura_engine:@g" /home/pi/.octoprint/config.yaml fi +### Streamer select service. + +systemctl_if_exists enable streamer_select.service + ### mjpg_streamer if [ "$OCTOPI_INCLUDE_MJPGSTREAMER" == "yes" ] @@ -241,12 +254,15 @@ then systemctl_if_exists enable webcamd.service else rm /etc/logrotate.d/webcamd - rm /etc/init.d/webcamd + rm /etc/systemd/system/webcamd.service rm /etc/default/webcamd rm /root/bin/webcamd fi +### HLS streamer + +systemctl_if_exists enable ffmpeg_hls.service + #cleanup apt-get clean apt-get autoremove -y -