如果达到特定的噪音水平,如何使机器“黑屏”一段时间(作为惩罚)?

Leo*_*sky 1567 audio linux shell parental-controls

我的孩子(4 岁和 5 岁)在电脑上玩游戏时会大喊大叫。我找到了一种有效的治疗方法。当我听到很大的噪音时,我会进入游戏计算机并执行以下操作:

chvt 3;  sleep 15;  chvt 7 
Run Code Online (Sandbox Code Playgroud)

这将在 Linux 上关闭屏幕 15 秒。我告诉他们电脑不喜欢大声喧哗。他们完全相信这一点,并请求计算机原谅。他们变得更安静了,但没有达到我会高兴的程度,所以我需要继续这个教育过程。但是,我并不总是手动执行此操作。

是否可以自动执行此操作?麦克风附在盒子上。如果响度水平超过某个阈值,那么我想运行一个命令。

tuc*_*uxi 654

使用sox来自SoX来分析一个简短的音频样本:

sox -t .wav "|arecord -d 2" -n stat
Run Code Online (Sandbox Code Playgroud)

随着-t .wav我们指定我们处理的wav类型,"|arecord -d 2"执行arecord 两秒钟程序,-n输出到空文件,并与stat我们指定我们想要的统计数据。

这个命令的输出,在我的系统上有一些背景语音,是:

Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
Samples read:             16000
Length (seconds):      2.000000
Scaled by:         2147483647.0
Maximum amplitude:     0.312500
Minimum amplitude:    -0.421875
Midline amplitude:    -0.054688
Mean    norm:          0.046831
Mean    amplitude:    -0.000044
RMS     amplitude:     0.068383
Maximum delta:         0.414063
Minimum delta:         0.000000
Mean    delta:         0.021912
RMS     delta:         0.036752
Rough   frequency:          684
Volume adjustment:        2.370
Run Code Online (Sandbox Code Playgroud)

然后可以通过以下方式提取最大幅度:

grep -e "RMS.*amplitude" | tr -d ' ' | cut -d ':' -f 2
Run Code Online (Sandbox Code Playgroud)

我们grep对于我们想要的行,使用它tr来修剪空格字符,然后cut:字符修剪掉它,并采用0.068383本例中给出的第二部分。正如评论所建议的,RMS是比最大幅度更好的能量度量。

您最终可以使用bc结果来比较命令行中的浮点值:

if (( $(echo "$value > $threshold" | bc -l) )) ; # ... 
Run Code Online (Sandbox Code Playgroud)

如果您构建一个循环(参见Bash 示例),调用sleep 1 分钟,测试音量,然后重复,您可以让它在后台运行。最后一步是将它添加到 init 脚本或服务文件(取决于您的操作系统/发行版),这样您甚至不必手动启动它。

  • 我不建议采用最大振幅。当孩子们的屏幕因为有人鼓掌或类似的东西而变黑时,这对孩子们来说并不好。平均似乎更合适。 (286认同)
  • 只是澄清一下,“平均”是指 RMS 幅度,对吗?如果噪声在 2 秒内具有一致的响度,则平均振幅将接近于 0(正负两半将相互抵消)。 (36认同)
  • 一系列样本的简单“能量”检测器只是将所有峰值的值加在一起。如果你不想,你甚至不必平均它。峰值就是`sample[n]>sample[n-1]&&sample[n]>sample[n+1]`的任何点我已经用它作为测量歌曲能量的基本机制并且它起作用很好。只需搜索您对音量级别感到满意的幻数。 (8认同)
  • 当涉及到孩子大喊大叫时,我想查看您的第一个命令的示例输出,以供参考。 (3认同)
  • 对于描述的用法(自动启动 + 每隔几分钟运行一次),cron 作业是正确的工具。与使用 init 脚本 + bash 循环 + 睡眠相比,设置更简单,更健壮。 (3认同)

Jan*_*sen 138

以下是使用Pure Data 的方法

使用 Pure Data 预防儿童大喊大叫

