我尝试制作一个可以分割音频的程序,我面临的问题之一是如何更改一个特定应用程序的音频输出。 opera
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
from comtypes import CLSCTX_ALL
import psutil
def change_audio_output(device_name):
prog_name = i_name
devices = AudioUtilities.GetAllDevices()
device = next((d for d in devices if d.FriendlyName == device_name), None)
if not device:
print(f"Device '{device_name}' not found.")
return
print(f"Selected device: {device.FriendlyName}")
sessions = AudioUtilities.GetAllSessions()
session_found = False
for session in sessions:
process = session.Process
if process and process.name().lower() == f'{prog_name}.exe'.lower():
print(f"Found session for '{prog_name}.exe'")
volume = session._ctl.QueryInterface(IAudioEndpointVolume)
volume.SetMasterVolumeLevelScalar(0.5, None)
session_found = True
break
if not session_found:
print(f"No session found for '{prog_name}.exe'")
i_name = input('Prog: ').strip()
change_audio_output("CABLE Input (VB-Audio Virtual Cable)")
回溯(最近一次调用): 文件“D:\Users\Angel\PycharmProjects\audio_projects\change_out.py”,第 36 行,位于 change_audio_output("电缆输入(VB-音频虚拟电缆)") 文件“D:\Users\Angel\PycharmProjects\audio_projects\change_out.py”,第 25 行,change_audio_output 音量 = session._ctl.QueryInterface(IAudioEndpointVolume) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 文件“D:\Users\Angel\PycharmProjects\audio_projects.venv\Lib\site-packages\comtypes_post_coinit\unknwn.py”,第 520 行,在 QueryInterface 中 self.__com_QueryInterface(byref(iid), byref(p)) # 类型:忽略 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ctypes.COMError:(-2147467262,'不支持此类接口',(无,无,无,0,无))
错误提示“不支持此类接口”表示你尝试获取音频会话的音量控制接口(
IAudioEndpointVolume
),但该会话不支持该接口。这很可能是因为你正在尝试访问浏览器(例如 Opera)的主音频会话,而浏览器通常会为其内部处理的不同音频流(例如标签页、插件)创建多个音频会话。
为了解决这个问题,你需要枚举Opera创建的音频会话并找到你想要控制的特定会话。你可以通过检查每个会话的属性(例如会话名称或关联的进程ID)来实现。
以下是如何修改你的代码以实现此目的的方法:
import psutil
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume, ISimpleAudioVolume
from comtypes import CLSCTX_ALL
def change_audio_output(device_name, prog_name):
devices = AudioUtilities.GetAllDevices()
device = next((d for d in devices if d.FriendlyName == device_name), None)
if not device:
print(f"找不到设备 '{device_name}'。")
return
print(f"所选设备:{device.FriendlyName}")
sessions = AudioUtilities.GetAllSessions()
for session in sessions:
process = session.Process
if process and prog_name.lower() in process.name().lower():
print(f"找到 '{prog_name}' 的会话")
# 尝试获取 IAudioEndpointVolume 接口
volume = session._ctl.QueryInterface(IAudioEndpointVolume, False)
if volume:
volume.SetMasterVolumeLevelScalar(0.5, None)
print(f"已更改 '{prog_name}' 的音量")
return
# 如果 IAudioEndpointVolume 不可用,请尝试 ISimpleAudioVolume
volume = session._ctl.QueryInterface(ISimpleAudioVolume, False)
if volume:
volume.SetMasterVolume(0.5, None)
print(f"已更改 '{prog_name}' 的音量")
return
print(f"无法控制 '{prog_name}' 会话的音量")
print(f"找不到 '{prog_name}' 的会话")
if __name__ == "__main__":
prog_name = input('程序:').strip()
change_audio_output("电缆输入(VB-音频虚拟电缆)", prog_name)
这段代码做了以下几件事:
- 枚举所有音频会话,并检查每个会话的进程名称是否包含目标程序名称。 这将有助于定位Opera创建的正确音频会话。
-
尝试首先获取
IAudioEndpointVolume
接口,如果失败,则尝试获取ISimpleAudioVolume
接口。 这确保了即使会话不支持更高级的IAudioEndpointVolume
接口,你也可以控制音量。 - 在找到并更改了目标会话的音量后,退出循环。 这可以防止修改错误会话的音量。
请注意,要使此代码正常工作,你需要安装 VB-音频虚拟电缆并将其设置为Opera的输出设备。
此外,不同的浏览器可能会为其音频会话使用不同的命名方案,因此你可能需要尝试使用不同的进程名称或会话属性来找到要控制的正确会话。
标签:python,python-3.x,windows,audio From: 78802225