История простая: после очередного обновления Windows 10 у меня начали странно работать мультимедийные клавиши. Привязка к текущему приложению иногда теряется и работать вообще перестает. Плюс ещё бесило стандартное всплывающее окно управления музыкой — оно висит вечность и закрыть его нельзя.

В какой‑то момент я понял, что терпеть это уже не хочется, и пошёл разбираться, как всё починить.


Почему всё сломалось

После обновления Windows система начала периодически терять активное медиа‑приложение. Проще говоря — Windows иногда просто не понимает, какое приложение сейчас должно получать команды «пауза», «следующий трек» и т.д.

Первая попытка — PowerToys

Сначала я попробовал пойти по простому пути и использовать Microsoft PowerToys — переназначал горячие клавиши, экспериментировал с биндингами. Но быстро стало понятно, что это не решает корневую проблему. Если Windows теряет активное медиа‑приложение, то никакие красивые биндинги не спасают.

Поэтому пришлось идти дальше и брать более гибкий инструмент — AutoHotkey.


Эксперименты с AutoHotkey

Попытка №1 — просто отправлять медиа‑кнопки

Самый очевидный вариант — просто пересылать мультимедийные команды:

Media_Play_Pause::Send, {Media_Play_Pause}
Media_Next::Send, {Media_Next}
Media_Prev::Send, {Media_Prev}

Но из‑за той же самой проблемы с «потерей активного плеера» это работало нестабильно: иногда команда проходила, иногда — нет.


Попытка №2 — побороть зависающее системное окно

Меня ещё раздражало, что при переключении трека появляется системное окно (Media OSD), которое долго висит на экране. Я попробовал хитрость — дополнительно дергать громкость, чтобы окно быстрее закрывалось:

Media_Next::
    Send {Volume_Up}
    Send {Volume_Down}
return

Работает… но костыльно. Понятно что фокус всё теряется.


Попытка №3 — свои комбинации клавиш

Дальше я решил повесить управление музыкой на собственные сочетания, например Ctrl + Alt + стрелки:

^!Right::
    ControlSend,, {Media_Next}
return

^!Left::
    ControlSend,, {Media_Prev}
return

Стало удобнее переключаться, но двигаемся дальше.


Попытка №4 — жёстко управлять фокусом окна

В какой‑то момент стало понятно: надо не надеяться на Windows, а самому управлять окном Яндекс Музыки.

Логика такая:

  1. Найти окно Яндекс Музыки.

  2. Активировать его.

  3. Отправить нужную клавишу (в настройках приложения можно найти список горячих клавиш).

  4. Свернуть обратно.

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

PlayPause:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
        Sleep, 200
        Send, k  ; Play/Pause в Яндекс Музыке
        WinMinimize
    }
return

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


Неожиданная проблема — раскладка клавиатуры

Когда всё вроде бы заработало, всплыла новая проблема: при русской раскладке буквы (k, n, p) отправлялись неправильно.

Решение простое — отправлять не буквы, а скан‑коды клавиш:

Send, {sc019} ; вместо буквы P

После этого раскладка вообще перестала иметь значение.


А что насчёт RDP?

Естественно, мне захотелось, чтобы всё это работало и когда я нахожусь в RDP. Тут я потратил кучу времени: пробовал разные программы, советы ИИ, хаки — но почти всё упиралось в ограничения самого RDP. Он очень агрессивно перехватывает ввод.

В итоге стало понятно: чисто программно эту задачу нормально не решить.

Поспрашивал ИИ, сначала он мне предложили купить отдельный USB‑нумпад. Но почти все такие устройства — это просто цифры от 0 до 9. Для управления музыкой это неудобно.

И тут я вспомнил, что у меня валяется джойстик от PS5. Подключил его — Windows увидела его сразу, AutoHotkey тоже без проблем начал ловить кнопки.

Клавиши ловил через вот этот небольшой скрипт:

#NoEnv
#SingleInstance Force

; Тест всех кнопок геймпада
SetTimer, ShowJoystick, 100
return

