使用php exec和amixer设置音量

时间:2022-09-17 08:05:02

I wrote a little php script to control the volume of my local machine with alsa:

我写了一个小的PHP脚本来控制alsa本地机器的音量:

<?php
# for simplicity and testing it really just executes the command:
echo exec('amixer set Master 5%+') . " \n";

Now when I run this script on command line it works fine:

现在,当我在命令行上运行此脚本时,它工作正常:

$ 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]

I have music playing and I hear it getting louder.

我有音乐播放,我听到声音越来越大。

But when I try to run the script via apache from the browser calling http://localhost/volume.php it doesn't work.

但是当我尝试从浏览器调用http://localhost/volume.php通过apache运行脚本时,它不起作用。

# http://localhost/volume.php
Front Right: Playback 55709 [10%] [on]
# F5
Front Right: Playback 55709 [15%] [on]
# F5
Front Right: Playback 55709 [20%] [on]

Now I hear no change in volume and the percentages seem to be unrelated to the current state. It says 10% - 15% - 20% when it really is still at 70%.

现在我听说音量没有变化,百分比似乎与当前状态无关。当它真的仍然是70%时,它说10% - 15% - 20%。

My apache is running as my user so exec('whoami') gives me the username I am logged in with on my shell where everything works fine.

我的apache正在以我的用户身份运行,因此exec('whoami')为我提供了我在shell上登录的用户名,一切正常。

# httpd.conf
User mkt
Group mkt

I'm on Fedora 22.

我在Fedora 22上。

Probably it's due to the apache2 process environment. Any ideas how to fix this?

可能是由于apache2进程环境。任何想法如何解决这一问题?

UPDATE:

This is the output of aplay -L:

这是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

On command line only default and pulse are working:

在命令行上只有默认和脉冲工作:

amixer -D pulse set Master 5%+
amixer -D default set Master 5%+

With PHP even those two don't work. Anyway... my sound comes from my monitors speakers which is plugged in via hdmi. So I guess the last 4 devices are my candidates. But non of them work.

用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%+

In all four cases it says: (with DEV=[0-3] of course)

