From f6fe53eda322cd937cd9857cf24416f840c56ab5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 17:31:53 +0000 Subject: [PATCH 1/5] Initial plan From d0a95031f5366d755008d09e07fe30e98cc26060 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 17:34:56 +0000 Subject: [PATCH 2/5] Add x11stream script, systemd service, and documentation Co-authored-by: maple-underscore <102273486+maple-underscore@users.noreply.github.com> --- README.md | 109 +++++++++++++++++++++++++++++++++++++++++++++- x11stream.service | 21 +++++++++ x11stream.sh | 53 ++++++++++++++++++++++ 3 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 x11stream.service create mode 100755 x11stream.sh diff --git a/README.md b/README.md index 19e7977..a0c8247 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,109 @@ # x11stream -Shell script on Ubuntu to auto-stream on boot using x11grab and ffmpeg + +Shell script on Ubuntu to auto-stream X11 display on boot using x11grab and ffmpeg. + +## Features + +- Captures X11 display using ffmpeg with low-latency settings +- Hosts an HTTP server for direct browser/VLC access +- Auto-starts on boot via systemd service +- Configurable resolution, framerate, and bitrate + +## Requirements + +- Ubuntu (or other Linux with X11) +- ffmpeg with x11grab support +- systemd (for auto-start on boot) + +Install ffmpeg: +```bash +sudo apt update +sudo apt install ffmpeg +``` + +## Installation + +1. Clone this repository: +```bash +git clone https://github.com/maple-underscore/x11stream.git +cd x11stream +``` + +2. Install the script: +```bash +sudo cp x11stream.sh /usr/local/bin/ +sudo chmod +x /usr/local/bin/x11stream.sh +``` + +3. Install and enable the systemd service: +```bash +sudo cp x11stream.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable x11stream.service +sudo systemctl start x11stream.service +``` + +## Usage + +### Manual Start +```bash +./x11stream.sh +``` + +### Access the Stream + +Once the script is running, access the stream via: + +- **Browser**: `http://:8080/stream` +- **VLC**: Open Network Stream → `http://:8080/stream` + +### Service Management +```bash +# Start the service +sudo systemctl start x11stream.service + +# Stop the service +sudo systemctl stop x11stream.service + +# Check status +sudo systemctl status x11stream.service + +# View logs +sudo journalctl -u x11stream.service -f +``` + +## Configuration + +The following environment variables can be set to customize the stream: + +| Variable | Default | Description | +|-------------|--------------|--------------------------------| +| DISPLAY | :0.0 | X11 display to capture | +| RESOLUTION | 1920x1080 | Capture resolution | +| FRAMERATE | 30 | Frames per second | +| BITRATE | 6M | Video bitrate | +| HTTP_PORT | 8080 | HTTP server port | + +To modify these settings permanently, edit the service file: +```bash +sudo systemctl edit x11stream.service +``` + +Or edit `/etc/systemd/system/x11stream.service` directly. + +## Troubleshooting + +### "Display not found" error +Ensure X11 is running and the `DISPLAY` variable is set correctly. On systems with multiple displays, try `:1.0` or `:0.1`. + +### "Permission denied" error +The user running the script needs access to the X11 display. Run with appropriate permissions or add the user to the video group. + +### Stream not accessible +- Check if ffmpeg is running: `ps aux | grep ffmpeg` +- Ensure the port is not blocked by firewall: `sudo ufw allow 8080/tcp` +- Verify the IP address and port in the startup output + +## License + +MIT License diff --git a/x11stream.service b/x11stream.service new file mode 100644 index 0000000..65aa732 --- /dev/null +++ b/x11stream.service @@ -0,0 +1,21 @@ +[Unit] +Description=X11 Display Stream Server +After=network.target display-manager.service +Wants=graphical.target + +[Service] +Type=simple +Environment="DISPLAY=:0.0" +Environment="RESOLUTION=1920x1080" +Environment="FRAMERATE=30" +Environment="BITRATE=6M" +Environment="HTTP_PORT=8080" +ExecStart=/usr/local/bin/x11stream.sh +Restart=on-failure +RestartSec=5 +# Note: Running as root for X11 access. For better security, create a dedicated +# user in the 'video' group with X11 display access and update this line. +User=root + +[Install] +WantedBy=multi-user.target diff --git a/x11stream.sh b/x11stream.sh new file mode 100755 index 0000000..db7f10a --- /dev/null +++ b/x11stream.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# +# x11stream.sh - Stream X11 display via HTTP using ffmpeg +# +# This script captures the X11 display and makes it available via HTTP +# Access the stream at: http://{ip}:8080/stream +# + +set -e + +# Configuration +DISPLAY_NUM="${DISPLAY:-:0.0}" +RESOLUTION="${RESOLUTION:-1920x1080}" +FRAMERATE="${FRAMERATE:-30}" +BITRATE="${BITRATE:-6M}" +HTTP_PORT="${HTTP_PORT:-8080}" + +# Detect the machine's IP address +# Uses 'ip route get 1' to find the default route interface IP (1 is a dummy destination IP) +get_ip() { + ip route get 1 2>/dev/null | awk '{print $7; exit}' || hostname -I | awk '{print $1}' +} + +IP_ADDRESS=$(get_ip) + +echo "============================================" +echo "X11 Stream Server" +echo "============================================" +echo "Display: $DISPLAY_NUM" +echo "Resolution: $RESOLUTION" +echo "Framerate: $FRAMERATE fps" +echo "Bitrate: $BITRATE" +echo "HTTP Port: $HTTP_PORT" +echo "" +echo "Access your stream at:" +echo " http://${IP_ADDRESS}:${HTTP_PORT}/stream" +echo " http://localhost:${HTTP_PORT}/stream" +echo "============================================" + +# Run ffmpeg with x11grab and output to HTTP via mpegts +# The -listen 1 flag makes ffmpeg act as an HTTP server +# Low-latency settings: +# -probesize 32: Minimal probe size (bytes) for faster stream start +# -analyzeduration 0: Skip analysis delay for immediate processing +exec ffmpeg -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 0 \ + -f x11grab -video_size "$RESOLUTION" -framerate "$FRAMERATE" -i "$DISPLAY_NUM" \ + -c:v libx264 -preset ultrafast -tune zerolatency \ + -x264-params "bframes=0:rc-lookahead=0:sync-lookahead=0:sliced-threads=1" \ + -g 15 -keyint_min 15 -sc_threshold 0 \ + -b:v "$BITRATE" -maxrate "$BITRATE" -bufsize 256k \ + -pix_fmt yuv420p \ + -f mpegts \ + -listen 1 "http://0.0.0.0:${HTTP_PORT}/stream" From 778fa31e6bd27decf2770dbbc39a8c3acbf7fec2 Mon Sep 17 00:00:00 2001 From: maple_ <102273486+maple-underscore@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:08:31 -0800 Subject: [PATCH 3/5] Change default framerate from 30 to 60 --- x11stream.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x11stream.sh b/x11stream.sh index db7f10a..9825b8b 100755 --- a/x11stream.sh +++ b/x11stream.sh @@ -11,7 +11,7 @@ set -e # Configuration DISPLAY_NUM="${DISPLAY:-:0.0}" RESOLUTION="${RESOLUTION:-1920x1080}" -FRAMERATE="${FRAMERATE:-30}" +FRAMERATE="${FRAMERATE:-60}" BITRATE="${BITRATE:-6M}" HTTP_PORT="${HTTP_PORT:-8080}" From fcc85d8c3648d4bfa02c21570414f9726a39c23a Mon Sep 17 00:00:00 2001 From: maple_ <102273486+maple-underscore@users.noreply.github.com> Date: Tue, 20 Jan 2026 10:08:57 -0800 Subject: [PATCH 4/5] Change framerate from 30 to 60 in x11stream.service Updated the framerate setting from 30 to 60. --- x11stream.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x11stream.service b/x11stream.service index 65aa732..4eb430b 100644 --- a/x11stream.service +++ b/x11stream.service @@ -7,7 +7,7 @@ Wants=graphical.target Type=simple Environment="DISPLAY=:0.0" Environment="RESOLUTION=1920x1080" -Environment="FRAMERATE=30" +Environment="FRAMERATE=60" Environment="BITRATE=6M" Environment="HTTP_PORT=8080" ExecStart=/usr/local/bin/x11stream.sh From 80d2deedeb33216231da8946476d6a37a4cc3f73 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 20 Jan 2026 18:19:57 +0000 Subject: [PATCH 5/5] Add interactive mode, audio streaming options, and fix review comments Co-authored-by: maple-underscore <102273486+maple-underscore@users.noreply.github.com> --- README.md | 82 +++++++++-- x11stream.service | 2 +- x11stream.sh | 346 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 403 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a0c8247..2bd2e9f 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,16 @@ Shell script on Ubuntu to auto-stream X11 display on boot using x11grab and ffmp - Captures X11 display using ffmpeg with low-latency settings - Hosts an HTTP server for direct browser/VLC access - Auto-starts on boot via systemd service -- Configurable resolution, framerate, and bitrate +- **Interactive mode** for easy configuration +- **Audio streaming support** with multiple quality presets +- Configurable resolution, framerate, bitrate, and audio settings +- Bandwidth estimation for all configurations ## Requirements - Ubuntu (or other Linux with X11) - ffmpeg with x11grab support +- PulseAudio or ALSA (for audio streaming) - systemd (for auto-start on boot) Install ffmpeg: @@ -45,7 +49,15 @@ sudo systemctl start x11stream.service ## Usage -### Manual Start +### Interactive Mode +Run in interactive mode to configure all settings through a menu: +```bash +./x11stream.sh --interactive +# or +./x11stream.sh -i +``` + +### Non-Interactive Mode ```bash ./x11stream.sh ``` @@ -74,15 +86,62 @@ sudo journalctl -u x11stream.service -f ## Configuration +### Environment Variables + The following environment variables can be set to customize the stream: -| Variable | Default | Description | -|-------------|--------------|--------------------------------| -| DISPLAY | :0.0 | X11 display to capture | -| RESOLUTION | 1920x1080 | Capture resolution | -| FRAMERATE | 30 | Frames per second | -| BITRATE | 6M | Video bitrate | -| HTTP_PORT | 8080 | HTTP server port | +| Variable | Default | Description | +|-------------------|--------------|--------------------------------| +| DISPLAY | :0.0 | X11 display to capture | +| RESOLUTION | 1920x1080 | Capture resolution | +| FRAMERATE | 60 | Frames per second | +| BITRATE | 6M | Video bitrate | +| HTTP_PORT | 8080 | HTTP server port | +| AUDIO_ENABLED | false | Enable audio streaming | +| AUDIO_BITRATE | 128 | Audio bitrate (kbps) | +| AUDIO_CODEC | aac | Audio codec (aac, mp3, pcm) | +| AUDIO_SAMPLE_RATE | 44100 | Sample rate for PCM audio | +| AUDIO_BIT_DEPTH | 16 | Bit depth for PCM audio | + +### Audio Quality Presets + +When using interactive mode, you can choose from these audio presets: + +#### Lossy Compression (AAC/MP3) +| Preset | Bitrate | Quality | Bandwidth | +|--------|-----------|-----------------|---------------| +| 1 | 64 kbps | Voice/Low | ~8 KB/s | +| 2 | 128 kbps | Standard | ~16 KB/s | +| 3 | 192 kbps | Good | ~24 KB/s | +| 4 | 256 kbps | High | ~32 KB/s | +| 5 | 320 kbps | Maximum | ~40 KB/s | + +#### Lossless PCM (16-bit) +| Preset | Sample Rate | Quality | Bandwidth | +|--------|-------------|---------------|---------------| +| 6 | 44.1 kHz | CD quality | ~172 KB/s | +| 7 | 48 kHz | DVD quality | ~188 KB/s | +| 8 | 96 kHz | Hi-Res | ~375 KB/s | +| 9 | 192 kHz | Ultra Hi-Res | ~750 KB/s | + +#### Lossless PCM (24-bit) +| Preset | Sample Rate | Quality | Bandwidth | +|--------|-------------|--------------------|---------------| +| 10 | 44.1 kHz | Studio | ~258 KB/s | +| 11 | 48 kHz | Professional | ~281 KB/s | +| 12 | 96 kHz | Hi-Res Studio | ~563 KB/s | +| 13 | 192 kHz | Ultra Hi-Res Studio| ~1125 KB/s | + +### Video Quality Presets + +| Bitrate | Quality | Bandwidth | +|---------|-------------------|---------------| +| 2M | Low bandwidth | ~250 KB/s | +| 4M | Medium quality | ~500 KB/s | +| 6M | Good quality | ~750 KB/s | +| 10M | High quality | ~1.25 MB/s | +| 15M | Very high | ~1.9 MB/s | +| 20M | Excellent | ~2.5 MB/s | To modify these settings permanently, edit the service file: ```bash @@ -104,6 +163,11 @@ The user running the script needs access to the X11 display. Run with appropriat - Ensure the port is not blocked by firewall: `sudo ufw allow 8080/tcp` - Verify the IP address and port in the startup output +### Audio not working +- Ensure PulseAudio or ALSA is running +- Check audio source: `pactl list short sources` (PulseAudio) +- Try different audio source in interactive mode + ## License MIT License diff --git a/x11stream.service b/x11stream.service index 4eb430b..383d3b7 100644 --- a/x11stream.service +++ b/x11stream.service @@ -18,4 +18,4 @@ RestartSec=5 User=root [Install] -WantedBy=multi-user.target +WantedBy=graphical.target diff --git a/x11stream.sh b/x11stream.sh index 9825b8b..9624332 100755 --- a/x11stream.sh +++ b/x11stream.sh @@ -5,49 +5,361 @@ # This script captures the X11 display and makes it available via HTTP # Access the stream at: http://{ip}:8080/stream # +# Run with --interactive or -i for interactive mode +# Run without arguments for non-interactive mode using environment variables +# set -e -# Configuration +# ============================================ +# Audio Presets with Bandwidth Estimates +# ============================================ +# MP3/AAC Bitrate Options: +# 64 kbps - Low quality voice (~8 KB/s) +# 128 kbps - Standard quality (~16 KB/s) +# 192 kbps - Good quality (~24 KB/s) +# 256 kbps - High quality (~32 KB/s) +# 320 kbps - Maximum MP3 quality (~40 KB/s) +# +# PCM/Lossless Options (sample rate @ bit depth): +# 16-bit @ 44.1 kHz - CD quality (~172 KB/s stereo) +# 16-bit @ 48 kHz - DVD quality (~188 KB/s stereo) +# 16-bit @ 96 kHz - Hi-Res (~375 KB/s stereo) +# 16-bit @ 192 kHz - Ultra Hi-Res (~750 KB/s stereo) +# 24-bit @ 44.1 kHz - Studio quality (~258 KB/s stereo) +# 24-bit @ 48 kHz - Professional (~281 KB/s stereo) +# 24-bit @ 96 kHz - Hi-Res Studio (~563 KB/s stereo) +# 24-bit @ 192 kHz - Ultra Hi-Res Studio (~1125 KB/s stereo) +# ============================================ + +# Default configuration DISPLAY_NUM="${DISPLAY:-:0.0}" RESOLUTION="${RESOLUTION:-1920x1080}" FRAMERATE="${FRAMERATE:-60}" -BITRATE="${BITRATE:-6M}" +VIDEO_BITRATE="${BITRATE:-6M}" HTTP_PORT="${HTTP_PORT:-8080}" +AUDIO_ENABLED="${AUDIO_ENABLED:-false}" +AUDIO_BITRATE="${AUDIO_BITRATE:-128}" +AUDIO_SAMPLE_RATE="${AUDIO_SAMPLE_RATE:-44100}" +AUDIO_BIT_DEPTH="${AUDIO_BIT_DEPTH:-16}" +AUDIO_CODEC="${AUDIO_CODEC:-aac}" +AUDIO_SOURCE="${AUDIO_SOURCE:-default}" +INTERACTIVE_MODE=false + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + -i|--interactive) + INTERACTIVE_MODE=true + shift + ;; + -h|--help) + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " -i, --interactive Run in interactive mode" + echo " -h, --help Show this help message" + echo "" + echo "Environment variables (non-interactive mode):" + echo " DISPLAY X11 display (default: :0.0)" + echo " RESOLUTION Video resolution (default: 1920x1080)" + echo " FRAMERATE Frames per second (default: 60)" + echo " BITRATE Video bitrate (default: 6M)" + echo " HTTP_PORT HTTP server port (default: 8080)" + echo " AUDIO_ENABLED Enable audio (default: false)" + echo " AUDIO_BITRATE Audio bitrate in kbps (default: 128)" + echo " AUDIO_CODEC Audio codec: aac, mp3, pcm (default: aac)" + exit 0 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done # Detect the machine's IP address -# Uses 'ip route get 1' to find the default route interface IP (1 is a dummy destination IP) +# Uses 'ip route get 1' to determine the primary interface IP via the default route get_ip() { ip route get 1 2>/dev/null | awk '{print $7; exit}' || hostname -I | awk '{print $1}' } IP_ADDRESS=$(get_ip) -echo "============================================" -echo "X11 Stream Server" -echo "============================================" +# Validate IP address +if [ -z "$IP_ADDRESS" ]; then + echo "Error: Unable to determine IP address for this host." >&2 + echo "Please ensure that 'ip route' or 'hostname -I' is available, or set IP_ADDRESS manually." >&2 + exit 1 +fi + +# Calculate bandwidth estimate +calculate_bandwidth() { + local video_bps audio_bps total_kbps + + # Parse video bitrate (e.g., "6M" -> 6000 kbps) + case "$VIDEO_BITRATE" in + *M) video_bps=$((${VIDEO_BITRATE%M} * 1000)) ;; + *k) video_bps=${VIDEO_BITRATE%k} ;; + *) video_bps=$VIDEO_BITRATE ;; # Assume kbps if no suffix + esac + + # Calculate audio bandwidth in kbps + if [ "$AUDIO_ENABLED" = "true" ]; then + if [ "$AUDIO_CODEC" = "pcm" ]; then + # PCM: sample_rate * bit_depth * channels / 1000 = kbps + audio_bps=$((AUDIO_SAMPLE_RATE * AUDIO_BIT_DEPTH * 2 / 1000)) + else + audio_bps=$AUDIO_BITRATE + fi + else + audio_bps=0 + fi + + total_kbps=$((video_bps + audio_bps)) + echo "$total_kbps kbps (~$((total_kbps / 8)) KB/s)" +} + +# Show audio presets menu +show_audio_presets() { + echo "" + echo "Audio Quality Presets:" + echo "============================================" + echo "Lossy Compression (AAC/MP3):" + echo " 1) 64 kbps - Voice/Low quality (~8 KB/s)" + echo " 2) 128 kbps - Standard quality (~16 KB/s)" + echo " 3) 192 kbps - Good quality (~24 KB/s)" + echo " 4) 256 kbps - High quality (~32 KB/s)" + echo " 5) 320 kbps - Maximum quality (~40 KB/s)" + echo "" + echo "Lossless PCM (16-bit):" + echo " 6) 16-bit @ 44.1 kHz - CD quality (~172 KB/s)" + echo " 7) 16-bit @ 48 kHz - DVD quality (~188 KB/s)" + echo " 8) 16-bit @ 96 kHz - Hi-Res (~375 KB/s)" + echo " 9) 16-bit @ 192 kHz - Ultra Hi-Res (~750 KB/s)" + echo "" + echo "Lossless PCM (24-bit):" + echo " 10) 24-bit @ 44.1 kHz - Studio (~258 KB/s)" + echo " 11) 24-bit @ 48 kHz - Professional (~281 KB/s)" + echo " 12) 24-bit @ 96 kHz - Hi-Res Studio (~563 KB/s)" + echo " 13) 24-bit @ 192 kHz - Ultra Hi-Res (~1125 KB/s)" + echo "============================================" +} + +# Apply audio preset +apply_audio_preset() { + case $1 in + 1) AUDIO_CODEC="aac"; AUDIO_BITRATE=64 ;; + 2) AUDIO_CODEC="aac"; AUDIO_BITRATE=128 ;; + 3) AUDIO_CODEC="aac"; AUDIO_BITRATE=192 ;; + 4) AUDIO_CODEC="aac"; AUDIO_BITRATE=256 ;; + 5) AUDIO_CODEC="aac"; AUDIO_BITRATE=320 ;; + 6) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=16; AUDIO_SAMPLE_RATE=44100 ;; + 7) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=16; AUDIO_SAMPLE_RATE=48000 ;; + 8) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=16; AUDIO_SAMPLE_RATE=96000 ;; + 9) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=16; AUDIO_SAMPLE_RATE=192000 ;; + 10) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=24; AUDIO_SAMPLE_RATE=44100 ;; + 11) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=24; AUDIO_SAMPLE_RATE=48000 ;; + 12) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=24; AUDIO_SAMPLE_RATE=96000 ;; + 13) AUDIO_CODEC="pcm"; AUDIO_BIT_DEPTH=24; AUDIO_SAMPLE_RATE=192000 ;; + *) echo "Invalid selection, using default (128 kbps AAC)"; AUDIO_CODEC="aac"; AUDIO_BITRATE=128 ;; + esac +} + +# Interactive configuration +interactive_setup() { + echo "============================================" + echo "X11 Stream Server - Interactive Setup" + echo "============================================" + echo "" + + # Display selection + echo "Current X11 display: $DISPLAY_NUM" + read -p "Enter display (press Enter for default): " input + [ -n "$input" ] && DISPLAY_NUM="$input" + + # Resolution selection + echo "" + echo "Resolution Options:" + echo " 1) 1920x1080 (Full HD)" + echo " 2) 2560x1440 (2K/QHD)" + echo " 3) 3840x2160 (4K/UHD)" + echo " 4) 1280x720 (HD)" + echo " 5) 1366x768 (HD+)" + echo " 6) Custom" + read -p "Select resolution [1-6] (default: 1): " res_choice + case $res_choice in + 2) RESOLUTION="2560x1440" ;; + 3) RESOLUTION="3840x2160" ;; + 4) RESOLUTION="1280x720" ;; + 5) RESOLUTION="1366x768" ;; + 6) read -p "Enter custom resolution (e.g., 1920x1080): " RESOLUTION ;; + *) RESOLUTION="1920x1080" ;; + esac + + # Framerate selection + echo "" + echo "Framerate Options:" + echo " 1) 24 fps (Film)" + echo " 2) 30 fps (Standard)" + echo " 3) 60 fps (Smooth)" + echo " 4) 120 fps (High refresh)" + echo " 5) 144 fps (Gaming)" + echo " 6) Custom" + read -p "Select framerate [1-6] (default: 3): " fps_choice + case $fps_choice in + 1) FRAMERATE=24 ;; + 2) FRAMERATE=30 ;; + 4) FRAMERATE=120 ;; + 5) FRAMERATE=144 ;; + 6) read -p "Enter custom framerate: " FRAMERATE ;; + *) FRAMERATE=60 ;; + esac + + # Video quality/bitrate selection + echo "" + echo "Video Quality Options:" + echo " 1) 2M - Low bandwidth (~250 KB/s)" + echo " 2) 4M - Medium quality (~500 KB/s)" + echo " 3) 6M - Good quality (~750 KB/s)" + echo " 4) 10M - High quality (~1.25 MB/s)" + echo " 5) 15M - Very high (~1.9 MB/s)" + echo " 6) 20M - Excellent (~2.5 MB/s)" + echo " 7) Custom" + read -p "Select video quality [1-7] (default: 3): " quality_choice + case $quality_choice in + 1) VIDEO_BITRATE="2M" ;; + 2) VIDEO_BITRATE="4M" ;; + 4) VIDEO_BITRATE="10M" ;; + 5) VIDEO_BITRATE="15M" ;; + 6) VIDEO_BITRATE="20M" ;; + 7) read -p "Enter custom bitrate (e.g., 6M or 6000k): " VIDEO_BITRATE ;; + *) VIDEO_BITRATE="6M" ;; + esac + + # Audio configuration + echo "" + read -p "Enable audio streaming? [y/N]: " audio_choice + if [[ "$audio_choice" =~ ^[Yy]$ ]]; then + AUDIO_ENABLED="true" + + show_audio_presets + read -p "Select audio preset [1-13] (default: 2): " audio_preset + [ -z "$audio_preset" ] && audio_preset=2 + apply_audio_preset "$audio_preset" + + # Audio source + echo "" + echo "Audio Source:" + echo " 1) PulseAudio default" + echo " 2) ALSA default" + echo " 3) Custom" + read -p "Select audio source [1-3] (default: 1): " source_choice + case $source_choice in + 2) AUDIO_SOURCE="hw:0" ;; + 3) read -p "Enter audio source: " AUDIO_SOURCE ;; + *) AUDIO_SOURCE="default" ;; + esac + else + AUDIO_ENABLED="false" + fi + + # HTTP Port + echo "" + read -p "HTTP port (default: 8080): " port_input + [ -n "$port_input" ] && HTTP_PORT="$port_input" + + echo "" + echo "============================================" + echo "Configuration Summary" + echo "============================================" +} + +# Run interactive setup if requested +if [ "$INTERACTIVE_MODE" = "true" ]; then + interactive_setup +fi + +# Build audio arguments +build_audio_args() { + if [ "$AUDIO_ENABLED" = "true" ]; then + local audio_input audio_codec_args + + # Input source + if [ "$AUDIO_SOURCE" = "default" ]; then + audio_input="-f pulse -i default" + else + audio_input="-f alsa -i $AUDIO_SOURCE" + fi + + # Codec settings + if [ "$AUDIO_CODEC" = "pcm" ]; then + local fmt + if [ "$AUDIO_BIT_DEPTH" = "24" ]; then + fmt="s24le" + else + fmt="s16le" + fi + audio_codec_args="-c:a pcm_${fmt} -ar $AUDIO_SAMPLE_RATE" + else + audio_codec_args="-c:a $AUDIO_CODEC -b:a ${AUDIO_BITRATE}k" + fi + + echo "$audio_input $audio_codec_args" + fi +} + +# Display configuration echo "Display: $DISPLAY_NUM" echo "Resolution: $RESOLUTION" echo "Framerate: $FRAMERATE fps" -echo "Bitrate: $BITRATE" +echo "Video: $VIDEO_BITRATE" +if [ "$AUDIO_ENABLED" = "true" ]; then + if [ "$AUDIO_CODEC" = "pcm" ]; then + echo "Audio: PCM ${AUDIO_BIT_DEPTH}-bit @ ${AUDIO_SAMPLE_RATE} Hz" + else + audio_codec_upper=$(echo "$AUDIO_CODEC" | tr '[:lower:]' '[:upper:]') + echo "Audio: ${audio_codec_upper} @ ${AUDIO_BITRATE} kbps" + fi +else + echo "Audio: Disabled" +fi echo "HTTP Port: $HTTP_PORT" echo "" +echo "Estimated bandwidth: $(calculate_bandwidth)" +echo "" echo "Access your stream at:" echo " http://${IP_ADDRESS}:${HTTP_PORT}/stream" echo " http://localhost:${HTTP_PORT}/stream" echo "============================================" +# Build and execute ffmpeg command +AUDIO_ARGS=$(build_audio_args) + # Run ffmpeg with x11grab and output to HTTP via mpegts # The -listen 1 flag makes ffmpeg act as an HTTP server # Low-latency settings: -# -probesize 32: Minimal probe size (bytes) for faster stream start +# -probesize 32768: Minimal probe size (32KB) for faster stream start # -analyzeduration 0: Skip analysis delay for immediate processing -exec ffmpeg -fflags nobuffer -flags low_delay -probesize 32 -analyzeduration 0 \ - -f x11grab -video_size "$RESOLUTION" -framerate "$FRAMERATE" -i "$DISPLAY_NUM" \ - -c:v libx264 -preset ultrafast -tune zerolatency \ - -x264-params "bframes=0:rc-lookahead=0:sync-lookahead=0:sliced-threads=1" \ - -g 15 -keyint_min 15 -sc_threshold 0 \ - -b:v "$BITRATE" -maxrate "$BITRATE" -bufsize 256k \ - -pix_fmt yuv420p \ - -f mpegts \ - -listen 1 "http://0.0.0.0:${HTTP_PORT}/stream" +if [ "$AUDIO_ENABLED" = "true" ]; then + exec ffmpeg -fflags nobuffer -flags low_delay -probesize 32768 -analyzeduration 0 \ + -f x11grab -video_size "$RESOLUTION" -framerate "$FRAMERATE" -i "$DISPLAY_NUM" \ + $AUDIO_ARGS \ + -c:v libx264 -preset ultrafast -tune zerolatency \ + -x264-params "bframes=0:rc-lookahead=0:sync-lookahead=0:sliced-threads=1" \ + -g 15 -keyint_min 15 -sc_threshold 0 \ + -b:v "$VIDEO_BITRATE" -maxrate "$VIDEO_BITRATE" -bufsize 256k \ + -pix_fmt yuv420p \ + -f mpegts \ + -listen 1 "http://0.0.0.0:${HTTP_PORT}/stream" +else + exec ffmpeg -fflags nobuffer -flags low_delay -probesize 32768 -analyzeduration 0 \ + -f x11grab -video_size "$RESOLUTION" -framerate "$FRAMERATE" -i "$DISPLAY_NUM" \ + -c:v libx264 -preset ultrafast -tune zerolatency \ + -x264-params "bframes=0:rc-lookahead=0:sync-lookahead=0:sliced-threads=1" \ + -g 15 -keyint_min 15 -sc_threshold 0 \ + -b:v "$VIDEO_BITRATE" -maxrate "$VIDEO_BITRATE" -bufsize 256k \ + -pix_fmt yuv420p \ + -f mpegts \ + -listen 1 "http://0.0.0.0:${HTTP_PORT}/stream" +fi