From 4cb116dc33329b1e20aada4c2f712008356600e8 Mon Sep 17 00:00:00 2001 From: Yanko Aleksandrov Date: Thu, 5 Jun 2025 17:58:45 +0300 Subject: [PATCH 1/5] working video storage with audio --- .../video_encoders/kill_old_gstreamers.sh | 67 ++++++++++++ installer/video_encoders/record_audio.sh | 85 +++++++++++++++ .../video_encoders/video_storage_encoder.sh | 50 --------- .../video_storage_encoder_with_audio.sh | 103 ++++++++++++++++++ 4 files changed, 255 insertions(+), 50 deletions(-) create mode 100755 installer/video_encoders/kill_old_gstreamers.sh create mode 100755 installer/video_encoders/record_audio.sh delete mode 100755 installer/video_encoders/video_storage_encoder.sh create mode 100755 installer/video_encoders/video_storage_encoder_with_audio.sh diff --git a/installer/video_encoders/kill_old_gstreamers.sh b/installer/video_encoders/kill_old_gstreamers.sh new file mode 100755 index 0000000..9048e1a --- /dev/null +++ b/installer/video_encoders/kill_old_gstreamers.sh @@ -0,0 +1,67 @@ +#!/bin/bash + +# Kill Old GStreamer Processes Script +# This script cleans up any running gst-launch processes that might be blocking audio/video devices + +echo "๐Ÿงน GStreamer Process Cleanup Script" +echo "====================================" + +# Function to cleanup old GStreamer processes +cleanup_old_processes() { + echo "๐Ÿ” Searching for running GStreamer processes..." + + # Find and display all gst-launch processes + PROCESS_LIST=$(ps aux | grep gst-launch | grep -v grep) + + if [ ! -z "$PROCESS_LIST" ]; then + echo "๐Ÿ“‹ Found running GStreamer processes:" + echo "$PROCESS_LIST" + echo "" + + # Extract PIDs + OLD_PIDS=$(echo "$PROCESS_LIST" | awk '{print $2}') + + echo "๐Ÿ”ซ Terminating processes (SIGTERM): $OLD_PIDS" + echo $OLD_PIDS | xargs kill 2>/dev/null + sleep 3 + + # Check if any processes are still running + REMAINING_LIST=$(ps aux | grep gst-launch | grep -v grep) + if [ ! -z "$REMAINING_LIST" ]; then + REMAINING_PIDS=$(echo "$REMAINING_LIST" | awk '{print $2}') + echo "๐Ÿ’€ Force killing remaining processes (SIGKILL): $REMAINING_PIDS" + echo $REMAINING_PIDS | xargs kill -9 2>/dev/null + sleep 1 + + # Final check + FINAL_CHECK=$(ps aux | grep gst-launch | grep -v grep) + if [ ! -z "$FINAL_CHECK" ]; then + echo "โŒ Warning: Some processes may still be running:" + echo "$FINAL_CHECK" + else + echo "โœ… All GStreamer processes successfully terminated" + fi + else + echo "โœ… All GStreamer processes successfully terminated" + fi + else + echo "โœ… No running GStreamer processes found" + fi + + echo "" + echo "๐ŸŽค Audio devices should now be available" + echo "๐Ÿ“น Video pipeline resources freed" +} + +# Run the cleanup +cleanup_old_processes + +# Optional: Show available audio devices +if command -v arecord &> /dev/null; then + echo "" + echo "๐ŸŽต Available audio capture devices:" + arecord -l | grep "card" | head -5 +fi + +echo "" +echo "Done! ๐ŸŽฌ" diff --git a/installer/video_encoders/record_audio.sh b/installer/video_encoders/record_audio.sh new file mode 100755 index 0000000..f1d5ca6 --- /dev/null +++ b/installer/video_encoders/record_audio.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +# Simple audio recording script for testing ReSpeaker microphone +# Usage: ./record_audio.sh [duration_in_seconds] [output_filename] + +# Default values +DURATION=${1:-10} # Default 10 seconds +OUTPUT_FILE=${2:-"audio_test_$(date +%Y%m%d_%H%M%S).wav"} +DEVICE="respeaker" + +echo "๐ŸŽค Audio Recording Test Script" +echo "===============================" +echo "Device: $DEVICE" +echo "Duration: $DURATION seconds" +echo "Output file: $OUTPUT_FILE" +echo "" + +# Check if arecord is available +if ! command -v arecord &> /dev/null; then + echo "โŒ Error: arecord not found. Please install alsa-utils:" + echo " sudo apt-get install alsa-utils" + exit 1 +fi + +# List available audio devices +echo "๐Ÿ“‹ Available audio devices:" +arecord -l +echo "" + +# Try to find ReSpeaker device +echo "๐Ÿ” Looking for ReSpeaker device..." +CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') + +if [ -z "$CARD_NUMBER" ]; then + echo "โš ๏ธ Warning: No ReSpeaker device found in device list." + echo " Available devices:" + arecord -l | grep "card" + echo "" + echo " Please specify the correct card number manually or check device connection." + echo " You can also try running with a specific device:" + echo " arecord -D hw:CARD_NUMBER,0 -f S16_LE -r 16000 -c 6 -d $DURATION $OUTPUT_FILE" + exit 1 +else + echo "โœ… Found ReSpeaker at card $CARD_NUMBER" +fi + +# Record audio +echo "" +echo "๐Ÿ”ด Starting recording in 3 seconds..." +echo " Speak into your microphone to test it!" +sleep 1 +echo " 3..." +sleep 1 +echo " 2..." +sleep 1 +echo " 1..." +sleep 1 +echo " ๐ŸŽ™๏ธ RECORDING NOW! (${DURATION}s)" + +# Record with specific parameters for ReSpeaker +arecord -D hw:$CARD_NUMBER,0 \ + -f S16_LE \ + -r 16000 \ + -c 6 \ + -d $DURATION \ + "$OUTPUT_FILE" + +if [ $? -eq 0 ]; then + echo "" + echo "โœ… Recording completed successfully!" + echo " File: $OUTPUT_FILE" + echo " Size: $(ls -lh "$OUTPUT_FILE" | awk '{print $5}')" + echo "" + echo "๐Ÿ”Š To play back the recording:" + echo " aplay $OUTPUT_FILE" + echo "" + echo " Or with volume control:" + echo " aplay $OUTPUT_FILE || paplay $OUTPUT_FILE" +else + echo "" + echo "โŒ Recording failed. Please check:" + echo " 1. ReSpeaker device is connected" + echo " 2. Device permissions (try with sudo if needed)" + echo " 3. Audio drivers are installed" +fi diff --git a/installer/video_encoders/video_storage_encoder.sh b/installer/video_encoders/video_storage_encoder.sh deleted file mode 100755 index 2427e23..0000000 --- a/installer/video_encoders/video_storage_encoder.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash - -# Set output directory for video storage -OUTPUT_DIR="/home/skycore/videos" -# Create directory if it doesn't exist -mkdir -p $OUTPUT_DIR - -# Log file for recording status -LOG_FILE="$OUTPUT_DIR/recording_log.txt" - -# Function to log messages -log_message() { - echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" >> "$LOG_FILE" - echo "$1" -} - -log_message "Starting HLS recording with 60-minute playlist rotation" - -# Main recording loop - runs indefinitely -while true; do - # Generate timestamp for this hour's recording - TIMESTAMP=$(date +%Y%m%d_%H%M%S) - - log_message "Creating new playlist: ${TIMESTAMP}_playlist.m3u8" - - # Run GStreamer for 60 minutes (3600 seconds) - timeout 3630 gst-launch-1.0 -e \ - rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=50 drop-on-latency=true ! \ - rtph264depay ! \ - h264parse ! \ - mpegtsmux ! \ - hlssink playlist-root=file://$OUTPUT_DIR \ - target-duration=60 \ - playlist-length=60 \ - max-files=0 \ - playlist-location="$OUTPUT_DIR/${TIMESTAMP}_playlist.m3u8" \ - location="$OUTPUT_DIR/${TIMESTAMP}_segment_%05d.ts" - - # Check if gst-launch exited due to an error - EXIT_CODE=$? - if [ $EXIT_CODE -ne 0 ] && [ $EXIT_CODE -ne 124 ]; then - # Exit code 124 means timeout completed normally - log_message "Error: gst-launch exited with code $EXIT_CODE. Waiting 10 seconds before retry." - sleep 10 - else - log_message "60-minute recording completed successfully" - # Small pause between recordings - sleep 2 - fi -done \ No newline at end of file diff --git a/installer/video_encoders/video_storage_encoder_with_audio.sh b/installer/video_encoders/video_storage_encoder_with_audio.sh new file mode 100755 index 0000000..8e6733d --- /dev/null +++ b/installer/video_encoders/video_storage_encoder_with_audio.sh @@ -0,0 +1,103 @@ +#!/bin/bash + +# Set output directory for video storage +OUTPUT_DIR="/home/skycore/videos" +# Create directory if it doesn't exist +mkdir -p $OUTPUT_DIR + +# Log file for recording status +LOG_FILE="$OUTPUT_DIR/recording_log.txt" + +# Function to log messages +log_message() { + echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" >> "$LOG_FILE" + echo "$1" +} + +# Function to find ReSpeaker audio device +find_respeaker_device() { + CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') + if [ -z "$CARD_NUMBER" ]; then + log_message "Warning: No ReSpeaker device found. Audio will be disabled." + return 1 + else + log_message "Found ReSpeaker at card $CARD_NUMBER" + echo $CARD_NUMBER + return 0 + fi +} + +log_message "Starting HLS recording with audio support and 60-minute playlist rotation" + +# Check for ReSpeaker device +RESPEAKER_CARD=$(find_respeaker_device | tail -n 1) +AUDIO_AVAILABLE=$? + +# Main recording loop - runs indefinitely +while true; do + # Generate timestamp for this hour's recording + TIMESTAMP=$(date +%Y%m%d_%H%M%S) + + log_message "Creating new playlist: ${TIMESTAMP}_playlist.m3u8" + + if [ $AUDIO_AVAILABLE -eq 0 ]; then + log_message "Recording with audio from ReSpeaker (card $RESPEAKER_CARD)" + # Enhanced pipeline with audio support (video + microphone audio) + timeout 3630 gst-launch-1.0 -e \ + mpegtsmux name=mux ! \ + hlssink playlist-root=file://$OUTPUT_DIR \ + target-duration=60 playlist-length=60 max-files=0 \ + playlist-location="$OUTPUT_DIR/${TIMESTAMP}_playlist.m3u8" \ + location="$OUTPUT_DIR/${TIMESTAMP}_segment_%05d.ts" \ + rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=50 drop-on-latency=true ! \ + rtph264depay ! h264parse ! \ + nvv4l2decoder enable-max-performance=1 disable-dpb=1 ! \ + nvvidconv ! \ + "video/x-raw(memory:NVMM),format=NV12" ! \ + nvv4l2h264enc profile=0 bitrate=15000000 iframeinterval=30 idrinterval=1 maxperf-enable=true poc-type=2 insert-sps-pps=true preset-level=0 ratecontrol-enable=1 quant-i-frames=20 quant-p-frames=23 quant-b-frames=25 ! \ + h264parse config-interval=1 ! \ + queue max-size-buffers=100 max-size-time=1000000000 ! \ + mux. \ + alsasrc device=hw:$RESPEAKER_CARD,0 ! \ + audio/x-raw,format=S16LE,rate=16000,channels=6 ! \ + audioconvert ! audioresample ! \ + audio/x-raw,rate=48000,channels=2 ! \ + queue max-size-buffers=200 max-size-time=2000000000 ! \ + avenc_aac bitrate=128000 ! aacparse ! mux. + else + log_message "Recording video only (no audio device available)" + # Original pipeline without audio + timeout 3630 gst-launch-1.0 -e \ + rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=50 drop-on-latency=true ! \ + rtph264depay ! h264parse ! \ + nvv4l2decoder enable-max-performance=1 disable-dpb=1 ! \ + nvvidconv ! \ + "video/x-raw(memory:NVMM),format=NV12" ! \ + nvv4l2h264enc profile=0 bitrate=15000000 iframeinterval=30 idrinterval=1 maxperf-enable=true poc-type=2 insert-sps-pps=true preset-level=0 ratecontrol-enable=1 quant-i-frames=20 quant-p-frames=23 quant-b-frames=25 ! \ + h264parse config-interval=1 ! \ + queue max-size-buffers=100 max-size-time=1000000000 ! \ + mpegtsmux ! \ + hlssink playlist-root=file://$OUTPUT_DIR \ + target-duration=60 \ + playlist-length=60 \ + max-files=0 \ + playlist-location="$OUTPUT_DIR/${TIMESTAMP}_playlist.m3u8" \ + location="$OUTPUT_DIR/${TIMESTAMP}_segment_%05d.ts" + fi + + # Check if gst-launch exited due to an error + EXIT_CODE=$? + if [ $EXIT_CODE -ne 0 ] && [ $EXIT_CODE -ne 124 ]; then + # Exit code 124 means timeout completed normally + log_message "Error: gst-launch exited with code $EXIT_CODE. Waiting 10 seconds before retry." + sleep 10 + else + if [ $AUDIO_AVAILABLE -eq 0 ]; then + log_message "60-minute recording with audio completed successfully" + else + log_message "60-minute recording (video only) completed successfully" + fi + # Small pause between recordings + sleep 2 + fi +done \ No newline at end of file From 06f7e0e7e2a42a6839ff4997f183b2887a7cb57e Mon Sep 17 00:00:00 2001 From: Yanko Aleksandrov Date: Fri, 13 Jun 2025 20:57:23 +0300 Subject: [PATCH 2/5] update stuff --- .github/workflows/deploy-docs.yml | 0 .github/workflows/test-installer.yml | 0 installer/audio_encoders/audio_encoder.sh | 36 ++++ installer/sc.sh | 155 +++++++++++++++++- .../video_encoders/video_hardware_encoder.sh | 0 .../video_encoders/video_software_encoder.sh | 39 ++++- list_cameras.py | 0 services/depth/README.md | 0 services/depth/cfg/d4xx-default.json | 0 services/depth/cfg/d4xx-high-accuracy.json | 0 services/depth/cfg/d4xx-high-confidence.json | 0 services/depth/depth _single_cam.py | 0 services/depth/depth.service | 0 services/depth/dock_aruco.py | 0 services/video/video.service | 0 services/video/video.sh | 0 tests/README.md | 0 tests/activate_drone.bats | 0 tests/banner.bats | 0 tests/clone_drive.bats | 0 tests/flash_drive.bats | 0 tests/install.bats | 0 tests/root_check.bats | 0 23 files changed, 225 insertions(+), 5 deletions(-) mode change 100644 => 100755 .github/workflows/deploy-docs.yml mode change 100644 => 100755 .github/workflows/test-installer.yml create mode 100644 installer/audio_encoders/audio_encoder.sh mode change 100644 => 100755 installer/video_encoders/video_hardware_encoder.sh mode change 100644 => 100755 list_cameras.py mode change 100644 => 100755 services/depth/README.md mode change 100644 => 100755 services/depth/cfg/d4xx-default.json mode change 100644 => 100755 services/depth/cfg/d4xx-high-accuracy.json mode change 100644 => 100755 services/depth/cfg/d4xx-high-confidence.json mode change 100644 => 100755 services/depth/depth _single_cam.py mode change 100644 => 100755 services/depth/depth.service mode change 100644 => 100755 services/depth/dock_aruco.py mode change 100644 => 100755 services/video/video.service mode change 100644 => 100755 services/video/video.sh mode change 100644 => 100755 tests/README.md mode change 100644 => 100755 tests/activate_drone.bats mode change 100644 => 100755 tests/banner.bats mode change 100644 => 100755 tests/clone_drive.bats mode change 100644 => 100755 tests/flash_drive.bats mode change 100644 => 100755 tests/install.bats mode change 100644 => 100755 tests/root_check.bats diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/test-installer.yml b/.github/workflows/test-installer.yml old mode 100644 new mode 100755 diff --git a/installer/audio_encoders/audio_encoder.sh b/installer/audio_encoders/audio_encoder.sh new file mode 100644 index 0000000..a5a58ef --- /dev/null +++ b/installer/audio_encoders/audio_encoder.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Function to find ReSpeaker audio device +find_respeaker_device() { + CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') + if [ -z "$CARD_NUMBER" ]; then + echo "Warning: No ReSpeaker device found. Audio will be disabled." >&2 + return 1 + else + echo "Found ReSpeaker at card $CARD_NUMBER" >&2 + echo $CARD_NUMBER + return 0 + fi +} + +# Check for ReSpeaker device +RESPEAKER_CARD=$(find_respeaker_device | tail -n 1) +AUDIO_AVAILABLE=$? + +# Audio pipeline (if ReSpeaker available) +if [ $AUDIO_AVAILABLE -eq 0 ]; then + echo "Adding audio stream from ReSpeaker (card $RESPEAKER_CARD) on port 5011" + gst-launch-1.0 -e \ + alsasrc device=hw:$RESPEAKER_CARD,0 do-timestamp=true ! \ + audio/x-raw,format=S16LE,rate=16000,channels=6 ! \ + audioconvert ! audioresample ! \ + audio/x-raw,rate=48000,channels=2 ! \ + opusenc bitrate=128000 ! \ + rtpopuspay pt=111 ! \ + udpsink host=127.0.0.1 port=5011 sync=false & +else + echo "No audio device found - audio encoder disabled" +fi + +# Wait for all background processes +wait diff --git a/installer/sc.sh b/installer/sc.sh index f561c78..cc2f9a5 100755 --- a/installer/sc.sh +++ b/installer/sc.sh @@ -1458,6 +1458,146 @@ EOF echo -e " - systemctl restart skycore-video-storage.service" } +# Function to set up audio streaming service +setup_audio_service() { + check_root + + SCRIPT_PATH="/home/skycore/audio_encoder.sh" + TARGET_PORT="${1:-5011}" + + echo -e "${YELLOW}[โ‹ฏ]${NC} Setting up audio streaming service..." + echo -e "${YELLOW}[โ‹ฏ]${NC} Streaming audio to UDP port: ${TARGET_PORT}" + echo -e "${YELLOW}[โ‹ฏ]${NC} Looking for ReSpeaker audio device..." + + # Create the audio encoder script file + echo -e "${YELLOW}[โ‹ฏ]${NC} Creating audio encoder script at $SCRIPT_PATH..." + + cat > "$SCRIPT_PATH" << 'EOF' +#!/bin/bash + +# Function to find ReSpeaker audio device +find_respeaker_device() { + CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') + if [ -z "$CARD_NUMBER" ]; then + echo "Warning: No ReSpeaker device found. Audio will be disabled." >&2 + return 1 + else + echo "Found ReSpeaker at card $CARD_NUMBER" >&2 + echo $CARD_NUMBER + return 0 + fi +} + +# Log function for service output +log_message() { + echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" +} + +log_message "Starting audio encoder service..." + +# Check for ReSpeaker device +RESPEAKER_CARD=$(find_respeaker_device | tail -n 1) +AUDIO_AVAILABLE=$? + +# Audio pipeline (if ReSpeaker available) +if [ $AUDIO_AVAILABLE -eq 0 ]; then + log_message "Adding audio stream from ReSpeaker (card $RESPEAKER_CARD) on port TARGET_PORT_PLACEHOLDER" + + # Main audio streaming loop with restart capability + while true; do + gst-launch-1.0 -e \ + alsasrc device=hw:$RESPEAKER_CARD,0 do-timestamp=true ! \ + audio/x-raw,format=S16LE,rate=16000,channels=6 ! \ + audioconvert ! audioresample ! \ + audio/x-raw,rate=48000,channels=2 ! \ + opusenc bitrate=128000 ! \ + rtpopuspay pt=111 ! \ + udpsink host=127.0.0.1 port=TARGET_PORT_PLACEHOLDER sync=false + + # Check exit status + EXIT_CODE=$? + if [ $EXIT_CODE -ne 0 ]; then + log_message "Audio pipeline exited with code $EXIT_CODE. Restarting in 5 seconds..." + sleep 5 + else + log_message "Audio pipeline stopped normally" + break + fi + done +else + log_message "No ReSpeaker audio device found - audio encoder disabled" + log_message "Service will keep running but audio streaming is inactive" + + # Keep the service running even without audio device + while true; do + sleep 60 + log_message "Audio service running (no device detected)" + done +fi +EOF + + # Replace the placeholder with actual port + sed -i "s/TARGET_PORT_PLACEHOLDER/${TARGET_PORT}/g" "$SCRIPT_PATH" + + # Make script executable + chmod +x "$SCRIPT_PATH" + chown skycore:skycore "$SCRIPT_PATH" + + # Create systemd service file + SERVICE_FILE="/etc/systemd/system/skycore-audio.service" + + echo -e "${YELLOW}[โ‹ฏ]${NC} Creating systemd service file at $SERVICE_FILE..." + + cat > "$SERVICE_FILE" << EOF +[Unit] +Description=SkyCore Audio Streaming Service +After=network.target sound.target + +[Service] +Type=simple +ExecStart=$SCRIPT_PATH +Restart=on-failure +RestartSec=10 +User=skycore +Group=skycore +# Add audio group for ALSA access +SupplementaryGroups=audio + +[Install] +WantedBy=multi-user.target +EOF + + # Reload systemd to recognize new service + echo -e "${YELLOW}[โ‹ฏ]${NC} Reloading systemd..." + systemctl daemon-reload + + # Enable service to start on boot + echo -e "${YELLOW}[โ‹ฏ]${NC} Enabling audio service to start on boot..." + systemctl enable skycore-audio.service + + # Start the service + echo -e "${YELLOW}[โ‹ฏ]${NC} Starting audio service..." + systemctl start skycore-audio.service + + # Check service status + sleep 3 + if systemctl is-active --quiet skycore-audio.service; then + echo -e "${GREEN}[โœ”]${NC} Audio service started successfully" + else + echo -e "${RED}[โœ–]${NC} Failed to start audio service" + echo -e "${YELLOW}[โ‹ฏ]${NC} Check logs with: systemctl status skycore-audio.service" + echo -e "${YELLOW}[โ‹ฏ]${NC} Check logs with: journalctl -u skycore-audio.service -f" + fi + + echo -e "${GREEN}[โœ”]${NC} Audio service has been set up and will run on boot" + echo -e "${YELLOW}[โ‹ฏ]${NC} Audio will be streamed to UDP port: ${TARGET_PORT}" + echo -e "${YELLOW}[โ‹ฏ]${NC} You can control the service with:" + echo -e " - systemctl start skycore-audio.service" + echo -e " - systemctl stop skycore-audio.service" + echo -e " - systemctl restart skycore-audio.service" + echo -e " - journalctl -u skycore-audio.service -f (view logs)" +} + # Function to update SkyCore to the latest version update_skycore() { echo -e "${YELLOW}[โ‹ฏ]${NC} Checking for latest SkyCore release..." @@ -1551,6 +1691,11 @@ elif [[ "$1" == "video-storage-service" ]]; then shift setup_video_storage_service "$@" +elif [[ "$1" == "audio-service" ]]; then + # Setup audio streaming service + shift + setup_audio_service "$@" + elif [[ "$1" == "help" ]]; then echo "Available commands:" echo " skycore cli - Start the SkyCore CLI" @@ -1568,8 +1713,9 @@ elif [[ "$1" == "help" ]]; then echo " skycore install - Install skycore to the system" echo " skycore update - Update skycore to the latest version" echo " skycore tty-setup - Set up TTY device permission rules" - echo " skycore video-service [path] - Set up video streaming service to run on boot" - echo " skycore video-storage-service [output_dir] [ip] [segment_duration] [max_files] - Set up video storage service to run on boot" + echo " skycore video-service [ip] [port] - Set up video streaming service to run on boot" + echo " skycore video-storage-service [output_dir] [ip] - Set up video storage service to run on boot" + echo " skycore audio-service [port] - Set up audio streaming service to run on boot" echo " skycore utils - Run utility commands" echo " Available utilities:" echo " boot_mmc - Configure system to boot from SD card" @@ -1602,8 +1748,9 @@ else echo " skycore install - Install skycore to the system" echo " skycore update - Update skycore to the latest version" echo " skycore tty-setup - Set up TTY device permission rules" - echo " skycore video-service [path] - Set up video streaming service to run on boot" - echo " skycore video-storage-service [output_dir] [ip] [segment_duration] [max_files] - Set up video storage service to run on boot" + echo " skycore video-service [ip] [port] - Set up video streaming service to run on boot" + echo " skycore video-storage-service [output_dir] [ip] - Set up video storage service to run on boot" + echo " skycore audio-service [port] - Set up audio streaming service to run on boot" echo " skycore utils - Run utility commands" echo " Available utilities:" echo " boot_mmc - Configure system to boot from SD card" diff --git a/installer/video_encoders/video_hardware_encoder.sh b/installer/video_encoders/video_hardware_encoder.sh old mode 100644 new mode 100755 diff --git a/installer/video_encoders/video_software_encoder.sh b/installer/video_encoders/video_software_encoder.sh index b906655..8539997 100755 --- a/installer/video_encoders/video_software_encoder.sh +++ b/installer/video_encoders/video_software_encoder.sh @@ -1,4 +1,23 @@ #!/bin/bash + +# Function to find ReSpeaker audio device +find_respeaker_device() { + CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') + if [ -z "$CARD_NUMBER" ]; then + echo "Warning: No ReSpeaker device found. Audio will be disabled." >&2 + return 1 + else + echo "Found ReSpeaker at card $CARD_NUMBER" >&2 + echo $CARD_NUMBER + return 0 + fi +} + +# Check for ReSpeaker device +RESPEAKER_CARD=$(find_respeaker_device | tail -n 1) +AUDIO_AVAILABLE=$? + +# Original video pipeline (unchanged) gst-launch-1.0 -e \ rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=50 drop-on-latency=true ! \ rtph264depay ! h264parse ! \ @@ -10,4 +29,22 @@ gst-launch-1.0 -e \ x264enc tune=zerolatency speed-preset=ultrafast bitrate=2500 key-int-max=15 bframes=0 ! \ h264parse config-interval=1 ! \ video/x-h264,stream-format=byte-stream,alignment=au ! \ - udpsink host=127.0.0.1 port=5010 sync=false + udpsink host=127.0.0.1 port=5010 sync=false & + +# Audio pipeline (if ReSpeaker available) +if [ $AUDIO_AVAILABLE -eq 0 ]; then + echo "Adding audio stream from ReSpeaker (card $RESPEAKER_CARD) on port 5011" + gst-launch-1.0 -e \ + alsasrc device=hw:$RESPEAKER_CARD,0 do-timestamp=true ! \ + audio/x-raw,format=S16LE,rate=16000,channels=6 ! \ + audioconvert ! audioresample ! \ + audio/x-raw,rate=48000,channels=2 ! \ + opusenc bitrate=128000 ! \ + rtpopuspay pt=111 ! \ + udpsink host=127.0.0.1 port=5011 sync=false & +else + echo "No audio device found - video only" +fi + +# Wait for all background processes +wait diff --git a/list_cameras.py b/list_cameras.py old mode 100644 new mode 100755 diff --git a/services/depth/README.md b/services/depth/README.md old mode 100644 new mode 100755 diff --git a/services/depth/cfg/d4xx-default.json b/services/depth/cfg/d4xx-default.json old mode 100644 new mode 100755 diff --git a/services/depth/cfg/d4xx-high-accuracy.json b/services/depth/cfg/d4xx-high-accuracy.json old mode 100644 new mode 100755 diff --git a/services/depth/cfg/d4xx-high-confidence.json b/services/depth/cfg/d4xx-high-confidence.json old mode 100644 new mode 100755 diff --git a/services/depth/depth _single_cam.py b/services/depth/depth _single_cam.py old mode 100644 new mode 100755 diff --git a/services/depth/depth.service b/services/depth/depth.service old mode 100644 new mode 100755 diff --git a/services/depth/dock_aruco.py b/services/depth/dock_aruco.py old mode 100644 new mode 100755 diff --git a/services/video/video.service b/services/video/video.service old mode 100644 new mode 100755 diff --git a/services/video/video.sh b/services/video/video.sh old mode 100644 new mode 100755 diff --git a/tests/README.md b/tests/README.md old mode 100644 new mode 100755 diff --git a/tests/activate_drone.bats b/tests/activate_drone.bats old mode 100644 new mode 100755 diff --git a/tests/banner.bats b/tests/banner.bats old mode 100644 new mode 100755 diff --git a/tests/clone_drive.bats b/tests/clone_drive.bats old mode 100644 new mode 100755 diff --git a/tests/flash_drive.bats b/tests/flash_drive.bats old mode 100644 new mode 100755 diff --git a/tests/install.bats b/tests/install.bats old mode 100644 new mode 100755 diff --git a/tests/root_check.bats b/tests/root_check.bats old mode 100644 new mode 100755 From f49008d4ef1b73ec0313c479a5d99e25c548a430 Mon Sep 17 00:00:00 2001 From: Yanko Aleksandrov Date: Sat, 14 Jun 2025 14:54:36 +0300 Subject: [PATCH 3/5] fix video stream --- installer/audio_encoders/audio_encoder.sh | 0 .../video_encoders/video_software_encoder.sh | 39 +------------------ 2 files changed, 1 insertion(+), 38 deletions(-) mode change 100644 => 100755 installer/audio_encoders/audio_encoder.sh diff --git a/installer/audio_encoders/audio_encoder.sh b/installer/audio_encoders/audio_encoder.sh old mode 100644 new mode 100755 diff --git a/installer/video_encoders/video_software_encoder.sh b/installer/video_encoders/video_software_encoder.sh index 8539997..57ab7b4 100755 --- a/installer/video_encoders/video_software_encoder.sh +++ b/installer/video_encoders/video_software_encoder.sh @@ -1,23 +1,4 @@ #!/bin/bash - -# Function to find ReSpeaker audio device -find_respeaker_device() { - CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') - if [ -z "$CARD_NUMBER" ]; then - echo "Warning: No ReSpeaker device found. Audio will be disabled." >&2 - return 1 - else - echo "Found ReSpeaker at card $CARD_NUMBER" >&2 - echo $CARD_NUMBER - return 0 - fi -} - -# Check for ReSpeaker device -RESPEAKER_CARD=$(find_respeaker_device | tail -n 1) -AUDIO_AVAILABLE=$? - -# Original video pipeline (unchanged) gst-launch-1.0 -e \ rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=50 drop-on-latency=true ! \ rtph264depay ! h264parse ! \ @@ -29,22 +10,4 @@ gst-launch-1.0 -e \ x264enc tune=zerolatency speed-preset=ultrafast bitrate=2500 key-int-max=15 bframes=0 ! \ h264parse config-interval=1 ! \ video/x-h264,stream-format=byte-stream,alignment=au ! \ - udpsink host=127.0.0.1 port=5010 sync=false & - -# Audio pipeline (if ReSpeaker available) -if [ $AUDIO_AVAILABLE -eq 0 ]; then - echo "Adding audio stream from ReSpeaker (card $RESPEAKER_CARD) on port 5011" - gst-launch-1.0 -e \ - alsasrc device=hw:$RESPEAKER_CARD,0 do-timestamp=true ! \ - audio/x-raw,format=S16LE,rate=16000,channels=6 ! \ - audioconvert ! audioresample ! \ - audio/x-raw,rate=48000,channels=2 ! \ - opusenc bitrate=128000 ! \ - rtpopuspay pt=111 ! \ - udpsink host=127.0.0.1 port=5011 sync=false & -else - echo "No audio device found - video only" -fi - -# Wait for all background processes -wait + udpsink host=127.0.0.1 port=5010 sync=false \ No newline at end of file From 412f02d8ed9adc0bd8706e116cc40ef660a00475 Mon Sep 17 00:00:00 2001 From: Yanko Aleksandrov Date: Sat, 14 Jun 2025 14:57:59 +0300 Subject: [PATCH 4/5] update --- .../video_encoders/kill_old_gstreamers.sh | 67 --------------- installer/video_encoders/record_audio.sh | 85 ------------------- 2 files changed, 152 deletions(-) delete mode 100755 installer/video_encoders/kill_old_gstreamers.sh delete mode 100755 installer/video_encoders/record_audio.sh diff --git a/installer/video_encoders/kill_old_gstreamers.sh b/installer/video_encoders/kill_old_gstreamers.sh deleted file mode 100755 index 9048e1a..0000000 --- a/installer/video_encoders/kill_old_gstreamers.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -# Kill Old GStreamer Processes Script -# This script cleans up any running gst-launch processes that might be blocking audio/video devices - -echo "๐Ÿงน GStreamer Process Cleanup Script" -echo "====================================" - -# Function to cleanup old GStreamer processes -cleanup_old_processes() { - echo "๐Ÿ” Searching for running GStreamer processes..." - - # Find and display all gst-launch processes - PROCESS_LIST=$(ps aux | grep gst-launch | grep -v grep) - - if [ ! -z "$PROCESS_LIST" ]; then - echo "๐Ÿ“‹ Found running GStreamer processes:" - echo "$PROCESS_LIST" - echo "" - - # Extract PIDs - OLD_PIDS=$(echo "$PROCESS_LIST" | awk '{print $2}') - - echo "๐Ÿ”ซ Terminating processes (SIGTERM): $OLD_PIDS" - echo $OLD_PIDS | xargs kill 2>/dev/null - sleep 3 - - # Check if any processes are still running - REMAINING_LIST=$(ps aux | grep gst-launch | grep -v grep) - if [ ! -z "$REMAINING_LIST" ]; then - REMAINING_PIDS=$(echo "$REMAINING_LIST" | awk '{print $2}') - echo "๐Ÿ’€ Force killing remaining processes (SIGKILL): $REMAINING_PIDS" - echo $REMAINING_PIDS | xargs kill -9 2>/dev/null - sleep 1 - - # Final check - FINAL_CHECK=$(ps aux | grep gst-launch | grep -v grep) - if [ ! -z "$FINAL_CHECK" ]; then - echo "โŒ Warning: Some processes may still be running:" - echo "$FINAL_CHECK" - else - echo "โœ… All GStreamer processes successfully terminated" - fi - else - echo "โœ… All GStreamer processes successfully terminated" - fi - else - echo "โœ… No running GStreamer processes found" - fi - - echo "" - echo "๐ŸŽค Audio devices should now be available" - echo "๐Ÿ“น Video pipeline resources freed" -} - -# Run the cleanup -cleanup_old_processes - -# Optional: Show available audio devices -if command -v arecord &> /dev/null; then - echo "" - echo "๐ŸŽต Available audio capture devices:" - arecord -l | grep "card" | head -5 -fi - -echo "" -echo "Done! ๐ŸŽฌ" diff --git a/installer/video_encoders/record_audio.sh b/installer/video_encoders/record_audio.sh deleted file mode 100755 index f1d5ca6..0000000 --- a/installer/video_encoders/record_audio.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -# Simple audio recording script for testing ReSpeaker microphone -# Usage: ./record_audio.sh [duration_in_seconds] [output_filename] - -# Default values -DURATION=${1:-10} # Default 10 seconds -OUTPUT_FILE=${2:-"audio_test_$(date +%Y%m%d_%H%M%S).wav"} -DEVICE="respeaker" - -echo "๐ŸŽค Audio Recording Test Script" -echo "===============================" -echo "Device: $DEVICE" -echo "Duration: $DURATION seconds" -echo "Output file: $OUTPUT_FILE" -echo "" - -# Check if arecord is available -if ! command -v arecord &> /dev/null; then - echo "โŒ Error: arecord not found. Please install alsa-utils:" - echo " sudo apt-get install alsa-utils" - exit 1 -fi - -# List available audio devices -echo "๐Ÿ“‹ Available audio devices:" -arecord -l -echo "" - -# Try to find ReSpeaker device -echo "๐Ÿ” Looking for ReSpeaker device..." -CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') - -if [ -z "$CARD_NUMBER" ]; then - echo "โš ๏ธ Warning: No ReSpeaker device found in device list." - echo " Available devices:" - arecord -l | grep "card" - echo "" - echo " Please specify the correct card number manually or check device connection." - echo " You can also try running with a specific device:" - echo " arecord -D hw:CARD_NUMBER,0 -f S16_LE -r 16000 -c 6 -d $DURATION $OUTPUT_FILE" - exit 1 -else - echo "โœ… Found ReSpeaker at card $CARD_NUMBER" -fi - -# Record audio -echo "" -echo "๐Ÿ”ด Starting recording in 3 seconds..." -echo " Speak into your microphone to test it!" -sleep 1 -echo " 3..." -sleep 1 -echo " 2..." -sleep 1 -echo " 1..." -sleep 1 -echo " ๐ŸŽ™๏ธ RECORDING NOW! (${DURATION}s)" - -# Record with specific parameters for ReSpeaker -arecord -D hw:$CARD_NUMBER,0 \ - -f S16_LE \ - -r 16000 \ - -c 6 \ - -d $DURATION \ - "$OUTPUT_FILE" - -if [ $? -eq 0 ]; then - echo "" - echo "โœ… Recording completed successfully!" - echo " File: $OUTPUT_FILE" - echo " Size: $(ls -lh "$OUTPUT_FILE" | awk '{print $5}')" - echo "" - echo "๐Ÿ”Š To play back the recording:" - echo " aplay $OUTPUT_FILE" - echo "" - echo " Or with volume control:" - echo " aplay $OUTPUT_FILE || paplay $OUTPUT_FILE" -else - echo "" - echo "โŒ Recording failed. Please check:" - echo " 1. ReSpeaker device is connected" - echo " 2. Device permissions (try with sudo if needed)" - echo " 3. Audio drivers are installed" -fi From c3ed0d0d0f335b12344efa6c218f6667b44d810e Mon Sep 17 00:00:00 2001 From: Yanko Aleksandrov Date: Sat, 14 Jun 2025 15:56:05 +0300 Subject: [PATCH 5/5] fixed video storage service --- installer/sc.sh | 111 ++++++++++++++---- .../video_storage_encoder_with_audio.sh | 46 ++++---- 2 files changed, 114 insertions(+), 43 deletions(-) diff --git a/installer/sc.sh b/installer/sc.sh index cc2f9a5..2e1418e 100755 --- a/installer/sc.sh +++ b/installer/sc.sh @@ -1331,13 +1331,16 @@ EOF setup_video_storage_service() { check_root - SCRIPT_PATH="/home/skycore/video_storage.sh" + # Use the updated video_storage_encoder_with_audio.sh script + SOURCE_SCRIPT_PATH="$(dirname "$0")/video_encoders/video_storage_encoder_with_audio.sh" + SCRIPT_PATH="/home/skycore/video_storage_encoder_with_audio.sh" OUTPUT_DIR="${1:-/home/skycore/videos}" TARGET_IP="${2:-192.168.144.25}" - echo -e "${YELLOW}[โ‹ฏ]${NC} Setting up video storage service..." + echo -e "${YELLOW}[โ‹ฏ]${NC} Setting up video storage service with audio support..." echo -e "${YELLOW}[โ‹ฏ]${NC} Using RTSP source: rtsp://${TARGET_IP}:8554/main.264" echo -e "${YELLOW}[โ‹ฏ]${NC} Saving recordings to: ${OUTPUT_DIR}" + echo -e "${YELLOW}[โ‹ฏ]${NC} Audio support: Will receive audio from audio_encoder.sh via UDP port 5011" echo -e "${YELLOW}[โ‹ฏ]${NC} HLS segment duration (target-duration): 60 seconds" echo -e "${YELLOW}[โ‹ฏ]${NC} HLS playlist length (segments per playlist file): 60 segments" echo -e "${YELLOW}[โ‹ฏ]${NC} HLS max files on disk: Unlimited (max-files=0)" @@ -1347,8 +1350,8 @@ setup_video_storage_service() { mkdir -p "$OUTPUT_DIR" chown skycore:skycore "$OUTPUT_DIR" - # Create the video storage script file - echo -e "${YELLOW}[โ‹ฏ]${NC} Creating video storage script at $SCRIPT_PATH..." + # Create the enhanced video storage script with audio support + echo -e "${YELLOW}[โ‹ฏ]${NC} Creating enhanced video storage script at $SCRIPT_PATH..." cat > "$SCRIPT_PATH" << EOF #!/bin/bash @@ -1367,27 +1370,78 @@ log_message() { echo "\$1" } -log_message "Starting HLS recording with 60-minute playlist rotation" +# Function to check if audio encoder is running and providing audio stream +check_audio_encoder() { + # Check if audio_encoder.sh is running + if pgrep -f "audio_encoder.sh" > /dev/null; then + log_message "Audio encoder is running - will use UDP audio stream on port 5011" + return 0 + else + log_message "Warning: Audio encoder is not running. Audio will be disabled." + return 1 + fi +} + +log_message "Starting HLS recording with audio support and 60-minute playlist rotation" + +# Check for audio encoder availability +check_audio_encoder +AUDIO_AVAILABLE=\$? # Main recording loop - runs indefinitely while true; do - # Generate timestamp for this recording + # Generate timestamp for this hour's recording TIMESTAMP=\$(date +%Y%m%d_%H%M%S) log_message "Creating new playlist: \${TIMESTAMP}_playlist.m3u8" - # Run GStreamer for 60 minutes (3600 seconds) - timeout 3630 gst-launch-1.0 -e \\ - rtspsrc location=rtsp://${TARGET_IP}:8554/main.264 latency=50 drop-on-latency=true ! \\ - rtph264depay ! \\ - h264parse ! \\ - mpegtsmux ! \\ - hlssink playlist-root=file://\$OUTPUT_DIR \\ - target-duration=60 \\ - playlist-length=60 \\ - max-files=0 \\ - playlist-location="\$OUTPUT_DIR/\${TIMESTAMP}_playlist.m3u8" \\ - location="\$OUTPUT_DIR/\${TIMESTAMP}_segment_%05d.ts" + if [ \$AUDIO_AVAILABLE -eq 0 ]; then + log_message "Recording with audio from UDP stream (port 5011)" + # Enhanced pipeline with audio support (video + UDP audio stream) + # Try hardware encoding first, fallback to software if it fails + timeout 3630 gst-launch-1.0 -e \\ + mpegtsmux name=mux ! \\ + hlssink playlist-root=file://\$OUTPUT_DIR \\ + target-duration=60 playlist-length=60 max-files=0 \\ + playlist-location="\$OUTPUT_DIR/\${TIMESTAMP}_playlist.m3u8" \\ + location="\$OUTPUT_DIR/\${TIMESTAMP}_segment_%05d.ts" \\ + rtspsrc location=rtsp://${TARGET_IP}:8554/main.264 latency=50 drop-on-latency=true ! \\ + rtph264depay ! h264parse ! \\ + nvv4l2decoder enable-max-performance=1 disable-dpb=1 ! \\ + nvvidconv ! \\ + video/x-raw,format=I420 ! \\ + videorate max-rate=25 ! \\ + x264enc tune=zerolatency speed-preset=ultrafast bitrate=2500 key-int-max=15 bframes=0 ! \\ + h264parse config-interval=1 ! \\ + queue max-size-buffers=100 max-size-time=1000000000 ! \\ + mux. \\ + udpsrc port=5011 caps="application/x-rtp,media=audio,clock-rate=48000,encoding-name=OPUS,payload=111" ! \\ + rtpopusdepay ! opusdec ! \\ + audioconvert ! audioresample ! \\ + audio/x-raw,rate=48000,channels=2 ! \\ + queue max-size-buffers=200 max-size-time=2000000000 ! \\ + avenc_aac bitrate=128000 ! aacparse ! mux. + else + log_message "Recording video only (no audio device available)" + # Video-only pipeline using software encoding + timeout 3630 gst-launch-1.0 -e \\ + rtspsrc location=rtsp://${TARGET_IP}:8554/main.264 latency=50 drop-on-latency=true ! \\ + rtph264depay ! h264parse ! \\ + nvv4l2decoder enable-max-performance=1 disable-dpb=1 ! \\ + nvvidconv ! \\ + video/x-raw,format=I420 ! \\ + videorate max-rate=25 ! \\ + x264enc tune=zerolatency speed-preset=ultrafast bitrate=2500 key-int-max=15 bframes=0 ! \\ + h264parse config-interval=1 ! \\ + queue max-size-buffers=100 max-size-time=1000000000 ! \\ + mpegtsmux ! \\ + hlssink playlist-root=file://\$OUTPUT_DIR \\ + target-duration=60 \\ + playlist-length=60 \\ + max-files=0 \\ + playlist-location="\$OUTPUT_DIR/\${TIMESTAMP}_playlist.m3u8" \\ + location="\$OUTPUT_DIR/\${TIMESTAMP}_segment_%05d.ts" + fi # Check if gst-launch exited due to an error EXIT_CODE=\$? @@ -1396,7 +1450,11 @@ while true; do log_message "Error: gst-launch exited with code \$EXIT_CODE. Waiting 10 seconds before retry." sleep 10 else - log_message "60-minute recording completed successfully" + if [ \$AUDIO_AVAILABLE -eq 0 ]; then + log_message "60-minute recording with UDP audio completed successfully" + else + log_message "60-minute recording (video only) completed successfully" + fi # Small pause between recordings sleep 2 fi @@ -1414,8 +1472,10 @@ EOF cat > "$SERVICE_FILE" << EOF [Unit] -Description=SkyCore Video Storage Service -After=network.target +Description=SkyCore Video Storage Service with Audio Support +After=network.target sound.target +# Optional dependency on audio service - will start after audio if available +After=skycore-audio.service [Service] Type=simple @@ -1424,6 +1484,8 @@ Restart=on-failure RestartSec=10 User=skycore Group=skycore +# Add audio group for potential audio access +SupplementaryGroups=audio [Install] WantedBy=multi-user.target @@ -1452,10 +1514,17 @@ EOF echo -e "${GREEN}[โœ”]${NC} Video storage service has been set up and will run on boot" echo -e "${YELLOW}[โ‹ฏ]${NC} Recordings will be saved to: ${OUTPUT_DIR}" + echo -e "${YELLOW}[โ‹ฏ]${NC} Recording logs will be saved to: ${OUTPUT_DIR}/recording_log.txt" + echo -e "${YELLOW}[โ‹ฏ]${NC} Audio support: Start audio-service first for audio recording" echo -e "${YELLOW}[โ‹ฏ]${NC} You can control the service with:" echo -e " - systemctl start skycore-video-storage.service" echo -e " - systemctl stop skycore-video-storage.service" echo -e " - systemctl restart skycore-video-storage.service" + echo -e " - journalctl -u skycore-video-storage.service -f (view logs)" + + echo "" + echo -e "${YELLOW}[โ‹ฏ]${NC} For audio recording, also set up the audio service:" + echo -e " skycore audio-service" } # Function to set up audio streaming service diff --git a/installer/video_encoders/video_storage_encoder_with_audio.sh b/installer/video_encoders/video_storage_encoder_with_audio.sh index 8e6733d..4bc2a1c 100755 --- a/installer/video_encoders/video_storage_encoder_with_audio.sh +++ b/installer/video_encoders/video_storage_encoder_with_audio.sh @@ -14,23 +14,22 @@ log_message() { echo "$1" } -# Function to find ReSpeaker audio device -find_respeaker_device() { - CARD_NUMBER=$(arecord -l | grep -i respeaker | head -1 | sed 's/card \([0-9]\).*/\1/') - if [ -z "$CARD_NUMBER" ]; then - log_message "Warning: No ReSpeaker device found. Audio will be disabled." - return 1 - else - log_message "Found ReSpeaker at card $CARD_NUMBER" - echo $CARD_NUMBER +# Function to check if audio encoder is running and providing audio stream +check_audio_encoder() { + # Check if audio_encoder.sh is running + if pgrep -f "audio_encoder.sh" > /dev/null; then + log_message "Audio encoder is running - will use UDP audio stream on port 5011" return 0 + else + log_message "Warning: Audio encoder is not running. Audio will be disabled." + return 1 fi } log_message "Starting HLS recording with audio support and 60-minute playlist rotation" -# Check for ReSpeaker device -RESPEAKER_CARD=$(find_respeaker_device | tail -n 1) +# Check for audio encoder availability +check_audio_encoder AUDIO_AVAILABLE=$? # Main recording loop - runs indefinitely @@ -41,8 +40,9 @@ while true; do log_message "Creating new playlist: ${TIMESTAMP}_playlist.m3u8" if [ $AUDIO_AVAILABLE -eq 0 ]; then - log_message "Recording with audio from ReSpeaker (card $RESPEAKER_CARD)" - # Enhanced pipeline with audio support (video + microphone audio) + log_message "Recording with audio from UDP stream (port 5011)" + # Enhanced pipeline with audio support (video + UDP audio stream) + # Try hardware encoding first, fallback to software if it fails timeout 3630 gst-launch-1.0 -e \ mpegtsmux name=mux ! \ hlssink playlist-root=file://$OUTPUT_DIR \ @@ -53,27 +53,29 @@ while true; do rtph264depay ! h264parse ! \ nvv4l2decoder enable-max-performance=1 disable-dpb=1 ! \ nvvidconv ! \ - "video/x-raw(memory:NVMM),format=NV12" ! \ - nvv4l2h264enc profile=0 bitrate=15000000 iframeinterval=30 idrinterval=1 maxperf-enable=true poc-type=2 insert-sps-pps=true preset-level=0 ratecontrol-enable=1 quant-i-frames=20 quant-p-frames=23 quant-b-frames=25 ! \ + video/x-raw,format=I420 ! \ + videorate max-rate=25 ! \ + x264enc tune=zerolatency speed-preset=ultrafast bitrate=2500 key-int-max=15 bframes=0 ! \ h264parse config-interval=1 ! \ queue max-size-buffers=100 max-size-time=1000000000 ! \ mux. \ - alsasrc device=hw:$RESPEAKER_CARD,0 ! \ - audio/x-raw,format=S16LE,rate=16000,channels=6 ! \ + udpsrc port=5011 caps="application/x-rtp,media=audio,clock-rate=48000,encoding-name=OPUS,payload=111" ! \ + rtpopusdepay ! opusdec ! \ audioconvert ! audioresample ! \ audio/x-raw,rate=48000,channels=2 ! \ queue max-size-buffers=200 max-size-time=2000000000 ! \ avenc_aac bitrate=128000 ! aacparse ! mux. else log_message "Recording video only (no audio device available)" - # Original pipeline without audio + # Video-only pipeline using software encoding timeout 3630 gst-launch-1.0 -e \ rtspsrc location=rtsp://192.168.144.25:8554/main.264 latency=50 drop-on-latency=true ! \ rtph264depay ! h264parse ! \ nvv4l2decoder enable-max-performance=1 disable-dpb=1 ! \ nvvidconv ! \ - "video/x-raw(memory:NVMM),format=NV12" ! \ - nvv4l2h264enc profile=0 bitrate=15000000 iframeinterval=30 idrinterval=1 maxperf-enable=true poc-type=2 insert-sps-pps=true preset-level=0 ratecontrol-enable=1 quant-i-frames=20 quant-p-frames=23 quant-b-frames=25 ! \ + video/x-raw,format=I420 ! \ + videorate max-rate=25 ! \ + x264enc tune=zerolatency speed-preset=ultrafast bitrate=2500 key-int-max=15 bframes=0 ! \ h264parse config-interval=1 ! \ queue max-size-buffers=100 max-size-time=1000000000 ! \ mpegtsmux ! \ @@ -93,11 +95,11 @@ while true; do sleep 10 else if [ $AUDIO_AVAILABLE -eq 0 ]; then - log_message "60-minute recording with audio completed successfully" + log_message "60-minute recording with UDP audio completed successfully" else log_message "60-minute recording (video only) completed successfully" fi # Small pause between recordings sleep 2 fi -done \ No newline at end of file +done