You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在树莓派上用Python播放MP3时获取当前声音振幅值的方法

获取Python播放MP3时的实时振幅值(树莓派环境)

因为pygame.mixer.music是流式播放模式,无法直接获取播放中的音频样本数据,所以需要换一种思路:先将MP3解码为PCM原始音频数据,再在播放过程中逐段分析计算振幅。下面提供两种适配树莓派的可行方案:

方案一:使用pygame.mixer.Sound + numpy(适合小体积MP3)

pygame.mixer.Sound会将音频解码后完整加载到内存,方便直接提取样本数据,适合文件不大的场景。

代码示例

import pygame
import numpy as np
from time import sleep

output_file = "sound.mp3"

# 初始化pygame音频模块
pygame.mixer.init()

# 加载MP3为Sound对象(自动完成解码)
sound = pygame.mixer.Sound(output_file)
# 提取原始样本数据,转为numpy数组(16位音频对应int16格式)
samples = np.frombuffer(sound.get_raw(), dtype=np.int16)

# 处理立体声:拆分通道,这里取左声道数据计算振幅
if sound.get_channels() == 2:
    samples = samples.reshape(-1, 2)[:, 0]

sample_rate = sound.get_frequency()
# 每50ms计算一次振幅,对应样本块大小
chunk_size = int(sample_rate * 0.05)
total_chunks = len(samples) // chunk_size

# 开始播放音频
sound.play()

# 逐块计算并输出振幅
for i in range(total_chunks):
    current_chunk = samples[i*chunk_size : (i+1)*chunk_size]
    # 三种常见振幅计算方式
    avg_amplitude = np.mean(np.abs(current_chunk))  # 平均振幅
    max_amplitude = np.max(np.abs(current_chunk))   # 最大振幅
    rms_amplitude = np.sqrt(np.mean(current_chunk**2))  # RMS振幅(更贴合人耳音量感知)
    print(f"第{i+1}段 - 平均振幅: {avg_amplitude:.2f}, 最大振幅: {max_amplitude}, RMS振幅: {rms_amplitude:.2f}")
    sleep(0.05)  # 与切片时长同步,保证实时性

# 等待播放结束
while pygame.mixer.get_busy():
    pass
sleep(0.2)

方案二:使用pydub + simpleaudio(适合大体积MP3流式处理)

如果MP3文件较大,用Sound加载会占用过多内存,可采用pydub实现流式切片播放,逐块计算振幅,更节省内存。

前置依赖安装(树莓派)

  • 安装ffmpeg(pydub依赖它解码MP3):
sudo apt update && sudo apt install ffmpeg
  • 安装Python库:
pip install pydub simpleaudio numpy

代码示例

from pydub import AudioSegment
from pydub.playback import play
import numpy as np
from time import sleep

output_file = "sound.mp3"

# 加载MP3音频
audio = AudioSegment.from_mp3(output_file)
sample_rate = audio.frame_rate
channels = audio.channels
sample_width = audio.sample_width

# 按50ms为单位拆分音频块
chunk_duration_ms = 50
audio_chunks = audio[::chunk_duration_ms]

# 定义播放并分析单个音频块的函数
def process_chunk(chunk):
    # 播放当前块
    play(chunk)
    # 将块的原始数据转为numpy数组
    dtype = np.int16 if sample_width == 2 else np.int8
    samples = np.frombuffer(chunk.raw_data, dtype=dtype)
    # 处理立体声
    if channels == 2:
        samples = samples.reshape(-1, 2)[:, 0]
    # 计算振幅
    avg_amp = np.mean(np.abs(samples))
    rms_amp = np.sqrt(np.mean(samples**2))
    print(f"实时振幅 - 平均: {avg_amp:.2f}, RMS: {rms_amp:.2f}")

# 逐块处理音频
for chunk in audio_chunks:
    process_chunk(chunk)

注意事项

  • 振幅计算方式可按需选择,RMS值更接近人耳实际感受到的音量大小
  • 树莓派性能有限,切片时长建议保持在30-100ms区间,过短可能导致播放卡顿

内容的提问来源于stack exchange,提问作者Reto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 05:34:57