diff --git a/docker/rootfs/etc/services.d/jsmpeg/finish b/docker/rootfs/etc/services.d/jsmpeg/finish
deleted file mode 100644
index 24482e77f..000000000
--- a/docker/rootfs/etc/services.d/jsmpeg/finish
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/execlineb -S1
-if { s6-test ${1} -ne 0 }
-if { s6-test ${1} -ne 256 }
-
-s6-svscanctl -t /var/run/s6/services
\ No newline at end of file
diff --git a/docker/rootfs/etc/services.d/jsmpeg/run b/docker/rootfs/etc/services.d/jsmpeg/run
deleted file mode 100644
index b47110b81..000000000
--- a/docker/rootfs/etc/services.d/jsmpeg/run
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/execlineb -P
-/usr/local/bin/node /opt/frigate/jsmpeg/relay.js 8081 8082
\ No newline at end of file
diff --git a/frigate/birdseye.py b/frigate/birdseye.py
index e9d95df29..364cf11ae 100644
--- a/frigate/birdseye.py
+++ b/frigate/birdseye.py
@@ -1,8 +1,23 @@
-import multiprocessing as mp
-import numpy as np
-import subprocess as sp
import logging
+import multiprocessing as mp
+import subprocess as sp
import threading
+
+import gevent
+import numpy as np
+from flask import (
+ Blueprint,
+ Flask,
+ Response,
+ current_app,
+ jsonify,
+ make_response,
+ request,
+)
+from flask_sockets import Sockets
+from gevent import pywsgi
+from geventwebsocket.handler import WebSocketHandler
+
from frigate.util import SharedMemoryFrameManager
logger = logging.getLogger(__name__)
@@ -56,12 +71,12 @@ class BirdsEyeFrameOutputter(threading.Thread):
)
def start_ffmpeg(self):
- ffmpeg_cmd = "ffmpeg -f rawvideo -pix_fmt yuv420p -video_size 1920x1080 -i pipe: -f mpegts -codec:v mpeg1video -b:v 1000k -bf 0 http://localhost:8081/birdseye".split(
+ ffmpeg_cmd = "ffmpeg -f rawvideo -pix_fmt yuv420p -video_size 1920x1080 -i pipe: -f mpegts -codec:v mpeg1video -b:v 1000k -bf 0 pipe:".split(
" "
)
self.process = sp.Popen(
ffmpeg_cmd,
- stdout=sp.DEVNULL,
+ stdout=sp.PIPE,
# TODO: logging
stderr=sp.DEVNULL,
stdin=sp.PIPE,
@@ -81,4 +96,50 @@ class BirdsEyeFrameOutputter(threading.Thread):
# separate process for passing jsmpeg packets over websockets
# signals to the frame manager when a client is listening
-# class JSMpegSocketServer:
+def run_jsmpeg_server():
+ app = Flask(__name__)
+ sockets = Sockets(app)
+
+ http = Blueprint("http", __name__)
+ ws = Blueprint("ws", __name__)
+
+ # TODO: add something for notification of subscribers
+ # self.app.frigate_config = frigate_config
+
+ app.register_blueprint(http)
+ sockets.register_blueprint(ws)
+
+ clients = list()
+
+ @http.route("/birdseye")
+ def receive_mpegts():
+ chunk_size = 4096
+ while True:
+ chunk = request.stream.read(chunk_size)
+ if len(chunk) == 0:
+ break
+ for client in clients:
+ try:
+ client.send(chunk)
+ except:
+ logger.debug(
+ "Removing websocket client due to a closed connection."
+ )
+ clients.remove(client)
+
+ @ws.route("/birdseye")
+ def echo_socket(socket):
+ # TODO: get reference to
+ # current_app.mqtt_backend.register(socket)
+ clients.append(socket)
+
+ while not socket.closed:
+ # Sleep to prevent *constant* context-switches.
+ gevent.sleep(0.1)
+
+ server = pywsgi.WSGIServer(("127.0.0.1", 5050), app, handler_class=WebSocketHandler)
+
+ try:
+ server.serve_forever()
+ except KeyboardInterrupt:
+ pass
diff --git a/web/public/jsmpeg.html b/web/public/jsmpeg.html
index 39c7c6dae..057db21af 100644
--- a/web/public/jsmpeg.html
+++ b/web/public/jsmpeg.html
@@ -15,8 +15,8 @@