音频响度分析和获取
程序员文章站
2022-11-21 09:27:20
# -*- coding: utf-8 -*-#/usr/local/bin/python3# @Time : 2020/3/7 4:05 PM# @Author : eric# @File : get_audio_loudness.py# @Software: PyCharmimport osim ......
# -*- coding: utf-8 -*-
#/usr/local/bin/python3
# @time : 2020/3/7 4:05 pm
# @author : eric
# @file : get_audio_loudness.py
# @software: pycharm
import os
import re
import subprocess
import sys
import csv
'''
说明:
integrated loudness:
i(整体响度): -26.5 lufs
threshold: -37.1 lufs
loudness range:
lra(整体范围): 10.2 lu
threshold: -49.5 lufs
lra low: -36.9 lufs
lra high: -26.6 lufs
mean_volume(平均音量): -32.2 db
max_volume(最大音量): -18.9 db
'''
'''
:param '/users/yy/documents/test_noise/agc/android_new/test_saopin_32bit.wav'
:return {'i': '-26.5', 'lra': ' 10.2', 'threshold': '-49.5', 'lra_low': '-36.9', 'lra_high': '-26.6', 'mean_volume': '-32.2', 'max_volume': '-18.9'}
# 音频整体响度/音量获取方法,输出文件
'''
def get_audio_loudness_by_file(audiofile):
lufs_i = r"\s+i:\s+([-+\s]\d+\.\d) lufs"
lufs_threshold = r"\s+threshold:\s+([-+\s]\d+\.\d) lufs"
lufs_lra = r"\s+lra:\s+([-+\s]\d+\.\d) lu"
luss_lrs_low = r"\s+lra low:\s+([-+\s]\d+\.\d) lufs"
luss_lrs_high = r"\s+lra high:\s+([-+\s]\d+\.\d) lufs"
mean_volume = r"\[parsed_volumedetect_0 @ \w+\] mean_volume:\s(-\d+\.\d) db"
max_volume = r"\[parsed_volumedetect_0 @ \w+\] max_volume:\s(-\d+\.\d) db"
cmd_lufs = 'ffmpeg -nostats -i {0} -filter_complex ebur128 -f null -'
cmd_db = 'ffmpeg -i {0} -af "volumedetect" -f null -'
dict_loudnes = {}
output = subprocess.getstatusoutput(cmd_lufs.format(audiofile))
if output:
lines = output[1].splitlines()
end_match = 0
for i in range(len(lines)):
if 'target:-23 lufs' in lines[i]:
for j in range(i+1, len(lines)):
line = lines[j]
if 'i:' in line:
match = re.search(lufs_i, line)
if match:
dict_loudnes['i(lufs)'] = match.group(1)
if 'threshold:' in line:
match = re.search(lufs_threshold, line)
if match:
dict_loudnes['threshold(lufs)'] = match.group(1)
if 'lra:' in line:
match = re.search(lufs_lra, line)
if match:
dict_loudnes['lra(lu)'] = match.group(1)
if 'lra low:' in line:
match = re.search(luss_lrs_low, line)
if match:
dict_loudnes['lra_low(lufs)'] = match.group(1)
if 'lra high' in line:
match = re.search(luss_lrs_high, line)
if match:
dict_loudnes['lra_high(lufs)'] = match.group(1)
end_match = 1
break
if end_match:
break
output_db = subprocess.getstatusoutput(cmd_db.format(audiofile))
if output_db:
match = re.search(mean_volume, output_db[1])
if match:
dict_loudnes['mean_volume(db)'] = match.group(1)
match = re.search(max_volume, output_db[1])
if match:
dict_loudnes['max_volume(db)'] = match.group(1)
return dict_loudnes
'''
:param '/users/yy/documents/test_noise/agc/android_new'
:return write csv file
'''
def get_audio_loudness_by_path(file_path):
audio_loudness_list = []
file_path = os.path.abspath(file_path)
for file in os.listdir(file_path):
if file.endswith('.mp3') or file.endswith('wav'):
dict_loudnes = get_audio_loudness_by_file(os.path.join(file_path, file))
dict_loudnes['audio_name'] = file
audio_loudness_list.append(dict_loudnes)
print(audio_loudness_list)
csvname = os.path.join(file_path, os.path.basename(file_path) + '.csv')
print(csvname)
with open(csvname, 'w', encoding='utf-8-sig') as f:
writer = csv.dictwriter(f, fieldnames=['audio_name', 'i(lufs)', 'threshold(lufs)', 'lra(lu)', 'lra_low(lufs)', 'lra_high(lufs)', 'mean_volume(db)', 'max_volume(db)'])
writer.writeheader()
writer.writerows(audio_loudness_list)
'''
:
:return 瞬时响度(由m标识)、短期响度(s)、综合响度(i)和响度范围(lra)
[parsed_ebur128_0 @ 0x7ff27302c900] t: 0.299979 target:-23 lufs m:-120.7 s:-120.7 i: -70.0 lufs lra: 0.0 lu
# 音频每100ms的瞬时响度(由m标识)、短期响度(s)、综合响度(i)和响度范围(lra)
'''
def get_audio_detail_loudness_by_file(audio_file):
ebur = r'\[parsed_ebur128_0 @ \w+\]\s+t:\s+(\d+[\.\d+]*)\s+target:(-\d+)\slufs\s+m:([-\s]*\d+\.\d)\s+s:([-\s]*\d+\.\d)\s+i:\s+([-\s]*\d+\.\d)\slufs\s+lra:\s+(\d+\.\d)\slu'
cmd_lufs = 'ffmpeg -nostats -i {0} -filter_complex ebur128 -f null -'
cmd = cmd_lufs.format(audio_file)
# print(cmd)
detail_list = []
output = subprocess.getstatusoutput(cmd)
if output:
lines = output[1].splitlines()
for line in lines:
match = re.search(ebur, line)
dict_loudnes = {}
if match:
dict_loudnes['time'] = match.group(1)
dict_loudnes['target(lufs)'] = match.group(2)
dict_loudnes['m(lufs)'] = match.group(3)
dict_loudnes['s(lufs)'] = match.group(4)
dict_loudnes['i(lufs)'] = match.group(5)
dict_loudnes['lra(lu)'] = match.group(6)
detail_list.append(dict_loudnes)
if len(detail_list) > 1:
csvname = audio_file + '.csv'
print(csvname)
dict_loudness = get_audio_loudness_by_file(audio_file)
info_str = 'agv_i={1}{0} lra_low={2}{0} lra_high={3}{0}'.format('lufs', dict_loudness['i(lufs)'], dict_loudness['lra_low(lufs)'], dict_loudness['lra_high(lufs)'])
info = [info_str]
print(dict_loudness)
with open(csvname, 'w', encoding='utf-8-sig') as f:
writer = csv.writer(f)
writer.writerow(info)
writer = csv.dictwriter(f, fieldnames=['time', 'target(lufs)', 'm(lufs)', 's(lufs)', 'i(lufs)',
'lra(lu)'])
writer.writeheader()
writer.writerows(detail_list)
def get_audio_detail_loudness_by_path(file_path):
file_path = os.path.abspath(file_path)
for root, dirs, files in os.walk(file_path):
for file in files:
if file.endswith('.mp3') or file.endswith('wav'):
print(os.path.join(root, file))
get_audio_detail_loudness_by_file(os.path.join(root, file))
if __name__ == "__main__":
print('xx')
test_file = '/users/yy/documents/test_noise/agc/android_new/test_saopin_32bit.wav'
get_audio_detail_loudness_by_file(test_file)
if len(sys.argv) > 1:
temp = sys.argv[1]
if os.path.isdir(temp):
print('path', temp)
get_audio_loudness_by_path(temp)
get_audio_detail_loudness_by_path(temp)
elif os.path.isfile(temp):
print('file', temp)
get_audio_loudness_by_file(temp)
else:
print(temp, 'is not exists')
else:
print('param need path or file')