21

How do I change it?

I'm looking for something like:

SetMasterVolume(0.5) SetAppVolume('FooBar',0.5) 

I tried using ctypes.windll.winmm, but I can't find much documentation on how to use it.

Thanks in advance.

1
  • 1
    Also sorry to one man this all, but changing the app volume depends on the library you are using, if you are using pygame it is pygame.mixer.music.set_volume(value) Commented Dec 30, 2013 at 1:36

12 Answers 12

47

I'd hope after 5 years this is no longer a problem for you, but I've just had to do the same thing. It's possible using the PyCaw library.

Simple proof of concept, based on PyCaw's examples

from __future__ import print_function from pycaw.pycaw import AudioUtilities, ISimpleAudioVolume def main(): sessions = AudioUtilities.GetAllSessions() for session in sessions: volume = session._ctl.QueryInterface(ISimpleAudioVolume) if session.Process and session.Process.name() == "vlc.exe": print("volume.GetMasterVolume(): %s" % volume.GetMasterVolume()) volume.SetMasterVolume(0.6, None) if __name__ == "__main__": main() 
Sign up to request clarification or add additional context in comments.

4 Comments

Even 3 years after your "new" answer this question is actual. Voted up for this and the example as well
Works for all Operating Systems?
github.com/AndreMiras/pycaw/blob/develop/examples/… referenced example, in case it ever changes
It worked well for me. All you need to change is if session.Process and ... to if session.Process is not None and ...
10

this is a very roundabout way to do it but it works.you can simulate the key presses for the computers master volume with pynput. it works but it is quite inacurate.

from pynput.keyboard import Key,Controller keyboard = Controller() import time while True: for i in range(10): keyboard.press(Key.media_volume_up) keyboard.release(Key.media_volume_up) time.sleep(0.1) for i in range(10): keyboard.press(Key.media_volume_down) keyboard.release(Key.media_volume_down) time.sleep(0.1) time.sleep(2) 

this is an ok method of doing it. every keypress and release is equal to about 2 volume . hope this is somewhat helpful!

1 Comment

btw i know this works on windows i dont know about linux or mac though
3

I know this is too late but if someone is still looking for a seamless solution

Download this exe application from here

and just call this command using python

./SoundVolumeView.exe /SetVolume "High Definition Audio Device\Device\Speakers" 50 

2 Comments

love it. open the program manually, right click on desired device and click properties. "Command-line friendly ID" contains the name to provide as argument
But it's pre-compiled.
3

I ripped this from here and modified it to use functions only.

import time import ctypes # Import the SendInput object SendInput = ctypes.windll.user32.SendInput # C struct redefinitions PUL = ctypes.POINTER(ctypes.c_ulong) class KeyBoardInput(ctypes.Structure): _fields_ = [ ("wVk", ctypes.c_ushort), ("wScan", ctypes.c_ushort), ("dwFlags", ctypes.c_ulong), ("time", ctypes.c_ulong), ("dwExtraInfo", PUL) ] class HardwareInput(ctypes.Structure): _fields_ = [ ("uMsg", ctypes.c_ulong), ("wParamL", ctypes.c_short), ("wParamH", ctypes.c_ushort) ] class MouseInput(ctypes.Structure): _fields_ = [ ("dx", ctypes.c_long), ("dy", ctypes.c_long), ("mouseData", ctypes.c_ulong), ("dwFlags", ctypes.c_ulong), ("time",ctypes.c_ulong), ("dwExtraInfo", PUL) ] class Input_I(ctypes.Union): _fields_ = [ ("ki", KeyBoardInput), ("mi", MouseInput), ("hi", HardwareInput) ] class Input(ctypes.Structure): _fields_ = [ ("type", ctypes.c_ulong), ("ii", Input_I) ] VK_VOLUME_MUTE = 0xAD VK_VOLUME_DOWN = 0xAE VK_VOLUME_UP = 0xAF def key_down(keyCode): extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBoardInput(keyCode, 0x48, 0, 0, ctypes.pointer(extra)) x = Input( ctypes.c_ulong(1), ii_ ) SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) def key_up(keyCode): extra = ctypes.c_ulong(0) ii_ = Input_I() ii_.ki = KeyBoardInput(keyCode, 0x48, 0x0002, 0, ctypes.pointer(extra)) x = Input(ctypes.c_ulong(1), ii_) SendInput(1, ctypes.pointer(x), ctypes.sizeof(x)) def key(key_code, length = 0): key_down(key_code) time.sleep(length) key_up(key_code) def volume_up(): key(VK_VOLUME_UP) def volume_down(): key(VK_VOLUME_DOWN) def set_volume(int): for _ in range(0, 50): volume_down() for _ in range(int / 2): volume_up() 

1 Comment

This is a viable workaround for the EventGhost issue where the volume stops working in Win10 after installation of LAV filters.
2
from ctypes import cast, POINTER from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume devices = AudioUtilities.GetSpeakers() interface = devices.Activate( IAudioEndpointVolume._iid_, CLSCTX_ALL, None) volume = cast(interface, POINTER(IAudioEndpointVolume)) # Control volume #volume.SetMasterVolumeLevel(-0.0, None) #max #volume.SetMasterVolumeLevel(-5.0, None) #72% volume.SetMasterVolumeLevel(-10.0, None) #51% 