在所有四种情况下它都说:(当然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

UPDATE

Output of aplay -l:

输出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%+

Both don't work!

两者都不起作用!

SOLUTION:

Thanks for all the help! The answer though came from https://superuser.com/questions/1069981/set-volume-using-php-exec-and-amixer

感谢您的帮助!答案虽然来自https://superuser.com/questions/1069981/set-volume-using-php-exec-and-amixer

putenv("PULSE_SERVER=/run/user/".getmyuid()."/pulse/native");

4 个解决方案

#1


4  

Perhaps amixer isn't addressing the correct DBUS when run from apache. Try setting the DBUS_ADDRESS environment variable by invoking amixer from a shell script that sets the variable before running amixer.

也许amixer在从apache运行时没有解决正确的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

(Code copied from Running command-line application from PHP as specific user)

(作为特定用户从PHP运行命令行应用程序复制的代码)

amixer.php

<?php
echo exec('dbus_amixer.sh') . " \n";

#2


2  

Try first running aplay -L and you should get output something like this:

首先尝试运行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
...

Identify which of these is your device, then modify your amixer ... command to amixer -D device ..., for example amixer -D surround21:CARD=MID,DEV=0 set Master 5%+.

确定哪些是您的设备,然后将amixer ...命令修改为amixer -D device ...,例如amixer -D surround21:CARD = MID,DEV = 0设置Master 5%+。

This may work. If not, try aplay -l (lowercase), and get the card number. Then, for example, if the card number is 1, try amixer -c 1 set Master 5%+.

这可能有效。如果没有,请尝试aplay -l(小写),并获取卡号。然后,例如,如果卡号为1,请尝试amixer -c 1设置Master 5%+。

#3


1  

You say that your Apache user runs as your command line user. How far does the similarity extend? I notice that you use short path:

您说您的Apache用户作为命令行用户运行。相似性延伸到多远?我注意到你使用短路径:

echo exec('amixer set Master 5%+')

...given that the user is the same, you might have the wrong path in Apache (PATH settings are not dependent on the user, they're in the user profile, and Apache might load a different profile altogether) - try placing the full path to amixer into the exec:

...假设用户是相同的,你可能在Apache中有错误的路径(PATH设置不依赖于用户,他们在用户配置文件中,而Apache可能会加载不同的配置文件) - 尝试放置amixer进入exec的完整路径:

echo exec('/usr/local/bin/or/whatever/amixer set Master 5%+') . " \n";

Also, for debugging purposes, run shell_exec adding 2>&1 stderr redirect to the command line. This might yield some clue as to what exactly is failing.

此外,出于调试目的,运行shell_exec将2>&1 stderr重定向添加到命令行。这可能会产生一些关于究竟是什么失败的线索。

You can run a more complex command to set up environment:

您可以运行更复杂的命令来设置环境:

exec(`HOME=whatever FLAGS=somethingelse PATH=/usr/local/... /usr/local/bin/amixer... 2>&1`);

To know what the environment variables are, you can log as the user, verify that amixer works, dump the environment into a file:

要了解环境变量是什么,您可以以用户身份登录,验证amixer是否正常工作,将环境转储到文件中:

set > set.txt

set> set.txt

and check out set.txt for whatever values could apply to amixer. You can run another similar set from within Apache, and compare the results (actually I think that the environment is accessible also via phpinfo()).

并查看set.txt,了解适用于amixer的任何值。您可以在Apache中运行另一个类似的集合,并比较结果(实际上我认为环境也可以通过phpinfo()访问)。

#4


0  

The best and more easy way to get this done is by using xdotool.

完成这项工作的最佳和更简单的方法是使用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");
?>

I installed xdotool and configured the rc.xml file on ubuntu openbox with

我安装了xdotool并在ubuntu openbox上配置了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>

It works like a charm.

它就像一个魅力。

#1


4  

Perhaps amixer isn't addressing the correct DBUS when run from apache. Try setting the DBUS_ADDRESS environment variable by invoking amixer from a shell script that sets the variable before running amixer.

也许amixer在从apache运行时没有解决正确的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

(Code copied from Running command-line application from PHP as specific user)

(作为特定用户从PHP运行命令行应用程序复制的代码)

amixer.php

<?php
echo exec('dbus_amixer.sh') . " \n";

#2


2  

Try first running aplay -L and you should get output something like this:

首先尝试运行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
...

Identify which of these is your device, then modify your amixer ... command to amixer -D device ..., for example amixer -D surround21:CARD=MID,DEV=0 set Master 5%+.

确定哪些是您的设备,然后将amixer ...命令修改为amixer -D device ...,例如amixer -D surround21:CARD = MID,DEV = 0设置Master 5%+。

This may work. If not, try aplay -l (lowercase), and get the card number. Then, for example, if the card number is 1, try amixer -c 1 set Master 5%+.

这可能有效。如果没有,请尝试aplay -l(小写),并获取卡号。然后,例如,如果卡号为1,请尝试amixer -c 1设置Master 5%+。

#3


1  

You say that your Apache user runs as your command line user. How far does the similarity extend? I notice that you use short path:

您说您的Apache用户作为命令行用户运行。相似性延伸到多远?我注意到你使用短路径:

echo exec('amixer set Master 5%+')

...given that the user is the same, you might have the wrong path in Apache (PATH settings are not dependent on the user, they're in the user profile, and Apache might load a different profile altogether) - try placing the full path to amixer into the exec:

...假设用户是相同的,你可能在Apache中有错误的路径(PATH设置不依赖于用户,他们在用户配置文件中,而Apache可能会加载不同的配置文件) - 尝试放置amixer进入exec的完整路径:

echo exec('/usr/local/bin/or/whatever/amixer set Master 5%+') . " \n";

Also, for debugging purposes, run shell_exec adding 2>&1 stderr redirect to the command line. This might yield some clue as to what exactly is failing.

此外,出于调试目的,运行shell_exec将2>&1 stderr重定向添加到命令行。这可能会产生一些关于究竟是什么失败的线索。

You can run a more complex command to set up environment:

您可以运行更复杂的命令来设置环境:

exec(`HOME=whatever FLAGS=somethingelse PATH=/usr/local/... /usr/local/bin/amixer... 2>&1`);

To know what the environment variables are, you can log as the user, verify that amixer works, dump the environment into a file:

要了解环境变量是什么,您可以以用户身份登录,验证amixer是否正常工作,将环境转储到文件中:

set > set.txt

set> set.txt

and check out set.txt for whatever values could apply to amixer. You can run another similar set from within Apache, and compare the results (actually I think that the environment is accessible also via phpinfo()).

并查看set.txt,了解适用于amixer的任何值。您可以在Apache中运行另一个类似的集合,并比较结果(实际上我认为环境也可以通过phpinfo()访问)。

#4


0  

The best and more easy way to get this done is by using xdotool.

完成这项工作的最佳和更简单的方法是使用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");
?>

I installed xdotool and configured the rc.xml file on ubuntu openbox with

我安装了xdotool并在ubuntu openbox上配置了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>

It works like a charm.

它就像一个魅力。