Last active
September 19, 2025 23:32
-
-
Save mahmoud/e50740d8f28d67c0b037ae58aabfc1fd to your computer and use it in GitHub Desktop.
Revisions
-
mahmoud revised this gist
Sep 19, 2025 . 1 changed file with 49 additions and 21 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -4,15 +4,18 @@ # This script sets up the Fujifilm XT-4 as a webcam from a clean slate. # # USAGE: # ./fuji_xt4_ubuntu.sh (Starts in default mode, full visible frame) # ./fuji_xt4_ubuntu.sh --letterbox (Starts in 16:9 letterbox mode) # # hit ctrl-c to restart the stream (and refocus), hit ctrl-c twice in quick succession to stop the stream. # # Required packages: # sudo apt install gphoto2 ffmpeg v4l2loopback-dkms git build-essential linux-headers-$(uname -r) v4l-utils vlc cpufrequtils # --- Script Configuration --- FULL_TOP_CROP=40 # by default the liveview stream has black bars on top and bottom FULL_BOTTOM_CROP=40 RESTART_DELAY_MS=2000 # milliseconds to wait between stream restarts, seems to need at least 2 seconds to restart cleanly # --- Common gphoto2 Parameters --- # These can be modified to customize camera behavior @@ -95,22 +98,47 @@ fi echo "β Virtual webcam found at $VIDEO_DEVICE" # 5. Start the stream with continuous autofocus based on the selected mode echo "π Starting video stream... (Press Ctrl+C to restart)" # Function to start the stream based on mode start_stream() { if [ "$MODE" == "full" ]; then # --- FULL MODE --- # Crop pixels from top and bottom to remove native letterboxing. gphoto2 $GPHOTO2_STDOUT $GPHOTO2_FOCUS_MODE $GPHOTO2_LIVEVIEW_SIZE $GPHOTO2_FOCUS_METERING $GPHOTO2_AUTOFOCUS_DRIVE $GPHOTO2_CAPTURE_MOVIE | \ ffmpeg -fflags nobuffer -i - -s 1152x768 \ -vf "crop=in_w:in_h-$((FULL_TOP_CROP + FULL_BOTTOM_CROP)):0:$FULL_TOP_CROP" \ -vcodec rawvideo -pix_fmt yuv420p -preset ultrafast -tune zerolatency \ -f v4l2 "$VIDEO_DEVICE" else # --- LETTERBOX MODE (Default) --- # Crop the stream to fill a 16:9 frame gphoto2 $GPHOTO2_STDOUT $GPHOTO2_FOCUS_MODE $GPHOTO2_LIVEVIEW_SIZE $GPHOTO2_FOCUS_METERING $GPHOTO2_AUTOFOCUS_DRIVE $GPHOTO2_CAPTURE_MOVIE | \ ffmpeg -fflags nobuffer -i - \ -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" \ -vcodec rawvideo -pix_fmt yuv420p -preset ultrafast -tune zerolatency \ -f v4l2 "$VIDEO_DEVICE" fi } # Main restart loop - just restart whenever the stream exits while true; do echo "βΆοΈ Starting stream..." # Run stream and capture exit code (don't let -e kill the script) start_stream || STREAM_EXIT_CODE=$? # Kill any remaining gphoto2 and gvfs processes (including slaves/children) pkill -f "gphoto2" 2>/dev/null || true pkill -f "gvfs-gphoto2" 2>/dev/null || true # Stream ended for any reason, wait and restart echo "βΈοΈ Stream stopped (exit code: ${STREAM_EXIT_CODE:-0}). Waiting ${RESTART_DELAY_MS}ms before restart..." # Convert milliseconds to seconds for sleep RESTART_DELAY_SEC=$(echo "scale=3; $RESTART_DELAY_MS / 1000" | bc -l 2>/dev/null || echo "0.2") sleep "$RESTART_DELAY_SEC" echo "π Restarting stream..." STREAM_EXIT_CODE=0 # Reset for next iteration done -
mahmoud revised this gist
Sep 18, 2025 . No changes.There are no files selected for viewing
-
mahmoud revised this gist
Sep 18, 2025 . No changes.There are no files selected for viewing
-
mahmoud revised this gist
Sep 18, 2025 . No changes.There are no files selected for viewing
-
mahmoud revised this gist
Sep 18, 2025 . No changes.There are no files selected for viewing
-
mahmoud created this gist
Sep 18, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,116 @@ #!/bin/bash -xe # --- Fuji XT-4 Webcam Startup Script --- # This script sets up the Fujifilm XT-4 as a webcam from a clean slate. # # USAGE: # ./start-camera.sh (Starts in default mode, full visible frame) # ./start-camera.sh --letterbox (Starts in 16:9 letterbox mode) # # Required packages: # sudo apt install gphoto2 ffmpeg v4l2loopback-dkms git build-essential linux-headers-$(uname -r) v4l-utils vlc cpufrequtils # --- Script Configuration --- FULL_TOP_CROP=40 # by default the liveview stream has black bars on top and bottom FULL_BOTTOM_CROP=40 # --- Common gphoto2 Parameters --- # These can be modified to customize camera behavior GPHOTO2_STDOUT="--stdout" GPHOTO2_FOCUS_MODE="--set-config /main/capturesettings/focusmode=2" GPHOTO2_LIVEVIEW_SIZE="--set-config /main/capturesettings/liveviewsize=0" GPHOTO2_CAPTURE_MOVIE="--capture-movie" # Autofocus settings - continuous autofocus eludes me at this point. Only thing I haven't tried is a firmware update bc I'm already on firmware 2.01. GPHOTO2_AUTOFOCUS_DRIVE="--set-config /main/actions/autofocusdrive=1" GPHOTO2_FOCUS_METERING="--set-config /main/capturesettings/focusmetermode=0" # Single-area AF # Additional common parameters (commented out - uncomment and modify as needed) # GPHOTO2_ISO="--set-config /main/imgsettings/iso=800" # ISO values: 80-51200 # GPHOTO2_APERTURE="--set-config /main/capturesettings/f-number=f/2.8" # f/1.2 to f/22 (lens dependent) # GPHOTO2_SHUTTER_SPEED="--set-config /main/capturesettings/shutterspeed=1/60" # 1/8000 to 15m + bulb # GPHOTO2_WHITE_BALANCE="--set-config /main/imgsettings/whitebalance=0" # 0=Auto, 1=Daylight, 2=Tungsten, etc. # GPHOTO2_METERING_MODE="--set-config /main/capturesettings/exposuremetermode=2" # 0=Average, 1=Center, 2=Multi, 3=Spot # GPHOTO2_FILM_SIMULATION="--set-config /main/imgsettings/filmsimulation=0" # 0=PROVIA, 1=Velvia, 2=ASTIA, etc. # GPHOTO2_FOCUS_METERING="--set-config /main/capturesettings/focusmetermode=0" # 0=Single-area, 1=Dynamic, 2=Group # GPHOTO2_IMAGE_FORMAT="--set-config /main/imgsettings/imageformat=1" # 0=RAW, 1=JPEG Fine, 2=JPEG Normal, etc. echo "πΈ Starting Fuji Webcam..." # Check for aspect ratio flag MODE="full" if [ "$1" == "--letterbox" ]; then MODE="letterbox" fi echo "Aspect Ratio Mode: $MODE" # 1. Prompt for administrator password upfront sudo -v # 2. Kill any conflicting processes that might be holding the camera echo "Checking for conflicting processes..." killall gvfs-gphoto2-volume-monitor > /dev/null 2>&1 || true # 3. Ensure v4l2loopback is ready (reload for a clean slate) echo "Reloading virtual camera module..." sudo modprobe -r v4l2loopback sleep 1 sudo modprobe v4l2loopback exclusive_caps=1 card_label="Fuji XT-4" sleep 1 # 4. Find the virtual video device dynamically echo "Detecting available video devices..." # First, check if v4l2-ctl command is available and working if ! command -v v4l2-ctl &> /dev/null; then echo "β Error: v4l2-ctl command not found. Please install v4l-utils package:" echo " sudo apt install v4l-utils" exit 1 fi # Get the list of devices, with error handling DEVICE_LIST=$(v4l2-ctl --list-devices 2>&1) if [ $? -ne 0 ]; then echo "β Error: Failed to list video devices:" echo "$DEVICE_LIST" exit 1 fi # Try to find the Fuji XT-4 device VIDEO_DEVICE=$(echo "$DEVICE_LIST" | grep -A 1 'Fuji XT-4' | grep -o '/dev/video[0-9]*') if [ -z "$VIDEO_DEVICE" ]; then echo "β Error: Could not find the 'Fuji XT-4' virtual webcam." echo "" echo "Available video devices:" echo "=======================" echo "$DEVICE_LIST" echo "" echo "π‘ Troubleshooting tips:" echo " 1. Make sure the v4l2loopback module loaded correctly" echo " 2. Check if the card_label matches exactly: 'Fuji XT-4'" echo " 3. Try rerunning the script to reload the module" exit 1 fi echo "β Virtual webcam found at $VIDEO_DEVICE" # 5. Start the stream with continuous autofocus based on the selected mode echo "π Starting video stream... (Press Ctrl+C in this window to stop)" if [ "$MODE" == "full" ]; then # --- FULL MODE --- # Crop pixels from top and bottom to remove native letterboxing. gphoto2 $GPHOTO2_STDOUT $GPHOTO2_FOCUS_MODE $GPHOTO2_LIVEVIEW_SIZE $GPHOTO2_FOCUS_METERING $GPHOTO2_AUTOFOCUS_DRIVE $GPHOTO2_CAPTURE_MOVIE | \ ffmpeg -fflags nobuffer -i - -s 1152x768 \ -vf "crop=in_w:in_h-$((FULL_TOP_CROP + FULL_BOTTOM_CROP)):0:$FULL_TOP_CROP" \ -vcodec rawvideo -pix_fmt yuv420p -preset ultrafast -tune zerolatency \ -f v4l2 "$VIDEO_DEVICE" else # --- LETTERBOX MODE (Default) --- # Crop the stream to fill a 16:9 frame gphoto2 $GPHOTO2_STDOUT $GPHOTO2_FOCUS_MODE $GPHOTO2_LIVEVIEW_SIZE $GPHOTO2_FOCUS_METERING $GPHOTO2_AUTOFOCUS_DRIVE $GPHOTO2_CAPTURE_MOVIE | \ ffmpeg -fflags nobuffer -i - \ -vf "scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720" \ -vcodec rawvideo -pix_fmt yuv420p -preset ultrafast -tune zerolatency \ -f v4l2 "$VIDEO_DEVICE" fi