🇬🇧 English version: README.md
Измерьте колонки/комнату в REW (или возьмите целевую кривую для наушников из AutoEQ) и примените результат как параметрический эквалайзер на каждое устройство вывода прямо внутри PipeWire с помощью per-device-eq.py.
per-device-eq записывает эквалайзер как in-node filter-graph прямо в реальный sink — без отдельного виртуального sink и без лишнего узла в графе — и ставит небольшой хук WirePlumber, который заново применяет настройку каждый раз, когда устройство начинает играть. Коррекция живёт внутри самого WirePlumber, поэтому переживает перезагрузку, переподключение и реконнект Bluetooth без единого вашего фонового процесса: ничего не нужно держать в автозапуске и ничего не нужно держать открытым.
- На каждое устройство вывода. Свой эквалайзер у каждого sink — встроенные колонки, HDMI, конкретная Bluetooth-гарнитура (по MAC).
- Профили многократного использования. Эквалайзер — это профиль, который можно переключать, дублировать, переименовывать и удалять.
Clean (no EQ)— это плоско; устройство без профиля = Clean. - Прямой импорт REW/AutoEQ. Загружает текст, который экспортирует REW (и AutoEQ
ParametricEQ.txt), как есть — без скрипта-конвертера. - Вживую и постоянно. Правки применяются мгновенно и автосохраняются; хук WirePlumber восстанавливает их при каждом воспроизведении.
- Интерактивный редактор. Перетаскивание полос по графику АЧХ, поканальный эквалайзер, преамп, bypass для A/B и Undo/Redo (
Ctrl+Z/Ctrl+Shift+Z).
EasyEffects — хорошая штука, но он не подошёл под то, как я реально пользуюсь машиной, — отсюда и этот инструмент. Конкретно:
- Не хранит настройки в разрезе устройств вывода. Я хочу, чтобы у каждого sink — колонки, эта Bluetooth-гарнитура, та — автоматически была своя коррекция. EasyEffects не мыслит в терминах sink-ов.
- Требует, чтобы он сам был запущен. Коррекция существует только пока работает процесс EasyEffects, значит его надо держать в автозапуске и открытым.
per-device-eqкладёт эквалайзер внутрь WirePlumber — со стороны пользователя не работает ничего. - Ломает прозрачность «выбрал sink — и он играет». Когда переключаешь вывод в окружении рабочего стола и звук идёт за ним, EasyEffects за ним не следует — нужный sink приходится искать и выбирать внутри самого EasyEffects. Здесь эквалайзер привязан к sink, поэтому следует за звуком сам.
- Не работает с DAW. Профессиональные аудиоприложения, которые обращаются к устройствам напрямую, обходят sink EasyEffects. In-node-граф на реальном устройстве применяется в любом случае.
per-device-eq свободен от всех четырёх — и, что важнее всего, делает ровно то, ради чего он есть: правильный звук.
PipeWire ≥ 1.6 (нужен in-node audioconvert.filter-graph), WirePlumber, GTK 4, PyGObject, PyCairo, Python 3. В работе приложение также вызывает утилиты командной строки PipeWire pw-metadata и pw-dump; если какого-то из них нет, оно сообщит об этом при запуске.
sudo dnf copr enable mikhail/per-device-eq
sudo dnf install per-device-eqСтавит лаунчер per-device-eq, хук WirePlumber (в /usr/share/per-device-eq/) и ярлык с иконкой. Запускайте из меню приложений как Per-Device EQ или командой per-device-eq. При первом запуске приложение копирует свой хук WirePlumber в пользовательскую сессию и один раз перезапускает WirePlumber; после этого EQ восстанавливается автоматически при каждой перезагрузке и переподключении.
Чтобы запускать скрипт напрямую, без пакета:
# Fedora; в других дистрибутивах те же утилиты называются иначе:
sudo dnf install gtk4 python3-gobject python3-cairo pipewire pipewire-utils wireplumber
git clone https://github.com/NTMan/calibrate-room-rew.git
cd calibrate-room-rew
chmod +x per-device-eq.py
./per-device-eq.pyЧтобы при запуске из исходников получить ещё и пункт меню/дока с иконкой, поставьте desktop-интеграцию в домашний каталог (обратимо, пишет только в ~/.local/share):
./per-device-eq.py --install-desktop # добавить .desktop и иконку
./per-device-eq.py --uninstall-desktop # удалить их обратноЕсли установлен пакет из COPR, это не нужно — системный ярлык уже есть, и приложение не трогает ~/.local/share.
В репозитории есть per-device-eq.spec. Локальная сборка на Fedora:
sudo dnf install rpm-build rpmdevtools desktop-file-utils libappstream-glib
rpmdev-setuptree
git archive --format=tar.gz --prefix=calibrate-room-rew-1.0.0/ \
-o ~/rpmbuild/SOURCES/calibrate-room-rew-1.0.0.tar.gz v1.0.0
rpmbuild -ba per-device-eq.specГотовый per-device-eq-*.noarch.rpm появится в ~/rpmbuild/RPMS/noarch/.
В планах. Flatpak'у нужно «прокинуть» хук WirePlumber из песочницы наружу, что требует дополнительной возни; пока на Fedora самый простой путь — COPR.
Встроенный профиль Clean приложение генерирует само — файл не нужен. Дополнительные общесистемные профили можно положить в /usr/share/per-device-eq/profiles/.
Корректируете наушники или IEM, а не комнату? Пропустите часть A: возьмите параметрический эквалайзер из AutoEQ (или https://autoeq.app) и используйте его экспорт ParametricEQ в части B.
- Скачайте REW (Room EQ Wizard) с официального сайта: https://www.roomeqwizard.com/.
- Лучше с встроенной Java — со свежей системной Java REW может работать неправильно.
- Подключите измерительный микрофон UMIK-1 к USB.
- Скачайте файл калибровки с сайта miniDSP: https://www.minidsp.com/products/acoustic-measurement/umik-1
- Выберите файл
7163423_90deg.txt, если измеряете колонки под углом 90° (по горизонтали). - REW не распознаёт параметр
Sens Factor, но поддерживает строкуSensitivity: -18.3 dB. - Добавьте строку
Sensitivity: -18.3 dBв начало файла7163423_90deg.txtвручную. - Полностью удалите строку
Sens Factor, иначе REW может не распознать файл.
- Выберите файл
wpctl set-volume @DEFAULT_AUDIO_SOURCE@ 0.9
wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.5- Откройте REW.
- Перейдите в меню Preferences → Cal files.
- В блоке Mic cal files:
- Убедитесь, что активный вход (например,
Default Device Default Input) выбран. - Нажмите на шестерёнку справа от строки и убедитесь, что флажок
Input device is a C weighted SPL meterснят — для калиброванных микрофонов он должен быть выключен. - Укажите полный путь к файлу
7163423_90deg.txt.
- Убедитесь, что активный вход (например,
- Перейдите на вкладку Measure.
- Нажмите Check Levels — уровень должен быть в пределах −12…−6 dBFS.
- Нажмите Start Measuring.
- После замера откройте вкладку EQ.
- Задайте тип устройства (обычно Full range speaker).
- Нажмите Match Response to Target.
- Экспортируйте через Export filter settings as text и сохраните файл.
Этот текстовый файл вы и импортируете в части B — конвертация не нужна.
./per-device-eq.pyПри первом запуске оно само ставит свой хук WirePlumber и один раз перезапускает WirePlumber, чтобы его активировать, — вручную запускать ничего не нужно. (Для headless-сценария это можно сделать и без GUI: ./per-device-eq.py --install-hook.)
Используйте выпадающий список Device. ★ отмечает текущее устройство по умолчанию; переключатель Follow default автоматически выбирает то, что играет.
Нажмите Import REW/AutoEQ… и выберите текстовый файл из части A (или AutoEQ ParametricEQ.txt для наушников). Фильтры загрузятся, коррекция зазвучит сразу, профиль создастся и привяжется к этому устройству и сохранится автоматически.
🎉 Готово. Эквалайзер заново применяется при каждой перезагрузке / переподключении — отдельного шага «сохранить» нет.
- Панель профилей (справа): переключение профиля, привязанного к текущему устройству; New, Duplicate, Rename, Delete. Выберите Clean (no EQ), чтобы убрать коррекцию.
- Bypass для сравнения A/B с некорректированным звуком (только рантайм, не сохраняется).
- Undo / Redo (
Ctrl+Z/Ctrl+Shift+Zили кнопки ↶ ↷) — на случай случайной правки. - Ручная подстройка: перетащите точку на графике, чтобы сдвинуть полосу, клик по пустому месту — добавить, правый клик — удалить; либо правьте Type/Freq/Gain/Q в таблице. Прокрутка колесом над таблицей прокручивает список (значения не меняет).
- Поканальный эквалайзер: снимите галку Apply to all channels, чтобы править FL/FR раздельно.
./per-device-eq.py --list # список sink-ов (по умолчанию помечен *)
./per-device-eq.py --list-profiles # профили и их привязки к устройствам
./per-device-eq.py --inspect NAME # дамп параметров sink (node.name)
./per-device-eq.py --apply # применить привязанные профили сейчас
./per-device-eq.py --install-hook # (пере)установить хук WirePlumber + конфиг| Путь | Что |
|---|---|
~/.config/per-device-eq/profiles/*.json |
ваши профили |
~/.config/per-device-eq/bindings.json |
привязка устройство (node.name) → профиль |
~/.local/share/wireplumber/scripts/90-per-device-eq.lua |
хук персистентности (статичный скрипт, ставится из репозитория как есть) |
~/.local/state/wireplumber/per-device-eq |
сохранённые хуком графы (пишет хук; восстанавливаются при старте) |
~/.config/wireplumber/wireplumber.conf.d/90-per-device-eq.conf |
загружает хук и создаёт metadata-объект per-device-eq |
profiles/clean.json, /usr/share/per-device-eq/profiles/ |
встроенные / системные профили |
- Падение громкости после включения EQ (PipeWire). На некоторых sink-ах с аппаратной громкостью первое изменение громкости после того, как in-node EQ уже активен, может обрушить реальный уровень вывода (хотя отображаемая громкость выглядит правильной) — до перезапуска PipeWire/WirePlumber. Отслеживается в апстриме: https://gitlab.freedesktop.org/pipewire/pipewire/-/work_items/5344. Обходной путь: выставляйте громкость до включения EQ либо
systemctl --user restart wireplumber.
Если вы по какой-то причине всё ещё пользуетесь EasyEffects, в репозитории остаётся старый конвертер rew2easyeffects.py: вставьте в него текст из REW, чтобы получить конфигурацию для EasyEffects. Во всех остальных случаях проект рекомендует per-device-eq (см. Почему это, а не EasyEffects выше).
