diff --git a/docker/Dockerfile.jsmpeg b/docker/Dockerfile.jsmpeg new file mode 100644 index 000000000..c97e2d7ad --- /dev/null +++ b/docker/Dockerfile.jsmpeg @@ -0,0 +1,11 @@ +ARG NODE_VERSION=14.16 + +FROM node:${NODE_VERSION} + +WORKDIR /opt/build + +COPY jsmpeg/. . + +RUN npm install --no-progress && \ + npm run build && \ + npm prune --production --ignore-scripts --prefer-offline diff --git a/jsmpeg/.gitignore b/jsmpeg/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/jsmpeg/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/jsmpeg/package-lock.json b/jsmpeg/package-lock.json new file mode 100644 index 000000000..30201bcf0 --- /dev/null +++ b/jsmpeg/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "jsmpeg", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ws": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", + "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==" + } + } +} diff --git a/jsmpeg/package.json b/jsmpeg/package.json new file mode 100644 index 000000000..4e96ee62e --- /dev/null +++ b/jsmpeg/package.json @@ -0,0 +1,14 @@ +{ + "name": "jsmpeg", + "version": "1.0.0", + "description": "", + "main": "relay.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT", + "dependencies": { + "ws": "^7.4.3" + } +} diff --git a/jsmpeg/relay.js b/jsmpeg/relay.js new file mode 100644 index 000000000..8d617c2e7 --- /dev/null +++ b/jsmpeg/relay.js @@ -0,0 +1,54 @@ +// Use the websocket-relay to serve a raw MPEG-TS over WebSockets. You can use +// ffmpeg to feed the relay. ffmpeg -> websocket-relay -> browser +// Example: +// node relay 8081 8082 +// ffmpeg -i -f mpegts http://localhost:8081/streamName + +var http = require('http'), + WebSocket = require('ws'); + +var STREAM_PORT = process.argv[2] || 8081, + WEBSOCKET_PORT = process.argv[3] || 8082; + +// Websocket Server +var socketServer = new WebSocket.Server({ port: WEBSOCKET_PORT, perMessageDeflate: false }); + +socketServer.on('connection', function (socket, request) { + var streamName = request.url.substr(1).split('/')[0]; + + socket.stream = streamName; + + console.log( + 'New WebSocket connection for: ', + streamName + ); +}); + +socketServer.broadcast = function(data, streamName) { + socketServer.clients.forEach(function each(client) { + if (client.readyState === WebSocket.OPEN && client.stream === streamName) { + client.send(data); + } + }); +}; + +// HTTP Server to accept incoming MPEG-TS Stream from ffmpeg +var streamServer = http.createServer( function(request, response) { + var streamName = request.url.substr(1).split('/')[0]; + + response.connection.setTimeout(0); + console.log( + 'Stream Connected: ', + streamName + ); + request.on('data', function(data){ + socketServer.broadcast(data, streamName); + }); +}) + +// Keep the socket open for streaming +streamServer.headersTimeout = 0; +streamServer.listen(STREAM_PORT); + +console.log('Listening for incoming MPEG-TS Stream on http://127.0.0.1:'+STREAM_PORT+'/'); +console.log('Awaiting WebSocket connections on ws://127.0.0.1:'+WEBSOCKET_PORT+'/'); \ No newline at end of file diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 48f69e7b4..689d081a0 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -32,6 +32,11 @@ http { keepalive 1024; } + upstream jsmpeg { + server localhost:8082; + keepalive 1024; + } + server { listen 5000; @@ -140,6 +145,14 @@ http { proxy_set_header Host $host; } + location /live/ { + proxy_pass http://jsmpeg/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + } + location /api/ { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';