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

OpenCV中音频的表示机制及提取音频dB值的方法咨询

问题描述

我写了一个试图读取视频帧关联音频信号的函数:

import cv2

def read_audio_frames(file_path):
    # Open the video file
    video = cv2.VideoCapture(file_path)

    # Get audio properties
    frame_rate = video.get(cv2.CAP_PROP_FPS)
    num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))

    # Read the audio frames
    audio_frames = []
    for _ in range(num_frames):
        ret, frame = video.read()
        
        if not ret:
            break
        
        audio_frames.append(frame)
    
    # Release the video object
    video.release()

    return audio_frames

调用后执行以下代码:

# Read audio frames
audio_frames = read_audio_frames(file_path)

audio_frames[0] # 每个分离的音频帧
len( audio_frames[0][0] ) #=  1080,搞不懂为什么和采样率44100有关
audio_frames[0][0][0]

得到结果:

array([3, 1, 1], dtype=uint8)

我有几个疑惑:

  • 目标音频是立体声,但结果返回三个值而非两个通道对应的值;而且uint8的0-255范围不符合音频常用的16bit、24bit、32bit位深。
  • 维度对应关系存疑:audio_frames[0]对应视频帧,但audio_frames[0][0]并没有对应采样率44100的音频采样点。
  • 不同MP4文件的维度结果不同:
len(audio_frames[0])=300
len(audio_frames[0][0])=1920
len(audio_frames[0][0][0])=3

len(audio_frames[0][0])和音频采样数不匹配。

请问OpenCV中音频是如何表示的?我该如何编写函数提取音频的dBs值?


解答

OpenCV的音频处理误区

你完全搞错了——OpenCV根本不支持读取视频中的音频数据。你写的函数里,video.read()返回的frame是视频的图像帧,不是音频帧:

  • 你看到的array([3,1,1], dtype=uint8)是图像像素的BGR三个通道值(OpenCV默认用BGR格式存储图像),和音频没有任何关系。
  • 维度len(audio_frames[0])是图像的高度,len(audio_frames[0][0])是图像的宽度,第三个维度是BGR通道数,不同MP4的维度差异其实是视频分辨率不同导致的,和音频完全无关。

正确提取音频并计算dB值的方法

要处理视频中的音频,得用专门的音视频处理库,比如ffmpeg-python结合librosa来实现:

步骤1:安装依赖

pip install ffmpeg-python librosa numpy

步骤2:提取音频并计算dB值的函数

import ffmpeg
import librosa
import numpy as np

def get_audio_dbs(file_path):
    # 用ffmpeg从视频中提取音频,转为PCM格式
    out, _ = (
        ffmpeg
        .input(file_path)
        .output('pipe:', format='s16le', acodec='pcm_s16le', ac=2, ar='44100')
        .run(capture_stdout=True)
    )
    
    # 将二进制数据转为int16格式的numpy数组
    audio_data = np.frombuffer(out, dtype=np.int16)
    # 分离立体声通道
    audio_data = audio_data.reshape(-1, 2)
    
    # 将音频数据转为-1到1的浮点数范围,用于计算dB
    audio_float = audio_data / np.iinfo(np.int16).max
    
    # 计算每个采样点的dBFS值(加1e-10避免log(0)报错)
    dbs = 20 * np.log10(np.abs(audio_float) + 1e-10)
    
    return dbs, audio_float.shape[0], 44100  # 返回dB数组、总采样数、采样率

调用示例

dbs, sample_count, sample_rate = get_audio_dbs("your_video.mp4")
print(f"采样率: {sample_rate},总采样数: {sample_count}")
print(f"第一个采样点左声道dB值: {dbs[0][0]:.2f},右声道dB值: {dbs[0][1]:.2f}")

补充:计算时间段平均dB

如果需要计算某段时间内的平均音量,可以对dB数组做滑动窗口平均:

# 计算每100ms的平均dB
window_size = int(sample_rate * 0.1)
avg_dbs = np.array([
    np.mean(dbs[i:i+window_size], axis=0)
    for i in range(0, sample_count - window_size, window_size)
])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:00:26