如何在Linux系统中使用Python获取系统音频输出的相对音量?
Got it, let's tackle this problem—you want to grab the relative loudness of audio being played through your Linux speakers using Python, not just the system volume level (like the slider setting). Here are a couple of reliable, distro-agnostic approaches that work for most setups:
Approach 1: Use PulseAudio's parec + Numpy (Simple & Effective)
Most Linux systems use PulseAudio as their audio server, so we can leverage its built-in tools to capture the "monitor" output (the audio being sent to speakers) and calculate relative loudness via RMS (Root Mean Square) — this metric directly correlates to perceived sound intensity.
Step 1: Install Dependencies
First, make sure you have the required tools and libraries:
# For Debian/Ubuntu-based distros sudo apt install pulseaudio-tools python3-numpy # For Fedora/RHEL-based distros sudo dnf install pulseaudio-utils python3-numpy
Step 2: Python Code to Calculate Relative Loudness
This script will capture the monitor audio stream, compute the RMS value, and print the relative loudness (higher = louder):
import subprocess import numpy as np def get_relative_loudness(): # Configure parec to capture monitor output (16-bit, mono, 44.1kHz) cmd = [ "parec", "--format=s16le", "--rate=44100", "--channels=1", "--monitor-stream" ] # Start the parec process and read raw audio data process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL) # Read a chunk of audio data (adjust chunk size for responsiveness) chunk = process.stdout.read(44100 * 2) # 1 second of data (16-bit = 2 bytes per sample) if not chunk: return 0.0 # Convert raw bytes to numpy array of integers audio_data = np.frombuffer(chunk, dtype=np.int16) # Calculate RMS (relative loudness) — normalize to 0-1 range rms = np.sqrt(np.mean(audio_data**2)) normalized_rms = rms / np.iinfo(np.int16).max # Max value for 16-bit audio process.terminate() return round(normalized_rms, 4) # Example usage if __name__ == "__main__": loudness = get_relative_loudness() print(f"Relative Loudness: {loudness}")
Approach 2: Use PyAudio (More Control Over Audio Streams)
If you prefer a pure-Python approach without relying on external CLI tools, PyAudio can access the PulseAudio monitor device directly.
Step 1: Install Dependencies
pip install pyaudio sudo apt install portaudio19-dev # Required for PyAudio on Debian/Ubuntu
Step 2: Python Code with PyAudio
First, find your monitor device name using pactl list sources — look for entries like "Monitor of Built-in Audio Analog Stereo". Then use this script:
import pyaudio import numpy as np def get_monitor_device_index(p, device_name_substring="Monitor"): # Find the index of the PulseAudio monitor device for i in range(p.get_device_count()): info = p.get_device_info_by_index(i) if device_name_substring in info["name"]: return i raise ValueError("Monitor device not found — check your PulseAudio setup") def get_relative_loudness(): p = pyaudio.PyAudio() monitor_index = get_monitor_device_index(p) # Configure audio stream (match monitor device parameters) stream = p.open( format=pyaudio.paInt16, channels=1, rate=44100, input=True, input_device_index=monitor_index, frames_per_buffer=44100 ) # Read audio data chunk = stream.read(44100) audio_data = np.frombuffer(chunk, dtype=np.int16) # Calculate normalized RMS rms = np.sqrt(np.mean(audio_data**2)) normalized_rms = rms / np.iinfo(np.int16).max stream.stop_stream() stream.close() p.terminate() return round(normalized_rms, 4) # Example usage if __name__ == "__main__": try: loudness = get_relative_loudness() print(f"Relative Loudness: {loudness}") except ValueError as e: print(e)
Key Notes
- RMS Explained: The normalized RMS value ranges roughly from 0 (silent) to 1 (maximum loudness). It’s a great proxy for perceived relative loudness.
- Permissions: Make sure your user is in the
audiogroup to access PulseAudio devices:sudo usermod -aG audio $USER(log out and back in after this). - Responsiveness: Adjust the chunk size in either script if you want faster updates (smaller chunks) or smoother readings (larger chunks).
内容的提问来源于stack exchange,提问作者Corey Campbell

