精确控制windows全局音量(Python)
话不多说,直接上代码:
1 import ctypes,time 2 import comtypes 3 from ctypes import wintypes 4 5 MMDeviceApiLib = comtypes.GUID( 6 \'{2FDAAFA3-7523-4F66-9957-9D5E7FE698F6}\') 7 IID_IMMDevice = comtypes.GUID( 8 \'{D666063F-1587-4E43-81F1-B948E807363F}\') 9 IID_IMMDeviceCollection = comtypes.GUID( 10 \'{0BD7A1BE-7A1A-44DB-8397-CC5392387B5E}\') 11 IID_IMMDeviceEnumerator = comtypes.GUID( 12 \'{A95664D2-9614-4F35-A746-DE8DB63617E6}\') 13 IID_IAudioEndpointVolume = comtypes.GUID( 14 \'{5CDF2C82-841E-4546-9722-0CF74078229A}\') 15 CLSID_MMDeviceEnumerator = comtypes.GUID( 16 \'{BCDE0395-E52F-467C-8E3D-C4579291692E}\') 17 18 # EDataFlow 19 eRender = 0 # audio rendering stream 20 eCapture = 1 # audio capture stream 21 eAll = 2 # audio rendering or capture stream 22 23 # ERole 24 eConsole = 0 # games, system sounds, and voice commands 25 eMultimedia = 1 # music, movies, narration 26 eCommunications = 2 # voice communications 27 28 LPCGUID = REFIID = ctypes.POINTER(comtypes.GUID) 29 LPFLOAT = ctypes.POINTER(ctypes.c_float) 30 LPDWORD = ctypes.POINTER(wintypes.DWORD) 31 LPUINT = ctypes.POINTER(wintypes.UINT) 32 LPBOOL = ctypes.POINTER(wintypes.BOOL) 33 PIUnknown = ctypes.POINTER(comtypes.IUnknown) 34 35 class IMMDevice(comtypes.IUnknown): 36 _iid_ = IID_IMMDevice 37 _methods_ = ( 38 comtypes.COMMETHOD([], ctypes.HRESULT, \'Activate\', 39 ([\'in\'], REFIID, \'iid\'), 40 ([\'in\'], wintypes.DWORD, \'dwClsCtx\'), 41 ([\'in\'], LPDWORD, \'pActivationParams\', None), 42 ([\'out\',\'retval\'], ctypes.POINTER(PIUnknown), \'ppInterface\')), 43 comtypes.STDMETHOD(ctypes.HRESULT, \'OpenPropertyStore\', []), 44 comtypes.STDMETHOD(ctypes.HRESULT, \'GetId\', []), 45 comtypes.STDMETHOD(ctypes.HRESULT, \'GetState\', [])) 46 47 PIMMDevice = ctypes.POINTER(IMMDevice) 48 49 class IMMDeviceCollection(comtypes.IUnknown): 50 _iid_ = IID_IMMDeviceCollection 51 52 PIMMDeviceCollection = ctypes.POINTER(IMMDeviceCollection) 53 54 class IMMDeviceEnumerator(comtypes.IUnknown): 55 _iid_ = IID_IMMDeviceEnumerator 56 _methods_ = ( 57 comtypes.COMMETHOD([], ctypes.HRESULT, \'EnumAudioEndpoints\', 58 ([\'in\'], wintypes.DWORD, \'dataFlow\'), 59 ([\'in\'], wintypes.DWORD, \'dwStateMask\'), 60 ([\'out\',\'retval\'], ctypes.POINTER(PIMMDeviceCollection), 61 \'ppDevices\')), 62 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetDefaultAudioEndpoint\', 63 ([\'in\'], wintypes.DWORD, \'dataFlow\'), 64 ([\'in\'], wintypes.DWORD, \'role\'), 65 ([\'out\',\'retval\'], ctypes.POINTER(PIMMDevice), \'ppDevices\'))) 66 @classmethod 67 def get_default(cls, dataFlow, role): 68 enumerator = comtypes.CoCreateInstance( 69 CLSID_MMDeviceEnumerator, cls, comtypes.CLSCTX_INPROC_SERVER) 70 return enumerator.GetDefaultAudioEndpoint(dataFlow, role) 71 72 class IAudioEndpointVolume(comtypes.IUnknown): 73 _iid_ = IID_IAudioEndpointVolume 74 _methods_ = ( 75 comtypes.STDMETHOD(ctypes.HRESULT, \'RegisterControlChangeNotify\', []), 76 comtypes.STDMETHOD(ctypes.HRESULT, \'UnregisterControlChangeNotify\', []), 77 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetChannelCount\', 78 ([\'out\', \'retval\'], LPUINT, \'pnChannelCount\')), 79 comtypes.COMMETHOD([], ctypes.HRESULT, \'SetMasterVolumeLevel\', 80 ([\'in\'], ctypes.c_float, \'fLevelDB\'), 81 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 82 comtypes.COMMETHOD([], ctypes.HRESULT, \'SetMasterVolumeLevelScalar\', 83 ([\'in\'], ctypes.c_float, \'fLevel\'), 84 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 85 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetMasterVolumeLevel\', 86 ([\'out\',\'retval\'], LPFLOAT, \'pfLevelDB\')), 87 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetMasterVolumeLevelScalar\', 88 ([\'out\',\'retval\'], LPFLOAT, \'pfLevel\')), 89 comtypes.COMMETHOD([], ctypes.HRESULT, \'SetChannelVolumeLevel\', 90 ([\'in\'], wintypes.UINT, \'nChannel\'), 91 ([\'in\'], ctypes.c_float, \'fLevelDB\'), 92 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 93 comtypes.COMMETHOD([], ctypes.HRESULT, \'SetChannelVolumeLevelScalar\', 94 ([\'in\'], wintypes.UINT, \'nChannel\'), 95 ([\'in\'], ctypes.c_float, \'fLevel\'), 96 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 97 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetChannelVolumeLevel\', 98 ([\'in\'], wintypes.UINT, \'nChannel\'), 99 ([\'out\',\'retval\'], LPFLOAT, \'pfLevelDB\')), 100 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetChannelVolumeLevelScalar\', 101 ([\'in\'], wintypes.UINT, \'nChannel\'), 102 ([\'out\',\'retval\'], LPFLOAT, \'pfLevel\')), 103 comtypes.COMMETHOD([], ctypes.HRESULT, \'SetMute\', 104 ([\'in\'], wintypes.BOOL, \'bMute\'), 105 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 106 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetMute\', 107 ([\'out\',\'retval\'], LPBOOL, \'pbMute\')), 108 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetVolumeStepInfo\', 109 ([\'out\',\'retval\'], LPUINT, \'pnStep\'), 110 ([\'out\',\'retval\'], LPUINT, \'pnStepCount\')), 111 comtypes.COMMETHOD([], ctypes.HRESULT, \'VolumeStepUp\', 112 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 113 comtypes.COMMETHOD([], ctypes.HRESULT, \'VolumeStepDown\', 114 ([\'in\'], LPCGUID, \'pguidEventContext\', None)), 115 comtypes.COMMETHOD([], ctypes.HRESULT, \'QueryHardwareSupport\', 116 ([\'out\',\'retval\'], LPDWORD, \'pdwHardwareSupportMask\')), 117 comtypes.COMMETHOD([], ctypes.HRESULT, \'GetVolumeRange\', 118 ([\'out\',\'retval\'], LPFLOAT, \'pfLevelMinDB\'), 119 ([\'out\',\'retval\'], LPFLOAT, \'pfLevelMaxDB\'), 120 ([\'out\',\'retval\'], LPFLOAT, \'pfVolumeIncrementDB\'))) 121 @classmethod 122 def get_default(cls): 123 endpoint = IMMDeviceEnumerator.get_default(eRender, eMultimedia) 124 interface = endpoint.Activate(cls._iid_, comtypes.CLSCTX_INPROC_SERVER) 125 return ctypes.cast(interface, ctypes.POINTER(cls)) 126 127 128 129 130 131 if __name__ == \'__main__\': 132 133 def show_vol(ev): 134 time.sleep(2) 135 voldb = ev.GetMasterVolumeLevel() 136 volsc = ev.GetMasterVolumeLevelScalar() 137 volst, nstep = ev.GetVolumeStepInfo() 138 print(\'Master Volume (dB): %0.4f\' % voldb) 139 print(\'Master Volume (scalar): %0.4f\' % volsc)#当前音量 140 print(\'Master Volume (step): %d / %d\' % (volst, nstep)) 141 142 def test(): 143 ev = IAudioEndpointVolume.get_default() 144 vol = ev.GetMasterVolumeLevelScalar() 145 vmin, vmax, vinc = ev.GetVolumeRange() 146 print(\'Volume Range (min, max, step) (dB): \' 147 \'%0.4f, %0.4f, %0.4f\' % (vmin, vmax, vinc)) 148 show_vol(ev) 149 try: 150 print(\'\nIncrement the master volume\') 151 ev.VolumeStepUp()#音量加 152 show_vol(ev) 153 print(\'\nDecrement the master volume twice\') 154 ev.VolumeStepDown()#音量减 155 ev.VolumeStepDown() 156 show_vol(ev) 157 print(\'\nSet the master volume to 0.75 scalar\') 158 ev.SetMasterVolumeLevelScalar(0.75)#音量百分比设置 159 show_vol(ev) 160 print(\'\nSet the master volume to 0.25 scalar\') 161 ev.SetMasterVolumeLevelScalar(0.25)#音量百分比设置 162 show_vol(ev) 163 finally: 164 ev.SetMasterVolumeLevelScalar(vol) 165 166 comtypes.CoInitialize() 167 try: 168 test() 169 finally: 170 comtypes.CoUninitialize()
简单逻辑就是先获取ev对象(
ev = IAudioEndpointVolume.get_default()
)
然后有几个方法:
方法一(获取当前音量):(
volsc = ev.GetMasterVolumeLevelScalar()
)
方法二(音量加/减):(
ev.VolumeStepUp()#音量加
ev.VolumeStepDown()#音量减
)
方法三(设置音量):(
ev.SetMasterVolumeLevelScalar(0.75)#音量百分比设置
)
另附简单调用win32API加减音量:
import ctypes,operator WM_APPCOMMAND = 0x319 APPCOMMAND_VOLUME_UP = 0x0a APPCOMMAND_VOLUME_DOWN = 0x09 APPCOMMAND_VOLUME_MUTE = 0x08 def setSpeakerVol(volume): hwnd = ctypes.windll.user32.GetForegroundWindow() # ctypes.windll.winmm.waveOutSetVolume(hwnd, 0xffffffff) print(hwnd) ctypes.windll.user32.PostMessageA(hwnd, WM_APPCOMMAND, 0, APPCOMMAND_VOLUME_DOWN * 0x10000) # if __name__ == \'__main__\': setSpeakerVol(0)
利用:
PostMessageA
版权声明:本文为wohuiyijiu原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。