Metro是一个节拍器,并且“metro 100”每 100 毫秒就会不断地敲击。

音频来自adc~,音量由env~计算。“pd dsp 0”在敲击时关闭DSP,“pd dsp 1”打开它。“shell”在shell中执行传递的命令,我使用Linux xrandr API将亮度设置为X,您需要为Wayland进行调整。

如您所见,宽限期和锁定比音频代码占用更多空间。

使用环形缓冲区和/或移动平均线制定解决方案应该比使用sox. 因此,我认为为此使用 Pure Data 并不是一个坏主意。但是屏幕消隐本身和锁定不符合数据流范式。

PD 文件位于gist.github.com:ysangkok - kidsyell.pd

  • 非常好!您可以使用此技术使其响应非常灵敏:跟踪一分钟内的平均声级,然后将其用作基线,这样当孩子们超过基线 20 dB 时,它就会触发。然后它会自动调整到环境声级。 (12认同)
  • 如果它比平时更安静,比如周末的早晨,那么它会变得更加敏感,因为它总是比环境水平高 20 dB (4认同)
  • 是的,这是有道理的@Hans-ChristophSteiner。但在某种程度上,环境噪音水平实际上不会要求孩子们大声喊叫,因为他们在整体噪音中所占的比例较小?当然,这只适用于现有噪声为白色或粉红色或以其他方式被忽略的情况。 (2认同)

Atr*_*opo 108

检查Thomer M. Gil 的“如何检测声音/音频的存在”

基本上它每 5 秒记录一次声音sox,然后检查声音幅度,使用,并决定是否触发脚本。我认为您可以轻松地ruby为您的孩子改编剧本!或者您也可以选择破解他提供的 Python 脚本(使用 PyAudio)。

  • 那些不到 5 秒而避免检测的爆发呢? (6认同)

小智 56

您可以通过执行以下操作从麦克风获取信息:

arecord -d1 /dev/null -vvv
Run Code Online (Sandbox Code Playgroud)

您可能需要稍微调整一下设置,例如:

arecord -d1 -Dhw:0 -c2 -fS16_LE /dev/null -vvv
Run Code Online (Sandbox Code Playgroud)

从那时起,解析输出就是一个简单的问题。


Ale*_*che 48

这是我见过的最有趣的问题之一。感谢tucuxi 这么好的回答;我已设置为 bash 脚本

#!/bin/bash

threshold=0.001
# we should check that sox and arecord are installed
if [ $1 ]; then threshold=$1; fi
while [ 1 -gt 0 ]; do
 if(( $(echo "$(sox -t .wav '|arecord -d 2' -n stat 2>&1|grep -e 'RMS.*amplitude'|tr -d ' '|cut -d ':' -f 2 ) > $threshold"|bc -l) ))
 then
  chvt 3; sleep 5; chvt 7;
 fi
done
Run Code Online (Sandbox Code Playgroud)

  • 如果您通过在 /etc/rc4.d/S99rc.local 中添加一行来开始运行,然后将输入麦克风从未放大更改为 100%,您也可能最终被扔到 tty3(您可以在睡眠结束之前跳回来) Ctrl+Alt+F7),如果您的键盘声音太大而无法打开终端,请运行 sudo killall too_loud 然后 Ctrl+Alt+F1 并在那里登录。) (8认同)

小智 44

我的 C 或 C++ 解决方案的 2 美分:也许不是最有效的方法,但在 Linux 上,您可以使用ALSA API(Linux 的内置音频处理库)并使用一些数值技术(例如,计算平均声音每秒水平)以获得噪声水平。

然后你可以在无限循环中检查它,如果它大于预设的阈值,你可以使用X11 库关闭屏幕几秒钟,或者(不太优雅,但它有效)chvt使用system("chvt 3; sleep 15; chvt 7 ");.

  • 如果使用命令,我会考虑与 `chvt` 不同的东西。[ArchWiki](https://wiki.archlinux.org/index.php/Backlight#Switching_off_the_backlight) 有很好的例子。 (2认同)