[Unit] Description=ESP32 Serial Audio to PulseAudio After=pulseaudio.service Requires=pulseaudio.service # Tie service start to the device node so it won’t launch until udev creates it Requires=dev-ttyESP32_A.device After=dev-ttyESP32_A.device [Service] # Ensure PulseAudio runtime dir is set so pactl can connect Environment=XDG_RUNTIME_DIR=/run/user/%U Environment=LANG=en_US.UTF-8 WorkingDirectory=/home/littlesophia/serial_audio_catcher # Wait until PulseAudio socket and serial device exist ExecStartPre=/bin/sh -c 'until [ -S "$XDG_RUNTIME_DIR/pulse/native" ] && [ -e /dev/ttyESP32_A ]; do sleep 2; done' # Create the null sink before starting the pipeline ExecStartPre=/usr/bin/pactl unload-module module-null-sink ExecStartPre=/usr/bin/pactl load-module module-null-sink sink_name=esp32 rate=16000 channels=2 format=s16le # Run the pipeline through a shell so the pipe is interpreted correctly ExecStart=/bin/sh -c '/home/littlesophia/serial_audio_catcher/serial_to_stdout /dev/ttyESP32_A | /usr/bin/pacat --raw --rate=16000 --channels=2 --format=s16le --device=esp32' # Restart automatically if it crashes or exits Restart=always RestartSec=5 # Log output to journal StandardOutput=journal StandardError=journal [Install] WantedBy=default.target