ShowJoystick:
    ; Проверяем все кнопки
    buttons := ""
    Loop, 32
    {
        if GetKeyState("Joy" . A_Index)
            buttons .= A_Index . " "
    }
    
    ; Проверяем D-Pad (POV)
    pov := GetKeyState("JoyPOV")
    
    ; Проверяем стики
    x := GetKeyState("JoyX")
    y := GetKeyState("JoyY")
    z := GetKeyState("JoyZ")
    r := GetKeyState("JoyR")
    
    ; Показываем всё
    ToolTip, Button: %buttons%`nPOV (D-Pad): %pov%`nleft stick X/Y: %x% / %y%`nrighr stick Z/R: %z% / %r%, 0, 0
return

Esc::ExitApp  ; Закрыть по Esc

Назначил кнопки:

Joy1::Gosub, PrevTrack      ; предыдущий трек
Joy3::Gosub, NextTrack      ; следующий трек
Joy14::Gosub, PlayPause     ; пауза / воспроизведение
Joy13::Gosub, ActivateMusic ; активировать яндекс музыку, если нет окна, то запустить

И внезапно это оказалось максимально удобным решением. Работает стабильно, в том числе и если находимся в RDP.


Управление громкостью и дополнительные бонусы

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

Joy4:: Send {Volume_Up}
Joy2:: Send {Volume_Down}

Но в RDP такие команды улетают в удалённую машину. Поэтому я переделал это на прямое управление системной громкостью:

Joy4:: SoundSet +1
Joy2:: SoundSet -1

А потом сделал приятный бонус — чтобы при удержании кнопки громкость плавно менялась:

Joy4::
    while GetKeyState("Joy4", "P")
    {
        SoundSet +1
        Sleep 50
    }
return

Добавил установку лайков и дизлайков

Подумал и на клавиши вверх и вниз добавил лайки и дизлайки. Тут все немного посложнее, но ИИ как обычно справился.

CheckPOV:
  POV := GetKeyState("JoyPOV")

  if (POV = 0 && !POVPressed)  ; Вверх - лайк
  {
      POVPressed := true
      Gosub, LikeTrack
  }
  else if (POV = 18000 && !POVPressed)  ; Вниз - дизлайк
  {
      POVPressed := true
      Gosub, DislikeTrack
  }
  else if (POV = -1)  ; Отпущен
      POVPressed := false
return

Что получилось в итоге

В результате у меня получилось:

  • стабильное управление музыкой;

  • не зависит от раскладки клавиатуры;

  • работает даже когда находимся в окне RDP;

  • нет раздражающего системного окна;

  • удобное управление с отдельного устройства;

  • установка лайков и дизлайков;

  • плавная регулировка громкости.

Бонусом оказалось то, что джойстики стоят недорого, легко подключаются к Windows и имеют много удобных кнопок разной формы — их легко запомнить на ощупь. В этом плане они даже удобнее нумпадов и клавиатур.

Если у вас потребность в дополнительных клавишах для любой вашей программы, можете также купить джойстик и модифицировать мой скрипт ?

Итоговый скрипт

Запускать его надо на AHK 1.1, скачать можно тут: https://www.autohotkey.com/

#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
#SingleInstance Force

if not A_IsAdmin   ; К сожалению зачем то нужны права админа, без них Яндекс Музыка не вызывается
{
    Run *RunAs "%A_ScriptFullPath%"
    ExitApp
}

; === Проверка D-Pad ===
SetTimer, CheckPOV, 100 ; запускаем таймер
return

CheckPOV:
    POV := GetKeyState("JoyPOV")
    
    if (POV = 0 && !POVPressed)  ; Вверх - лайк
    {
        POVPressed := true
        Gosub, LikeTrack
    }
    else if (POV = 18000 && !POVPressed)  ; Вниз - дизлайк
    {
        POVPressed := true
        Gosub, DislikeTrack
    }
    else if (POV = -1)  ; Отпущен
        POVPressed := false
return

Media_Play_Pause::Gosub, PlayPause

; === Кнопки PS5 ===
Joy1::Gosub, PrevTrack      ; Квадрат (□) - предыдущий
Joy3::Gosub, NextTrack      ; Круг (○) - следующий
Joy14::Gosub, PlayPause     ; Тачпад - воспроизведение\пауза
Joy13::Gosub, ActivateMusic ; PS - активировать яндекс музыку

; === Процедуры ===
Joy4:: ; Треугольник (△) - громче
    while GetKeyState("Joy4", "P")
    {
        SoundSet +1
        Sleep 50
    }
return

Joy2:: ; Крест (✕) - тише
    while GetKeyState("Joy2", "P")
    {
        SoundSet -1
        Sleep 50
    }
return

PlayPause:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
        Sleep, 200
        Send, {sc025}; k
        WinMinimize
    }
return

NextTrack:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
        Sleep, 200
        Send, {sc031}; n
        WinMinimize
    }
return

PrevTrack:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
        Sleep, 200
        Send, {sc019}; p
        WinMinimize
    }
return

LikeTrack:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
        Sleep, 200
        Send, {sc021}; f
        WinMinimize
    }
return

DislikeTrack:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
        Sleep, 200
        Send, {sc020}; d
        WinMinimize
    }
return

ActivateMusic:
    if WinExist("ahk_exe Яндекс Музыка.exe")
    {
        WinActivate
    }
    else
    {
        Run, %LOCALAPPDATA%\Programs\YandexMusic\Яндекс Музыка.exe
    }
return

Комментарии (6)


  1. itshnick88
    15.01.2026 23:33

    И тут я вспомнил, что у меня валяется джойстик от PS5.

    ; Тест всех кнопок геймпада SetTimer, ShowJoystick, 100 return


    Так для джойстика или геймпада??) На фотке геймпад


    1. Mirzapch
      15.01.2026 23:33

      Да.

      Вы один из немногих, кто понимает разницу.


  1. CitizenOfDreams
    15.01.2026 23:33

    Ну вы еще обсудите разницу между "батарейкой" и "элементом", которую тоже мало кто понимает.

    А по теме - под эту задачу скорее заточен не Autohotkey с геймпадом, а Girder с LIRC и пультом от какого-нибудь музцентра.


  1. Garik_takse
    15.01.2026 23:33

    Тоже заметил что перестают работать команды управления с наушников через 5-10 мин.(пауза, вперед, назад). (v5.79.7 Windows11_25h2). Удалил приложение Yandex Music, перезагрузился, скачал заново - установил, обновил до актуальной. Клавиши управления мультимедиа и команды с наушников перестали отваливаться. Уже месяц полет нормальный.


    1. vladnet1 Автор
      15.01.2026 23:33

      А если находишься в rdp так работает? Или для вас не актуально?


      1. Garik_takse
        15.01.2026 23:33

        На RDP не использовал, не было необходимости.