I am looking for a tool that will tell me, in less than half a second, if the microphone is picking up any sound above a certain threshold. (I plan to then mute the Master channel with another command line tool, like amixer.)
4 Answers
This solution will avoid writing repeatedly to disk, and even though it in worst case takes a second instead of the desired less than half a second, I found it to be fast enough after trying it. So, here are the two scripts I use:
./detect
:
while true; do
arecord -d 1 /dev/shm/tmp_rec.wav ; sox -t .wav /dev/shm/tmp_rec.wav -n stat 2>\
&1 | grep "Maximum amplitude" | cut -d ':' -f 2 | ./check.py
if [ $? -eq 0 ] ; then
amixer set Master 0
else
amixer set Master 80
fi
done
./check.py
:
#!/usr/bin/env python
import sys
number = 0.0
thing="NO"
line = sys.stdin.readline()
thing = line.strip()
number = float(thing)
if number < 0.15:
raise Exception,"Below threshold"
Hardly elegant, but it works.
Note: If you want a more gradual thing, add something like this:
for i in `seq 0 80 | tac`; do
amixer set Master $i
done
for muting and
for i in `seq 0 80`; do
amixer set Master $i
done
for unmuting.
-
9A slightly more elegant solution, which supports half-second resolution and doesn't require a temporary file:
while true; do amixer set Master $(rec -n stat trim 0 .5 2>&1 | awk '/^Maximum amplitude/ { print $3 < .15 ? 80 : 0 }'); done
– nandhpCommented Jun 29, 2012 at 13:17 -
1Python is a bit overkill, math-blog.com/2012/07/23/… result=$(AUDIODEV=hw:1 rec -n stat trim 0 .5 2>&1 | grep "Maximum amplitude" | grep -o "[0-9]\.[0-9]*$"); echo "$result > 0.01" | bc– KevinCommented Jun 15, 2016 at 5:55
-
1Just keep in mind that 'Maximum amplitude' isn't the only indicator of a loud sound. A sound with a high frequency (e.g. clinking of glasses) may be perceived as really loud by human ears but the sox' 'Maximum amplitude' won't be very different from the lowest one. So in some cases it would make sense to analyze 'Rough frequency' as well.– ka3akCommented May 19, 2017 at 15:05
-
In contrast to
arecord
, I could not userec
while the input device is used by another process (webRTC using uv4l and janus webrtc). @Kevin @nandhp Commented May 31, 2021 at 16:44
Just version without python script and TALKING_PERIOD, that sets up how many seconds will sound be on DOWN_SOUND_PERC level, then goes to UP_SOUND_PERC level.
#!/bin/bash
TALKING_PERIOD=16
UP_SOUND_PERC=65
DOWN_SOUND_PERC=45
counter=0
while true; do
echo "counter: " $counter
if [ "$counter" -eq 0 ]; then
nmb=$(arecord -d 1 /dev/shm/tmp_rec.wav ; sox -t .wav /dev/shm/tmp_rec.wav -n stat 2>&1 | grep "Maximum amplitude" | cut -d ':' -f 2)
echo "nmb: " $nmb
if (( $(echo "$nmb > 0.3" |bc -l) )); then
echo "ticho"
amixer -D pulse sset Master 45%
counter=$TALKING_PERIOD
else
echo "hlasno"
amixer -D pulse sset Master 65%
fi
fi
if [[ $counter -gt 0 ]]; then
((counter--))
fi
sleep 1
done
There is a tool called pavumeter that lets you see the microphone level, Open capture interface of pavumeter,
Then adjust the capture sound level using pavucontrol, In pavucontrol, go to input devices, and adjust microphone sensitivity.
Edit: In the bash script by R4v0, done is inside code.
Edit2: I wanted to raise the volume each time there is noise, so i just edited more than to be less than and cancelled talking peroid
if (( $(echo "$nmb < 0.3" |bc -l) )); then
-
7
I edited it to work with ffmpeg
sox and bc need to be installed.
Using -f "format" pulse seems too slow looping, so i used alsa
For -i "input" you can instead specify the stream
For more info: https://trac.ffmpeg.org/wiki/Capture/PulseAudio#Selectingtheinput
#!/bin/bash
ffmpeg -y -loglevel panic -f pulse -i default -t 0.5 /dev/shm/tmp_rec.wav ; sox -t .wav /dev/shm/tmp_rec.wav -n stat 2>&1 | grep "Maximum amplitude" | cut -d ':' -f 2