Skip to content

Instantly share code, notes, and snippets.

@git58
Created February 2, 2026 08:46
Show Gist options
  • Select an option

  • Save git58/5a4d922401e50b09fe3fc1fa42d7ec1b to your computer and use it in GitHub Desktop.

Select an option

Save git58/5a4d922401e50b09fe3fc1fa42d7ec1b to your computer and use it in GitHub Desktop.
Switch to analog audio if no sound in system
#!/bin/bash
###############################################################################
# MiniJack Hardware-Level Audio Watchdog with Recovery Attempts
# -------------------------------------------------------------
# This script monitors the ALSA hardware output (minijack) and attempts to
# restore audio up to 3 times if silence is detected while applications are
# playing sound. If all 3 recovery attempts fail, a KDE Plasma notification
# is shown to the user.
###############################################################################
HW_SINK="alsa_output.pci-0000_00_1f.3.analog-stereo"
MAX_ATTEMPTS=3
ATTEMPT_COUNT=0
check_signal_level() {
LEVEL=$(pw-dump | jq -r \
".[] | select(.info.props.\"node.name\"==\"$HW_SINK\") | .info.props.\"audio.level\"" \
2>/dev/null)
if [ -z "$LEVEL" ] || [ "$LEVEL" == "null" ]; then
LEVEL=0.0
fi
echo "$LEVEL"
}
attempt_recovery() {
# Force hardware sink as default
pactl set-default-sink "$HW_SINK"
# Unmute and set safe volume
pactl set-sink-mute "$HW_SINK" 0
pactl set-sink-volume "$HW_SINK" 80%
# Move all active audio streams to hardware sink
for INPUT in $(pactl list short sink-inputs | awk '{print $1}'); do
pactl move-sink-input "$INPUT" "$HW_SINK"
done
sleep 1
}
while true; do
# 1. Check if any audio is playing
if ! pactl list sink-inputs | grep -q "Sink Input"; then
ATTEMPT_COUNT=0
sleep 2
continue
fi
# 2. Read signal level
LEVEL=$(check_signal_level)
# 3. If silence detected, try recovery
if (( $(echo "$LEVEL < 0.0001" | bc -l) )); then
ATTEMPT_COUNT=$((ATTEMPT_COUNT+1))
attempt_recovery
# Re-check signal after recovery attempt
LEVEL=$(check_signal_level)
if (( $(echo "$LEVEL >= 0.0001" | bc -l) )); then
ATTEMPT_COUNT=0
fi
else
ATTEMPT_COUNT=0
fi
# 4. If 3 failed attempts → notify user
if [ "$ATTEMPT_COUNT" -ge "$MAX_ATTEMPTS" ]; then
kdialog --passivepopup "Звук упал, выключите и включите компьютер заново" 5000
ATTEMPT_COUNT=0
fi
sleep 2
done
@git58
Copy link
Author

git58 commented Feb 2, 2026

Changelog for v1.0 (Initial release)

MiniJack Hardware‑Level Audio Watchdog with Recovery Attempts — Документация

Общее описание

Этот скрипт представляет собой сторожевой механизм аппаратного уровня, предназначенный для контроля фактического аудиовыхода через ALSA‑устройство (обычно миниджек встроенной звуковой карты).

Его задача — обнаруживать ситуации, когда:

  • приложения воспроизводят звук,
  • но физический аудиовыход остаётся полностью тихим,
  • что указывает на сбой в PipeWire, PulseAudio‑совместимости или аудиопайплайне.

Скрипт не просто фиксирует проблему, а предпринимает до трёх попыток восстановить звук.
Если все попытки оказываются безуспешными, он уведомляет пользователя через KDE Plasma.


Назначение

Скрипт полезен в системах, где:

  • PipeWire периодически нарушает маршрутизацию,
  • виртуальные sinks (например, ViperFX) могут зависать,
  • аудиопотоки остаются активными, но звук не доходит до миниджека,
  • требуется автоматический контроль и попытки восстановления.

Он работает полностью автономно и не зависит от других скриптов.


Основные функции

1. Контроль активности аудиопотоков

Скрипт проверяет наличие активных аудиопотоков через:

pactl list sink-inputs

Если аудио не воспроизводится, скрипт:

  • сбрасывает счётчик попыток,
  • делает паузу,
  • продолжает мониторинг.

Это предотвращает ложные срабатывания, когда пользователь просто ничего не слушает.


2. Измерение уровня сигнала ALSA‑устройства

Скрипт получает фактический уровень PCM‑сигнала через PipeWire:

pw-dump | jq ...

Он извлекает параметр:

"audio.level"

Если значение отсутствует или равно null, оно считается равным 0.0.

Это позволяет определить, что физический выход молчит, даже если граф PipeWire выглядит корректным.


3. Обнаружение тишины и запуск попыток восстановления

Если уровень сигнала ниже порога 0.0001, скрипт считает это тишиной.

При каждой такой проверке:

  • увеличивается счётчик попыток,
  • выполняется функция восстановления attempt_recovery().

Если после восстановления уровень сигнала стал ненулевым — счётчик сбрасывается.


4. Попытка восстановления звука

Функция attempt_recovery() выполняет:

  1. Принудительное назначение ALSA‑устройства как default‑sink.
  2. Снятие mute и установка безопасной громкости (80%).
  3. Перемещение всех активных аудиопотоков на аппаратный sink.
  4. Короткую паузу для обновления состояния PipeWire.

Это мягкая попытка вернуть звук без перезапуска сервисов.


5. Уведомление пользователя после трёх неудачных попыток

Если три последовательные попытки восстановления не помогли:

  • выводится уведомление KDE Plasma:
"Звук упал, выключите и включите компьютер заново"
  • счётчик попыток сбрасывается,
  • мониторинг продолжается.

Скрипт не перезапускает PipeWire и не вмешивается в другие процессы — он только предупреждает пользователя.


Параметры конфигурации

Имя аппаратного sink

HW_SINK="alsa_output.pci-0000_00_1f.3.analog-stereo"

При необходимости можно заменить на другое устройство.


Количество попыток восстановления

MAX_ATTEMPTS=3

После трёх неудачных попыток выводится уведомление.


Интервал проверки

Скрипт делает паузу:

sleep 2

То есть проверка выполняется каждые 2 секунды.


Поведение скрипта

Состояние Действие
Нет аудиопотоков Сброс счётчика, ожидание
Есть аудиопотоки + есть сигнал Сброс счётчика
Есть аудиопотоки + тишина Попытка восстановления
1–2 неудачные попытки Продолжение попыток
3 неудачные попытки Уведомление KDE Plasma
После уведомления Сброс счётчика, мониторинг продолжается

Преимущества

  • ✔ Полностью автономен
  • ✔ Не зависит от ViperFX или других скриптов
  • ✔ Работает на уровне ALSA, а не PipeWire‑графа
  • ✔ Мягко пытается восстановить звук
  • ✔ Не ломает маршрутизацию
  • ✔ Уведомляет пользователя только при реальной проблеме

@git58
Copy link
Author

git58 commented Feb 2, 2026

Данный скрипт пока не тестировал

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment