Как отключить приостановку аудиовыхода в режиме ожидания с помощью WirePlumber в Fedora 35, чтобы аудио не задерживалось при начале воспроизведения?

Вопрос или проблема

В Fedora 35 WirePlumber заменил pipewire-media-session в качестве менеджера аудиосессий. Существует крайне неприятная проблема с аудио на многих встроенных звуковых картах на Linux, когда аудио-выход приостанавливается после того, как ничего не воспроизводится в течение 3 секунд. При возобновлении воспроизведения после 3 секунд задержка аудио или возникают щелчки. Как мы можем исправить это поведение по умолчанию?

Соответствующий конфигурационный файл — /usr/share/wireplumber/main.lua.d/50-alsa-config.lua, но не редактируйте системную версию!

Вам нужно скопировать его в /etc/wireplumber/main.lua.d/ (глобальная конфигурация) или ~/.config/wireplumber/main.lua.d/ (конфигурация пользователя) и внести необходимые изменения.

Самый простой способ — скопировать его в место глобальной конфигурации, чтобы это касалось всех пользовательских аккаунтов:

sudo cp -a /usr/share/wireplumber/main.lua.d/50-alsa-config.lua /etc/wireplumber/main.lua.d/50-alsa-config.lua
sudo nano /etc/wireplumber/main.lua.d/50-alsa-config.lua

Затем вам нужно прокрутить вниз до конца файла, внутри раздела apply_properties, и добавить там строку:

["session.suspend-timeout-seconds"] = 0

Я сделал намного больше изменений и настроил его под собственное оборудование. Вот моя конфигурация для справки, но эта конфигурация полезна только для моих устройств. Вам действительно нужна только строка выше, чтобы отключить автоматическую приостановку. Добавьте ее в свою собственную конфигурацию по умолчанию. Не копируйте мою конфигурацию. Остальные изменения не имеют отношения.

alsa_monitor.properties = {
  ["alsa.jack-device"] = true,
  ["alsa.reserve"] = true,
  ["alsa.midi.monitoring"] = true
}

alsa_monitor.rules = {
{
    matches = {
      {
        { "device.name", "matches", "alsa_card.*" }
      }
    },
    apply_properties = {
      ["api.alsa.use-acp"] = true,
      ["api.acp.auto-profile"] = false,
      ["api.acp.auto-port"] = false
    }
  },
  {
    matches = {
      {
        { "node.name", "matches", "alsa_output.pci-0000_0c_00.4.iec958-ac3-surround-51" }
      }
    },
    apply_properties = {
      ["api.alsa.period-size"] = 128,
      ["api.alsa.headroom"] = 2048,
      ["session.suspend-timeout-seconds"] = 0
    }
  },
  { 
    matches = {
      {
        { "node.name", "matches", "alsa_input.usb-BEHRINGER_UMC202HD_192k-00.analog-mono" }
      }
    },
    apply_properties = {
      ["api.alsa.period-size"] = 128
    }
  }
}

Установка свойства session.suspend-timeout-seconds в 0 предотвращает поведение приостановки/сна. Оно полностью отключает это поведение, как можно видеть в исходном коде WirePlumber.

WirePlumber необходимо перезапустить, чтобы изменения вступили в силу:

systemctl --user restart wireplumber

Это обычно исправляется в системах, работающих на PipeWire без WirePlumber, которые используют pipewire-media-session, изменением session.suspend-timeout-seconds на 0 в нижней части /etc/pipewire/media-session.d/alsa-monitor.conf. Однако этот каталог и любой конфигурационный файл мониторинга сессий не находятся в установках Fedora 35. Практически нет документации, показывающей, как предотвратить приостановку выходов через 3 секунды, поэтому мне пришлось разобраться с этим самостоятельно. Вместо этого нам нужно изменить Lua-скрипт в каталоге скриптов для WirePlumber. Перейдите в /usr/share/wireplumber/scripts/ и сделайте резервную копию suspend-node.lua. Затем откройте suspend-node.lua в текстовом редакторе или в терминале с правами sudo, и закомментируйте блок кода, отвечающий за предел времени ожидания и приостановку выходов, чтобы файл выглядел следующим образом:

-- WirePlumber
--
-- Copyright © 2021 Collabora Ltd.
--    @author George Kiagiadakis <[email protected]>
--
-- SPDX-License-Identifier: MIT

om = ObjectManager {
  Interest { type = "node",
    Constraint { "media.class", "matches", "Audio/*" }
  },
  Interest { type = "node",
    Constraint { "media.class", "matches", "Video/*" }
  },
}

sources = {}

om:connect("object-added", function (om, node)
  node:connect("state-changed", function (node, old_state, cur_state)
    -- Всегда очищать текущий источник, если он есть
    local id = node["bound-id"]
    if sources[id] then
      sources[id]:destroy()
      sources[id] = nil
    end

--    -- Добавьте источник времени ожидания, если бездействие длится как минимум 3 секунды
--    if cur_state == "idle" then
--      -- соблюдайте "session.suspend-timeout-seconds", если указано
--      local timeout =
--          tonumber(node.properties["session.suspend-timeout-seconds"]) or 3

--      if timeout == 0 then
--        return
--      end

--      -- добавьте время ожидания бездействия; умножьте на 1000, timeout_add() ожидает мс
--      sources[id] = Core.timeout_add(timeout * 1000, function()
--        -- Приостановить узел
--        Log.info(node, "был бездействующем некоторое время; приостановка ...")
--        node:send_command("Suspend")

--        -- Удалите ссылку на источник
--        sources[id] = nil

--        -- false (== G_SOURCE_REMOVE) уничтожает источник так, что эта
--        -- функция не срабатывает снова спустя 3 секунды
--        return false
--      end)
--    end

  end)
end)

om:activate()

Может есть и лучший способ сделать это, чем закомментировать целый блок, но, по крайней мере, таким образом время обработки не теряется на проверку состояния выхода на бездействие. Теперь нет неприятной задержки аудио или щелчков при возобновлении воспроизведения музыки и видео после того, как выход был в состоянии бездействия в течение нескольких секунд. Я надеюсь, это поможет тем, кто использует WirePlumber на Fedora 35.

Я потратил много времени на поиск в Google и выполнение описанных здесь действий.

Я просто оставлю весь алгоритм здесь (работает как часы на Ubuntu 23.04)

  1. Переместите конфигурации в глобальную область и измените их параметр session.suspend-timeout-seconds:

    # Основная конфигурация
     sudo mkdir -p /etc/wireplumber/main.lua.d
     sudo cp -a /usr/share/wireplumber/main.lua.d/50-alsa-config.lua /etc/wireplumber/main.lua.d/50-alsa-config.lua
    
     # Конфигурация Bluetooth
     sudo mkdir -p /etc/wireplumber/bluetooth.lua.d/
     sudo cp -a /usr/share/wireplumber/bluetooth.lua.d/50-bluez-config.lua /etc/wireplumber/bluetooth.lua.d/50-bluez-config.lua
    
     # Измените нужные настройки в обоих конфигурационных файлах
     # Обратите внимание на `--` в начале. Это комментарий к строке в Lua. И мы должны удалить его
     sudo sed -i 's/--\["session.suspend-timeout-seconds"\] = 5/\["session.suspend-timeout-seconds"\] = 0/g' /etc/wireplumber/main.lua.d/50-alsa-config.lua
     sudo sed -i 's/--\["session.suspend-timeout-seconds"\] = 5/\["session.suspend-timeout-seconds"\] = 0/g' /etc/wireplumber/bluetooth.lua.d/50-bluez-config.lua
    
  2. Затем перезагрузите службы:

    systemctl --user restart pipewire wireplumber
    
  3. Теперь вы можете протестировать состояние всех ваших аудио устройств с помощью этой команды, воспроизводя и останавливая аудио, а затем наблюдая за изменением состояния:

    watch -cd -n .1 pactl list short sinks
    

    Это показывает статусы:

    • RUNNING — устройство в настоящее время воспроизводит или прошло менее 10 секунд после предыдущего воспроизведения
    • IDLE — устройство не воспроизводит, но готово воспроизвести немедленно (это необходимо!)
    • SUSPEND — в этом состоянии устройство проснется с задержкой (это НЕ нужно)

    Больше не должно быть статусов SUSPENDED после первого воспроизведения в сессии.

Поздравляю! Теперь ваш аудио будет воспроизводиться без пауз.

Вместо того чтобы дублировать существующий (и довольно длинный) файл 50-alsa-config.lua, я предлагаю создать файл значительно короче.

Вот мой ~/.config/wireplumber/main.lua.d/51-alsa-custom.lua:

rule = {
  matches = {
    {
      { "node.nick", "matches", "ALC887-VD Analog" },
    },
  },
  apply_properties = {
      ["session.suspend-timeout-seconds"] = 0
  },
}
table.insert(alsa_monitor.rules,rule)

Я получил node.nick с помощью следующей команды:

$ pactl list sinks |grep node.nick
                node.nick = "ALC887-VD Analog"

После этого вам все равно нужно перезапустить службу:

systemctl --user restart wireplumber

Соответствующий конфигурационный файл — /usr/share/wireplumber/main.lua.d/50-alsa-config.lua, но не редактируйте системную версию.

Это решение не работает для устройств Bluetooth. Чтобы оно работало, скопируйте файл Bluetooth и измените свойство session.suspend-timeout-seconds.

sudo cp -a /usr/share/wireplumber/bluetooth.lua.d/50-bluez-config.lua /etc/wireplumber/bluetooth.lua.d/50-bluez-config.lua

sudo vi /etc/wireplumber/bluetooth.lua.d/50-bluez-config.lua

50-bluez-config.lua:

apply_properties = {
  --["node.nick"] = "My Node",
  --["priority.driver"] = 100,
  --["priority.session"] = 100,
  --["node.pause-on-idle"] = false,
  --["resample.quality"] = 4,
  --["channelmix.normalize"] = false,
  --["channelmix.mix-lfe"] = false,
  ["session.suspend-timeout-seconds"] = 0,  -- 0 отключает приостановку
  --["monitor.channel-volumes"] = false,

  -- Роль медиапотока, "input" или "playback"
  -- По умолчанию "playback", воспроизведение потока на динамики
  -- Установите на "input", чтобы использовать в качестве входа для приложений
  --["bluez5.media-source-role"] = "input",
},

Создайте файл ~/.config/wireplumber/main.lua.d/51-disable-suspension.lua
и вставьте это в него:

table.insert (alsa_monitor.rules, {
  matches = {
    {
      -- Совпадает со всеми источниками.
      { "node.name", "matches", "alsa_input.*" },
    },
    {
      -- Совпадает со всеми выходами.
      { "node.name", "matches", "alsa_output.*" },
    },
  },
  apply_properties = {
    ["session.suspend-timeout-seconds"] = 0,  -- 0 отключает приостановку
  },
})

Затем перезапустите WirePlumber:

systemctl --user restart wireplumber

Источник: https://wiki.archlinux.org/title/PipeWire#Noticeable_audio_delay_or_audible_pop/crack_when_starting_playback

Обновление для Ubuntu 24.10

Грязный, но быстрый трюк:

sudo sed -i 's/\["session.suspend-timeout-seconds"\]) or 5/\["session.suspend-timeout-seconds"\]) or 0/g' /usr/share/wireplumber/scripts/node/suspend-node.lua 

systemctl --user restart pipewire wireplumber

Ответ или решение

Чтобы отключить автоматическую приостановку аудиовыхода в WirePlumber на Fedora 35 и избежать задержек при запуске воспроизведения, выполните следующие шаги. Важно помнить, что WirePlumber заменил pipewire-media-session в данной версии, и настройка поведения управления аудиосессией теперь осуществляется через файлы конфигурации на Lua.

1. Копирование конфигурационного файла

Сначала вам необходимо скопировать файл конфигурации, который управляет поведением аудиосистемы. Изменения нужно вносить в локальную или глобальную версию конфигурации, а не в файлы в директории /usr/share.

Откройте терминал и выполните следующие команды для создания глобальной конфигурации:

sudo mkdir -p /etc/wireplumber/main.lua.d/
sudo cp -a /usr/share/wireplumber/main.lua.d/50-alsa-config.lua /etc/wireplumber/main.lua.d/50-alsa-config.lua

2. Редактирование конфигурационного файла

Откройте скопированный файл для редактирования:

sudo nano /etc/wireplumber/main.lua.d/50-alsa-config.lua

Прокрутите вниз до секции apply_properties и добавьте следующую строку:

["session.suspend-timeout-seconds"] = 0

Это изменение блокирует автоматическую приостановку при бездействии, так что аудиовыход больше не будет переходить в режим ожидания после 3 секунд тишины.

3. Перезапуск WirePlumber

После внесения изменений в конфигурацию, чтобы они вступили в силу, вам нужно перезапустить WirePlumber. Введите в терминале:

systemctl --user restart wireplumber

4. Проверка состояния аудиоустройств

Для проверки статуса ваших аудиоустройств и убедитесь, что они больше не переходят в состояние "SUSPENDED", используйте следующую команду:

watch -cd -n .1 pactl list short sinks

Наблюдайте за состояниями:

  • RUNNING – устройство активно воспроизводит звук.
  • IDLE – устройство не воспроизводит звук, но готово к быстрому запуску.
  • SUSPEND – устройство приостановлено, что нежелательно для вас.

Дополнительные рекомендации

Если у вас есть Bluetooth-устройства, аналогичные изменения следует внести в файл конфигурации:

sudo cp -a /usr/share/wireplumber/bluetooth.lua.d/50-bluez-config.lua /etc/wireplumber/bluetooth.lua.d/50-bluez-config.lua

Затем редактируйте также свой 50-bluez-config.lua, добавив:

["session.suspend-timeout-seconds"] = 0

Заключение

Следуя вышеописанным шагам, вы успешно отключите автоматическую приостановку аудиовыхода на вашей системе Fedore 35 с WirePlumber, что позволяет избежать задержек и пиков в звуке при запуске воспроизведения. Эти изменения могут значительно улучшить ваш опыт работы с мультимедийным контентом на Linux.

Оцените материал
Добавить комментарий

Капча загружается...