stream optimizations

This commit is contained in:
Maik Jurischka
2025-12-12 14:37:57 +01:00
parent 43a1abdd31
commit 9c9f822f35
10 changed files with 168 additions and 24 deletions

24
scripts/mjpeg_http_proxy.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/bash
# HTTP proxy wrapper for MJPEG stream from tcpserversink
# This adds proper HTTP headers for browser compatibility
TCP_PORT="${1:-8081}"
HTTP_PORT="${2:-8080}"
echo "Starting MJPEG HTTP proxy..."
echo "Listening for TCP stream on port $TCP_PORT"
echo "Serving HTTP on port $HTTP_PORT"
echo ""
echo "Configure vizionStreamer to use tcpserversink on port $TCP_PORT"
echo "Then access the stream at: http://localhost:$HTTP_PORT"
echo ""
# Start socat to wrap TCP stream with HTTP headers
socat -v TCP-LISTEN:$HTTP_PORT,reuseaddr,fork \
SYSTEM:"echo 'HTTP/1.1 200 OK'; \
echo 'Content-Type: multipart/x-mixed-replace; boundary=--videoboundary'; \
echo 'Cache-Control: no-cache'; \
echo 'Pragma: no-cache'; \
echo 'Connection: close'; \
echo ''; \
socat - TCP:localhost:$TCP_PORT"

79
scripts/mjpeg_http_server.py Executable file
View File

@@ -0,0 +1,79 @@
#!/usr/bin/env python3
"""
Simple HTTP server that proxies MJPEG stream from tcpserversink
Adds proper HTTP headers for browser compatibility
"""
import socket
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
class MJPEGProxyHandler(BaseHTTPRequestHandler):
tcp_host = 'localhost'
tcp_port = 9000
def do_GET(self):
"""Handle GET requests and proxy the MJPEG stream"""
try:
# Connect to the GStreamer tcpserversink
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((self.tcp_host, self.tcp_port))
# Send HTTP headers
self.send_response(200)
self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=--videoboundary')
self.send_header('Cache-Control', 'no-cache')
self.send_header('Pragma', 'no-cache')
self.send_header('Connection', 'close')
self.end_headers()
# Stream data from TCP socket to HTTP client
while True:
data = sock.recv(4096)
if not data:
break
self.wfile.write(data)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
finally:
try:
sock.close()
except:
pass
def log_message(self, format, *args):
"""Custom logging"""
print(f"[{self.client_address[0]}] {format % args}")
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""Handle requests in separate threads"""
pass
if __name__ == '__main__':
tcp_port = int(sys.argv[1]) if len(sys.argv) > 1 else 8081
http_port = int(sys.argv[2]) if len(sys.argv) > 2 else 8080
MJPEGProxyHandler.tcp_port = tcp_port
server = ThreadedHTTPServer(('0.0.0.0', http_port), MJPEGProxyHandler)
print(f"MJPEG HTTP Proxy Server")
print(f"========================")
print(f"Proxying TCP stream from localhost:{tcp_port}")
print(f"HTTP server listening on port {http_port}")
print(f"")
print(f"Configure vizionStreamer with:")
print(f' ./scripts/set_pipeline_mjpeg.sh {tcp_port}')
print(f"")
print(f"Access stream at: http://localhost:{http_port}")
print(f"")
try:
server.serve_forever()
except KeyboardInterrupt:
print("\nShutting down...")
server.shutdown()

View File

@@ -4,8 +4,18 @@
SOCKET="/tmp/vizion_control.sock"
PORT="${1:-8080}"
# Check if gst-plugins-good with souphttpsink is available
if gst-inspect-1.0 souphttpsink &>/dev/null; then
echo "Using souphttpsink for HTTP server..."
PIPELINE="videoconvert ! jpegenc quality=85 ! multipartmux boundary=\"--videoboundary\" ! souphttpsink port=$PORT"
else
echo "WARNING: souphttpsink not found. Using tcpserversink (may not work in browsers)."
echo "Install gst-plugins-good: sudo apt install gstreamer1.0-plugins-good"
PIPELINE="videoconvert ! jpegenc quality=85 ! multipartmux ! tcpserversink host=0.0.0.0 port=$PORT"
fi
echo "Setting MJPEG HTTP streaming pipeline on port $PORT..."
echo "{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"videoconvert ! jpegenc ! multipartmux ! tcpserversink host=0.0.0.0 port=$PORT\"}}" | socat - UNIX-CONNECT:$SOCKET
echo "{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"$PIPELINE\"}}" | socat - UNIX-CONNECT:$SOCKET
echo ""
echo "Pipeline set. Start streaming with start_stream.sh"

View File

@@ -0,0 +1,32 @@
#!/bin/bash
# Optimized pipeline for cameras that already output MJPEG format
# Passes through MJPEG data without re-encoding
SOCKET="/tmp/vizion_control.sock"
PORT="${1:-8080}"
# Check if gst-plugins-good with souphttpsink is available
if gst-inspect-1.0 souphttpsink &>/dev/null; then
echo "Using souphttpsink for HTTP server (no re-encoding)..."
PIPELINE="multipartmux boundary=\"--videoboundary\" ! souphttpsink port=$PORT"
else
echo "WARNING: souphttpsink not found. Using tcpserversink (requires HTTP proxy)."
echo "Install gst-plugins-good: sudo apt install gstreamer1.0-plugins-good"
echo "Or use: ./scripts/mjpeg_http_server.py $PORT 8080"
PIPELINE="multipartmux ! tcpserversink host=0.0.0.0 port=$PORT"
fi
echo "Setting optimized MJPEG passthrough pipeline on port $PORT..."
echo "NOTE: This pipeline is optimized for cameras with native MJPEG output."
echo ""
echo "{\"command\":\"set_pipeline\",\"params\":{\"pipeline\":\"$PIPELINE\"}}" | socat - UNIX-CONNECT:$SOCKET
echo ""
echo "Pipeline set. Start streaming with start_stream.sh"
if gst-inspect-1.0 souphttpsink &>/dev/null; then
echo "View stream in browser: http://localhost:$PORT"
else
echo "Start HTTP proxy first: ./scripts/mjpeg_http_server.py $PORT 8080"
echo "Then view stream: http://localhost:8080"
fi