After 2,5 years and 1000+ entities with 62 million state changes later its time to give something back to community. I have been looking for a solution to monitor noises at my house but couldn’t find any. So decided to try it myself. This is more like proof of concept so feel free to suggest improvements.
Motivation and use cases
- Identify fire alarm remotely (main case for me)
- Identify any noises when away from home
- Use it as supporting factor to decide if house is empty (everyone away)
- Identify when some machine is running
- Monitor baseline for “boiler room” and get notified if some machine is soon breaking down or malfunctioning (pitch changes)
The solution
- Windows scheduler running Power Shell script every minute
- Use ffmpeg to record 58 seconds of audio from microphone
- Use aubiopitch.exe from Aubio library to analyse pitch from recorded file
- Average and max pitch is calculated from aubiopitch output
- Use ffmpeg to analyse average and max volume
- Use mosquitto_pub.exe to publish the results to mqtt queue
- Use mqtt sensors on Home Assistant to get the results
Power Shell script
del C:\temp\temp.wav
del C:\temp\temp.txt
#$audio = "audio=Desktop Microphone (Microsoftr LifeCam HD-5000)"
$audio = "audio=@device_cm_{33D9A762-90C8-11D0-BD43-00A0C911CE86}\wave_{42903B81-B67E-4949-8255-5619CAB6FB17}";
$time = 58;
$volume = 2;
"Recording for $time seconds with volume $volume"
C:\path_to_files\ffmpeg.exe -f dshow -t $time -i $audio -filter_complex "volume=$volume" C:\temp\temp.wav 2>&1 | Out-Null
C:\path_to_files\aubiopitch.exe -i C:\temp\temp.wav -s -150 -B 1024 -H 1024 > C:\temp\temp.txt | Out-Null
C:\path_to_files\ffmpeg.exe -i C:\temp\temp.wav -filter:a volumedetect -f null nul 2>&1 |
foreach {
if($_ -match 'mean_volume') {
$parts = $_ -split ' ';
$mean_volume = $parts[4];
}
if($_ -match 'max_volume') {
$parts = $_ -split ' ';
$max_volume = $parts[4];
}
}
$table = ""
$table = Import-Csv C:\temp\temp.txt -Delimiter ' ' -Header "Time", "Tone"
$count = 0
$total = 0
[Double]$max = 0.0
foreach ($item in $table) {
if($item.Tone -ne 0){
$count++;
[Double]$tone = [double]$item.Tone;
$total += $tone;
if($tone -gt $max) {
$max = $item.Tone;
}
}
}
$avg = $total/$count
#$avg
#$max
$mean_v = 100+$mean_volume
$max_v = 100+$max_volume
$json = @"
{
\"max_tone\": $max,
\"avg_tone\": $avg,
\"avg_volume\": $mean_v,
\"max_volume\": $max_v
}
"@
#$json
& 'C:\Program Files\mosquitto\mosquitto_pub.exe' -h 192.168.1.123 -t "volume/tyohuone" -m $json
From Windows driver I have set microphone “sensitivity” to 100 %. Volume-parameter on ffmpeg should be high enough to get some meaningful data out of aubiopitch. Too low value result only zeroes. Average is calculated by skipping zero values.
Home Assistant configuration
sensor:
- platform: mqtt
name: Työhuone max tone
state_topic: "volume/tyohuone"
value_template: "{{ value_json.max_tone | round(1) }}"
unit_of_measurement: "Hz"
icon: mdi:microphone
- platform: mqtt
name: Työhuone avg tone
state_topic: "volume/tyohuone"
value_template: "{{ value_json.avg_tone | round(1) }}"
unit_of_measurement: "Hz"
icon: mdi:microphone
- platform: mqtt
name: Työhuone avg volume
state_topic: "volume/tyohuone"
value_template: "{{ value_json.avg_volume }}"
icon: mdi:microphone
unit_of_measurement: "dB"
- platform: mqtt
name: Työhuone max volume
state_topic: "volume/tyohuone"
value_template: "{{ value_json.max_volume }}"
unit_of_measurement: "dB"
icon: mdi:microphone
Outcomes
In above graph HVAC speed increases at 2:00 10 %. You can hardly hear it but this graph impressively catches it (1.). Child screams on the other end of the house 4:40 (2.).
Small nighttime spikes at max volume are likely fridge and freezer compressor starts about 6 meters from mic.
Next steps
- As you might notice my PowerShell skills are limited. Feel free to suggest improvements
- Would be nice to have this analysis done from live stream
- Please suggest also other improvements, such as addtional analysis methods
- Make some critical and other notifcations from combination of these sensors
- Also another mic to “boiler room” is still pending
edit: typo