pythonaudiopyaudioaudio-analysis

Python - Measure LIVE audio volume


I have two audios frequently playing on my computer, one loud and one soft.

I would like to measure the live audio volume playing on my pc, and if it exceeds a certain value, then it would execute a function. How would this be achieved, if possible?

EDIT:

ive been using X99's solution but it records microphone audio, while i need it to record computer audio. Ive been trying to use the input device "Microsoft Sound Mapper - Output", but I keep getting this error.
Error opening InputStream: Invalid number of channels [PaErrorCode -9998]

code:

import numpy as np
import sounddevice as sd

# define your threshold
threshold = 10

devices = sd.query_devices()
for i, device in enumerate(devices):
    if device['name'] == 'Microsoft Sound Mapper - Output':
        channelCount = device['max_output_channels']
        inputDeviceIndex = i
        
print(channelCount)
print(inputDeviceIndex)

def your_function():
    print("Audio level exceeded the threshold")

def callback(indata, frames, time, status):
    # this is called for every chunk of audio data
    volume_norm = np.linalg.norm(indata) * 10
    if volume_norm > threshold:
        your_function()
        
input_device = inputDeviceIndex

with sd.InputStream(callback=callback, channels=channelCount, device=input_device):
    while True:
        sd.sleep(1000)

Solution

  • I successfuly tested this code on my computer. As you didn't specify which audio source to get the input from, I used default value. The code can be adapted to your needs though.

    import numpy as np
    import sounddevice as sd
    
    # define your threshold
    threshold = 0.5
    
    def your_function():
        print("Audio level exceeded the threshold")
    
    def callback(indata, frames, time, status):
        # this is called for every chunk of audio data
        volume_norm = np.linalg.norm(indata) * 10
        if volume_norm > threshold:
            your_function()
    
    with sd.InputStream(callback=callback):
        while True:
            sd.sleep(1000)