音頻響度分析和獲取

来源:https://www.cnblogs.com/petty/archive/2020/04/12/12688519.html
-Advertisement-
Play Games

# -*- 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')

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 介面不能創建對象,但是可以被實現(`implements` ,類似於被繼承)。一個實現介面的類(可以看做是介面的子類),需要實現介面中所有的抽象方法,創建該類對象,就可以調用方法了,否則它必須是一個抽象類。 介面:是功能的集合(介面中定義的都是方法) 定義介面使用的也是.java文件;編譯生成的也是 ...
  • 1. Struts2配置項細節 1.1.導入外部xml文件 在struts.xml文件中使用<include>標簽,file屬性上引入外部的.xml文件。 example.xml配置中又分隔了另外一個action,package一般不同。具體如下: 這樣做的目的是為了拆分struts.xml中過多的 ...
  • 基本語法(一) 程式的基本結構 Java程式的基本形式 Java語言是面向對象的語言。Java程式主要以類的形式存在,也叫Class,類也是Java程式的最小程式單位。 Java程式要求所有執行語句、方法都必須放在類里。 最簡單的Java程式: 在上面的 Hello 類中,只是一個空類的定義,沒有任 ...
  • 思維 我們只需看與根節點直接相連的邊權權值是1的有幾條,就可判斷以該節點為根節點而開始游戲的勝者,奇數->先手勝 偶數->後手勝。 ...
  • 梯度提升樹(GBDT)的全稱是Gradient Boosting Decision Tree。GBDT還有很多的簡稱,例如GBT(Gradient Boosting Tree), GTB(Gradient Tree Boosting ),GBRT(Gradient Boosting Regressi ...
  • 方法一(手動取cookie) 臨時用一次時,直接將 cookie 複製到 headers 里 方法二(selenium取cookie) 用 selenium 登錄,取 cookie 保存,再添加到 requests 中使用 再次用到時,再陸續更新... 方法三(requests取cookie) ...
  • 被static修飾的成員屬於類,不屬於對象。static修飾的成員被多個對象共用。 定義和使用格式 類變數 static 數據類型 變數名; static int num = 5; 該類的每個對象都"共用"同一個類變數的值。任何對象都可以更改該類變數的值,但也可以在不創建該類的對象的情況下對類變數進 ...
  • 一、synchronized關鍵字 1.我們修改一下上一次連載中的withdraw方法 //synchronized關鍵字添加到成員方法上去可以達到同步記憶體變數的目的 public synchronized void withdraw(double money) { double after = t ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...