如何从 PowerShell 静音/取消静音

Posted

技术标签:

【中文标题】如何从 PowerShell 静音/取消静音【英文标题】:How can I mute/unmute my sound from PowerShell 【发布时间】:2008-11-01 02:11:17 【问题描述】:

尝试编写一个 PowerShell cmdlet,该 cmdlet 将在开始时静音,除非已经静音,然后在结束时取消静音(只有在开始时没有静音)。 找不到我可以使用的任何 PoweShell 或 WMI 对象。我一直在玩弄诸如auxGetVolume 或auxSetVolume 之类的Win32 函数,但不能让它工作(如何从IntPtr 中读取值?)。

我正在使用 V2 CTP2。大家有什么想法吗?

谢谢!

【问题讨论】:

你见过这个问题吗(它与哔哔声有关,但我不确定你在说什么声音)? ***.com/questions/252799/… 【参考方案1】:

从 Vista 开始,您必须使用 Core Audio API 来控制系统音量。它是一个不支持自动化的 COM API,因此需要从 .NET 和 PowerShell 中使用大量样板。

无论如何,下面的代码让您可以从 PowerShell 访问 [Audio]::Volume[Audio]::Mute 属性。这也适用于可能有用的远程计算机。只需将代码复制粘贴到您的 PowerShell 窗口中即可。

Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume 
  // f(), g(), ... are unused COM method slots. Define these if you care
  int f(); int g(); int h(); int i();
  int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
  int j();
  int GetMasterVolumeLevelScalar(out float pfLevel);
  int k(); int l(); int m(); int n();
  int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
  int GetMute(out bool pbMute);

[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice 
  int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);

[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator 
  int f(); // Unused
  int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);

[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject  

public class Audio 
  static IAudioEndpointVolume Vol() 
    var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
    IMMDevice dev = null;
    Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
    IAudioEndpointVolume epv = null;
    var epvid = typeof(IAudioEndpointVolume).GUID;
    Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
    return epv;
  
  public static float Volume 
    get float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;
    set Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));
  
  public static bool Mute 
    get  bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; 
    set  Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); 
  

'@

使用示例:

PS C:\> [Audio]::Volume         # Check current volume (now about 10%)
0,09999999
PS C:\> [Audio]::Mute           # See if speaker is muted
False
PS C:\> [Audio]::Mute = $true   # Mute speaker
PS C:\> [Audio]::Volume = 0.75  # Set volume to 75%
PS C:\> [Audio]::Volume         # Check that the changes are applied
0,75
PS C:\> [Audio]::Mute
True
PS C:\>

如果您需要,还有更全面的 Core Audio API .NET 包装器,但我不知道有一组 PowerShell 友好的 cmdlet。

P.S. Diogo answer 看起来很聪明,但对我不起作用。

【讨论】:

您有没有机会分享如何使用这种方法使麦克风静音/取消静音? 我发现 this 更完整:github.com/frgnca/AudioDeviceCmdlets 非常感谢!【参考方案2】:

在 ps1 powershell 脚本上使用以下命令:

$obj = new-object -com wscript.shell 
$obj.SendKeys([char]173)

【讨论】:

要使用 .bat 运行,将此代码放入文件中并写入 powershell.exe -file "C:\file.ps1" 谢谢.. 添加键盘快捷键“F4”就像一个魅力。 这是敲击静音键的好方法和简单方法,但它只是一个切换而不是离散静音。在不知道卷的状态的情况下,它可能会做与预期相反的事情。【参考方案3】:

Alexandre 的回答适合我的情况,但由于关于“var”命名空间的编译错误,他的示例不起作用。似乎较新/不同版本的 .net 可能会导致该示例不起作用。如果您发现收到编译错误,可以尝试使用以下替代版本:

Add-Type -Language CsharpVersion3 -TypeDefinition @'
using System.Runtime.InteropServices;

