使用 php exec 和 amixer 设置音量
Posted
技术标签:
【中文标题】使用 php exec 和 amixer 设置音量【英文标题】:Set volume using php exec and amixer 【发布时间】:2016-08-20 10:05:00 【问题描述】:我写了一个小 php 脚本来用 alsa 控制我本地机器的音量:
<?php
# for simplicity and testing it really just executes the command:
echo exec('amixer set Master 5%+') . " \n";
现在,当我在命令行上运行此脚本时,它工作正常:
$ php volume.php
Front Right: Playback 39226 [60%] [on]
$ php volume.php
Front Right: Playback 42503 [65%] [on]
$ php volume.php
Front Right: Playback 45780 [70%] [on]
我正在播放音乐,但我听到的声音越来越大。
但是当我尝试通过 apache 从浏览器调用 http://localhost/volume.php
运行脚本时,它不起作用。
# http://localhost/volume.php
Front Right: Playback 55709 [10%] [on]
# F5
Front Right: Playback 55709 [15%] [on]
# F5
Front Right: Playback 55709 [20%] [on]
现在我听到音量没有变化,而且百分比似乎与当前状态无关。它说的是 10% - 15% - 20%,但实际上仍然是 70%。
我的 apache 以我的用户身份运行,因此 exec('whoami')
为我提供了我在 shell 上登录时使用的用户名,一切正常。
# httpd.conf
User mkt
Group mkt
我在 Fedora 22 上。
可能是apache2进程环境的原因。 任何想法如何解决这个问题?
更新:
这是aplay -L的输出:
[mkt@localhost ~]$ aplay -L
null
Discard all samples (playback) or generate zero samples (capture)
pulse
PulseAudio Sound Server
default
Default ALSA Output (currently PulseAudio Sound Server)
sysdefault:CARD=Intel
HDA Intel, ALC888 Analog
Default Audio Device
front:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
Front speakers
surround21:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
4.0 Surround output to Front and Rear speakers
surround41:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=Intel,DEV=0
HDA Intel, ALC888 Analog
7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
iec958:CARD=Intel,DEV=0
HDA Intel, ALC888 Digital
IEC958 (S/PDIF) Digital Audio Output
hdmi:CARD=NVidia,DEV=0
HDA NVidia, HDMI 0
HDMI Audio Output
hdmi:CARD=NVidia,DEV=1
HDA NVidia, HDMI 1
HDMI Audio Output
hdmi:CARD=NVidia,DEV=2
HDA NVidia, HDMI 2
HDMI Audio Output
hdmi:CARD=NVidia,DEV=3
HDA NVidia, HDMI 3
HDMI Audio Output
在命令行只有默认和脉冲工作:
amixer -D pulse set Master 5%+
amixer -D default set Master 5%+
使用 PHP,即使这两个也不起作用。 无论如何...我的声音来自我的显示器扬声器,它是通过 hdmi 插入的。所以我猜最后 4 台设备是我的候选人。但它们都不起作用。
$ amixer -D hdmi:CARD=NVidia,DEV=0 set Master 5%+
$ amixer -D hdmi:CARD=NVidia,DEV=1 set Master 5%+
$ amixer -D hdmi:CARD=NVidia,DEV=2 set Master 5%+
$ amixer -D hdmi:CARD=NVidia,DEV=3 set Master 5%+
在所有四种情况下,它都说: (当然是 DEV=[0-3])
ALSA lib control.c:954:(snd_ctl_open_noupdate) Invalid CTL hdmi:CARD=NVidia,DEV=3
amixer: Mixer attach hdmi:CARD=NVidia,DEV=3 error: No such file or directory
更新
aplay -l 的输出:
$ aplay -l
**** List of Hardware-Devices (PLAYBACK) ****
Card 0: Intel [HDA Intel], Device 0: ALC888 Analog [ALC888 Analog]
Sub-Devices: 1/1
Sub-Device #0: subdevice #0
Card 0: Intel [HDA Intel], Device 1: ALC888 Digital [ALC888 Digital]
Sub-Devices: 1/1
Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 3: HDMI 0 [HDMI 0]
Sub-Devices: 1/1
Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 7: HDMI 1 [HDMI 1]
Sub-Devices: 0/1
Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 8: HDMI 2 [HDMI 2]
Sub-Devices: 1/1
Sub-Device #0: subdevice #0
Card 1: NVidia [HDA NVidia], Device 9: HDMI 3 [HDMI 3]
Sub-Devices: 1/1
Sub-Device #0: subdevice #0
$ amixer -c0 set Master 5%+
$ amixer -c1 set Master 5%+
两者都不起作用!
解决方案:
感谢大家的帮助! 答案虽然来自https://superuser.com/questions/1069981/set-volume-using-php-exec-and-amixer
putenv("PULSE_SERVER=/run/user/".getmyuid()."/pulse/native");
【问题讨论】:
您是否检查过您的 apache2 进程的环境是否与您的环境匹配?amixer
可能会尝试访问它不可用的本地设置。
hm...echo exec('echo $HOME')
在命令行上输出正确的路径,但在浏览器中为空...所以我猜这就是问题所在?但是如何解决这个...?
可以试试putenv()
可能,php.net/manual/en/function.putenv.php
您说 Apache 以您的用户身份运行 - 但它是否在同一个会话中运行? amixer 使用 DBUS ...我对细节很模糊,但我假设 DBUS 绑定到会话,而不是用户 ID。你如何以及在哪里开始 apache?也许使用可以从命令行轻松运行的更轻量级的 http 服务器更适合您的目的。你甚至可以自己写:) station.clancats.com/writing-a-webserver-in-pure-php/#
附录:这是一个关于在同一用户的会话之间共享 DBUS 的问题:unix.stackexchange.com/questions/44317/…
【参考方案1】:
完成此任务的最佳且更简单的方法是使用 xdotool。
<?php
shell_exec("DISPLAY=:0 xdotool key XF86AudioMute");
?>
<?php
shell_exec("DISPLAY=:0 xdotool key XF86AudioRaiseVolume");
?>
<?php
shell_exec("DISPLAY=:0 xdotool key XF86AudioLowerVolume");
?>
我在ubuntu openbox上安装了xdotool并配置了rc.xml文件
<!-- Keybinding for Volume management -->
<keybind key="XF86AudioRaiseVolume">
<action name="Execute">
<command>amixer -D pulse set Master 10%+</command>
</action>
</keybind>
<keybind key="XF86AudioLowerVolume">
<action name="Execute">
<command>amixer -D pulse set Master 10%-</command>
</action>
</keybind>
<keybind key="XF86AudioMute">
<action name="Execute">
<command>amixer -D pulse set Master 100%-</command>
</action>
</keybind>
它就像一个魅力。
【讨论】:
【参考方案2】:您说您的 Apache 用户作为您的命令行用户运行。相似性延伸到什么程度?我注意到您使用的是短路径:
echo exec('amixer set Master 5%+')
...鉴于 user 是相同的,您可能在 Apache 中有 错误的路径(PATH 设置不依赖于用户,它们位于用户配置文件,Apache 可能会完全加载不同的配置文件)- 尝试将 amixer
的完整路径放入 exec 中:
echo exec('/usr/local/bin/or/whatever/amixer set Master 5%+') . " \n";
另外,出于调试目的,运行shell_exec
添加2>&1
stderr 重定向到命令行。这可能会提供一些关于究竟是什么失败的线索。
您可以运行更复杂的命令来设置环境:
exec(`HOME=whatever FLAGS=somethingelse PATH=/usr/local/... /usr/local/bin/amixer... 2>&1`);
要了解环境变量是什么,您可以以用户身份登录,验证 amixer 是否工作,将环境转储到文件中:
设置 > 设置.txt
并查看 set.txt 以了解适用于 amixer 的任何值。您可以在 Apache 中运行另一个类似的set
,并比较结果(实际上我认为该环境也可以通过phpinfo()
访问)。
【讨论】:
【参考方案3】:从 apache 运行时,amixer
可能没有解决正确的DBUS。尝试通过在运行amixer
之前从设置变量的shell 脚本调用amixer
来设置DBUS_ADDRESS
环境变量。
dbus_amixer.sh
#! /bin/bash
DBUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/*/environ 2> /dev/null| sed 's/DBUS/\nDBUS/g' | tail -n 1`
if [ "x$DBUS_ADDRESS" != "x" ]; then
export $DBUS_ADDRESS
/usr/bin/amixer set Master 5%+
fi
(复制自Running command-line application from PHP as specific user的代码)
amixer.php
<?php
echo exec('dbus_amixer.sh') . " \n";
【讨论】:
【参考方案4】:尝试首先运行aplay -L
,你应该得到如下输出:
pulse
PulseAudio Sound Server
sysdefault:CARD=MID
HDA Intel MID, ALC889 Analog
Default Audio Device
front:CARD=MID,DEV=0
HDA Intel MID, ALC889 Analog
Front speakers
surround21:CARD=MID,DEV=0
HDA Intel MID, ALC889 Analog
2.1 Surround output to Front and Subwoofer speakers
...
确定其中哪一个是您的设备,然后将您的amixer ...
命令修改为amixer -D device ...
,例如amixer -D surround21:CARD=MID,DEV=0 set Master 5%+
。
这可能有效。如果没有,请尝试aplay -l
(小写),并获取卡号。那么,比如卡号是1
,试试amixer -c 1 set Master 5%+
。
【讨论】:
以上是关于使用 php exec 和 amixer 设置音量的主要内容,如果未能解决你的问题,请参考以下文章
Index» Newbie Corner» [SOLVED] Alsamixer and amixer both output “No such file or directory“