Comments

0

So instead of editing my old answer I'm adding a new post to allow others who use self to use my old code and anyone who's not, to use my new code.

def get_master_volume(): proc = subprocess.Popen('/usr/bin/amixer sget Master', shell=True, stdout=subprocess.PIPE) amixer_stdout = proc.communicate()[0].split('\n')[4] proc.wait() find_start = amixer_stdout.find('[') + 1 find_end = amixer_stdout.find('%]', find_start) return float(amixer_stdout[find_start:find_end]) def set_master_volume(volume): val = float(int(volume)) proc = subprocess.Popen('/usr/bin/amixer sset Master ' + str(val) + '%', shell=True, stdout=subprocess.PIPE) proc.wait() 

3 Comments

Thanks again for the reply. I'm still getting 'The system cannot find the path specified.'
@f.rodrigues, this does not work on windows. the path /usr is only on unix-based systems
The question is about windows. Your answer is only for unix based systems, it does not answer the question.
0

You can use pyautogui:

import pyautogui pyautogui.FAILSAFE = False x = 1 while x < 10: pyautogui.press('volumedown') x+=1 

1 Comment

Nice solution! to mute one can use pyautogui.press('volumemute')
0
import pyautogui x = 50 a = (x//2) pyautogui.press('volumeup',a) #this code will increase computer master volume by even numbers 

1 Comment

Nice solution! to mute one can use pyautogui.press('volumemute')
0

you can set the number of presses in pyautogui and create to an even output

e.g. 43 input = 42 output

imports used:

import pyautogui as p import math, time from tkinter import simpledialog 

using tkinter askdialog to get an input

volume = simpledialog.askinteger("new volume", "what would you like the volume to be?") 

and setting the volume

def set_vol(new_volume): p.press('volumedown', presses = 50) #sets volume to zero time.sleep(0.5) #using time.sleep to space the presses x = math.floor(new_volume / 2) #setting the amount of presses required p.press('volumeup', presses = x) #setting volume 

running the definition

set_vol(volume) 

2 Comments

Welcome to Stack Overflow @Ethan. I am curious to why you would want to divide the new_volume with two, and why you need the sleep?
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
0

I figured out a way to set the master volume using numpy, while still using Pycaw.

from ctypes import cast, POINTER from comtypes import CLSCTX_ALL from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume import numpy as np 

Get the audio output device

devices = AudioUtilities.GetSpeakers() interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None) volume = cast(interface, POINTER(IAudioEndpointVolume)) 

Set the desired volume in percentage (0 to 100)

desired_vol = 50 

Get the volume range (min and max values in dB)

vol_range = volume.GetVolumeRange() min_vol = vol_range[0] max_vol = vol_range[1] 

Convert the desired volume percentage to volume level in dB

desired_vol_db = np.interp(desired_vol, [0, 100], [min_vol, max_vol]) volume.SetMasterVolumeLevelScalar(desired_vol / 100, None) 

Print the current volume percentage

curr_vol = int(volume.GetMasterVolumeLevelScalar() * 100) print(f'Volume set to: {int(curr_vol)} %') 

Comments

0

One liner using helper function

If not installed, run: pip install pynput

""" You must set n to the volume levels your computer has. x: volume in percent, 0 min, 1 max """ def set_volume(x): n = 100 # volume levels your computer has keyboard = Controller() pause = 0.0001 desired_level = int(x*n) # go to 0 first since we dont know the current volume level press_count = int(n/2) for _ in range(press_count): keyboard.press(Key.media_volume_down) keyboard.release(Key.media_volume_down) time.sleep(pause) press_count = int(desired_level/2) for _ in range(press_count): keyboard.press(Key.media_volume_up) keyboard.release(Key.media_volume_up) time.sleep(pause) 

Example: set_volume(0.5)

Comments

-1

First import subprocess import subprocess

Then to get the master volume

def get_master_volume(self): proc = subprocess.Popen('/usr/bin/amixer sget Master', shell=True, stdout=subprocess.PIPE) amixer_stdout = proc.communicate()[0].split('\n')[4] proc.wait() find_start = amixer_stdout.find('[') + 1 find_end = amixer_stdout.find('%]', find_start) return float(amixer_stdout[find_start:find_end]) 

And to set the Master volume

def set_master_volume(self, widget): val = self.volume val = float(int(val)) proc = subprocess.Popen('/usr/bin/amixer sset Master ' + str(val) + '%', shell=True, stdout=subprocess.PIPE) proc.wait() 

3 Comments

Thanks for the reply. If I try 'set_master_volume(0.5,'foobar2000')' I get: AttributeError: 'float' object has no attribute 'volume' If I chance val to 0.5 I get: 'The system cannot find the path specified.' I guess I need to get the application correct address, but I don't know how to do it.
I see no reason to set the volume to .5% as you might be able to see it will set the master volume to a percentage so say you want to change the volume to 50% self.volume needs to equal 50.0 so just by calling val = float(int(val)) It will set 50 to an integer if its something like 50.1 and then changes it to a float of 50.0
This is a Linux answer. How does it apply to MS-Windows? The question specifies Windows.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.