[Guid("5CDF2C82-841E-4546-9722-0CF74078229A"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IAudioEndpointVolume 
  // f(), g(), ... are unused COM method slots. Define these if you care
  int f(); int g(); int h(); int i();
  int SetMasterVolumeLevelScalar(float fLevel, System.Guid pguidEventContext);
  int j();
  int GetMasterVolumeLevelScalar(out float pfLevel);
  int k(); int l(); int m(); int n();
  int SetMute([MarshalAs(UnmanagedType.Bool)] bool bMute, System.Guid pguidEventContext);
  int GetMute(out bool pbMute);

[Guid("D666063F-1587-4E43-81F1-B948E807363F"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDevice 
  int Activate(ref System.Guid id, int clsCtx, int activationParams, out IAudioEndpointVolume aev);

[Guid("A95664D2-9614-4F35-A746-DE8DB63617E6"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IMMDeviceEnumerator 
  int f(); // Unused
  int GetDefaultAudioEndpoint(int dataFlow, int role, out IMMDevice endpoint);

[ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")] class MMDeviceEnumeratorComObject  

public class Audio 
  static IAudioEndpointVolume Vol() 
    var enumerator = new MMDeviceEnumeratorComObject() as IMMDeviceEnumerator;
    IMMDevice dev = null;
    Marshal.ThrowExceptionForHR(enumerator.GetDefaultAudioEndpoint(/*eRender*/ 0, /*eMultimedia*/ 1, out dev));
    IAudioEndpointVolume epv = null;
    var epvid = typeof(IAudioEndpointVolume).GUID;
    Marshal.ThrowExceptionForHR(dev.Activate(ref epvid, /*CLSCTX_ALL*/ 23, 0, out epv));
    return epv;
  
  public static float Volume 
    get float v = -1; Marshal.ThrowExceptionForHR(Vol().GetMasterVolumeLevelScalar(out v)); return v;
    set Marshal.ThrowExceptionForHR(Vol().SetMasterVolumeLevelScalar(value, System.Guid.Empty));
  
  public static bool Mute 
    get  bool mute; Marshal.ThrowExceptionForHR(Vol().GetMute(out mute)); return mute; 
    set  Marshal.ThrowExceptionForHR(Vol().SetMute(value, System.Guid.Empty)); 
  

'@

用法同理:

PS C:\> [Audio]::Volume         # Check current volume (now about 10%)
0,09999999
PS C:\> [Audio]::Mute           # See if speaker is muted
False
PS C:\> [Audio]::Mute = $true   # Mute speaker
PS C:\> [Audio]::Volume = 0.75  # Set volume to 75%
PS C:\> [Audio]::Volume         # Check that the changes are applied
0,75
PS C:\> [Audio]::Mute
True
PS C:\>

【讨论】:

不错。这是否可以扩展到涵盖麦克风/录音设备? 好喜欢晚上的尼克!! @monojohnny 是的,如果您将第一个参数更改为 enumerator.GetDefaultAudioEndpoint1 (eCapture) 而不是 0 (eRender),那么这可以使默认麦克风/输入设备静音/取消静音. 还值得指出这与上面亚历山大的答案 (***.com/a/19348221) 之间的唯一区别是添加了-Language CsharpVersion3。如果这个答案只是对那个问题的评论,那可能就不那么令人困惑了。【参考方案4】:

似乎没有一种快速简便的方法来调整音量。如果你有 c++ 经验,你可以用this blog post 做一些事情,Larry Osterman 描述了如何从平台 api 调用 IAudioEndpointVolume 接口(对于 Vista,从我在几次搜索中发现的内容来看,XP 可能更难)。

V2 确实允许您编译内联代码(通过 Add-Type),所以这可能是一个选项。

【讨论】:

【参考方案5】:

您可以通过简单地管理 Windows 音频服务以另一种方式给猫剥皮。停止静音,启动取消静音。

【讨论】:

这是我今天在搜索中找到的最简单的选项 +1。 "net stop "Windows 音频" 在 powershell 中:Stop-Service -DisplayName "Windows Audio" & Start-Service -DisplayName "Windows Audio"。希望我早点想到这一点。 简单,工作(在我的 Win10 机器上),并导致发送其他密钥或使用其他 shell 方法等的可能性。NICE @Brian Adams ***.com/users/32992/brian-adams 如果在停止和重新启动服务时媒体文件处于暂停状态,这可能会出现问题。视频播放器稍后可能无法播放声音,除非您停止并重新开始播放。 注意 - 这需要管理员权限,这对我来说是一个交易破坏者。【参考方案6】:

我知道这不是 PowerShell,但结合 Michael 和 Diogo 的答案给出了一个单行 VBScript 解决方案:

CreateObject("WScript.Shell").SendKeys(chr(173))

把这个打到mute.vbs,你可以双击切换静音

在 Windows 10 (10586.104) 中仍然有效 无需像使用 PowerShell 那样Set-ExecutionPolicy

【讨论】:

【参考方案7】:

我没有找到如何在 PowerShell 中执行此操作,但是有一个名为 NirCmd 的命令行实用程序可以通过运行以下命令来解决问题:

C:\utils\nircmd.exe mutesysvolume 2

NirCmd 可在此处免费获得: http://www.nirsoft.net/utils/nircmd.html

【讨论】:

【参考方案8】:

vbscript 中的解决方案:

Set WshShell = CreateObject("WScript.Shell")
For i = 0 To 50
  WshShell.SendKeys(chr(174))
  WScript.Sleep 100
Next

按键每次将音量降低 2。

【讨论】:

【参考方案9】:

查看我对Change audio level from powershell?的回复

Set-DefaultAudioDeviceMute

【讨论】:

【参考方案10】:

在我的回答得到一些反馈后,让我再试一次

这是基于@frgnca 的 AudioDeviceCmdlets,可在此处找到:https://github.com/frgnca/AudioDeviceCmdlets

这里的代码将使每个录音设备静音。

Import-Module .\AudioDeviceCmdlets
$audio_device_list = Get-AudioDevice -list
$recording_devices = $audio_device_list | ? $_.Type -eq "Recording"
$recording_devices 
$recording_device_index = $recording_devices.Index | Out-String -stream
foreach ($i in $recording_device_index) 
    $inti = [int]$i
    Set-AudioDevice $inti | out-null -erroraction SilentlyContinue
    Set-AudioDevice -RecordingMute 1 -erroraction SilentlyContinue

您导入 AudioDeviceCmdlets dll,然后保存所有音频设备的列表,过滤到录音设备中。您获取所有录制设备的索引,然后遍历每个设备,首先将设备设置为主音频设备,然后将该设备设置为静音(这 2 步过程是 dll 施加的限制)。

要取消静音,请将 -RecordingMute 1 更改为 RecordingMute 0

同样,您可以使用以下代码静音播放设备:

Import-Module .\AudioDeviceCmdlets
$audio_device_list = Get-AudioDevice -list
$playback_devices = $audio_device_list | ? $_.Type -eq "Playback"
$playback_devices 
$playback_device_index = $playback_devices.Index | Out-String -stream
foreach ($i in $playback_device_index) 
$inti = [int]$i
    Set-AudioDevice $inti | out-null -erroraction SilentlyContinue
    Set-AudioDevice -PlaybackMute 1 -erroraction SilentlyContinue

要取消静音,请将 -PlaybackMute 1 更改为 PlaybackMute 0

此代码来自我拥有的一个更大项目的一部分,该项目通过 Arduino 连接到物理按钮/LED 静音状态显示,以启用单按钮按下以静音/取消静音所有系统麦克风(以帮助 Zoom、Meet、Teams、 Discord 等)并帮助人们避免尴尬的热点事件。

https://github.com/dakota-mewt/mewt

附:我真的很喜欢Change audio level from powershell?这样的一些单行解决方案@

但是,请注意,单线静音通常仅适用于当前设置为 Windows 默认设置的单个设备。因此,如果您的软件能够处理不同的音频设备(例如 Zoom 和 Meet),而它们恰好使用的是非默认设备,那么它可能无法正常工作。

【讨论】:

发布一个独立的解决方案而不是链接【参考方案11】:

在上面的第二个脚本中,要在 PowerShell 7 或 PowerShell Core 中工作的第一行更改:

-Language CsharpVersion3

到...

-Language Csharp

在 W10 上工作

【讨论】:

或者完全省略 -Language 参数(CSharp 是 PowerShell 7 中唯一可接受的值,也是默认值,请参阅 documentation)为Alexandre 的original answer 就是这种情况 - 即这不是一个新答案,作为对上述答案的评论可能会更好。

以上是关于如何从 PowerShell 静音/取消静音的主要内容,如果未能解决你的问题,请参考以下文章

如何快速制作静音和取消静音按钮?

如何使用 pywin32 静音/取消静音?

如何在 ionic 平台的 APIRTC 上静音和取消静音视频/音频?

Swift 3:如何在使用 AVFoundation 录制视频期间将麦克风静音/取消静音

为网站中的静音/取消静音设置 cookie

我如何对 youtube 嵌入播放器进行编程以在单击时取消静音