首页 > 编程语言 >python 计算两个录音文件延迟

python 计算两个录音文件延迟

时间:2024-08-14 16:38:19浏览次数:14  
标签:ffmpeg python 录音 delay periods file print silence 延迟

需求

a和b通讯,两人都将通话进行录音,现在要计算两段录音的延迟

原理

录音会有静音片段,通过程序识别到静音片段(比如小于-40dB为静默),计算静音片段的开始和结束时间,两个录音的时间相减得到延迟。

系统环境,依赖库

python安装pydub库。

电脑下载ffmpeg,官网下载压缩包,解压后设置环境变量,将ffmpeg的...\bin路径放到系统环境变量的PATH

使用ffmpeg -version如果能发现版本信息输出,说明成功。

但是python程序仍然可能调用不了ffmpeg,下面代码中又手动设置了ffmpeg的路径。

下面的代码解析的是.wav的音频文件,可以使用ffmpeg -i a.mp3 a.wav先进行修改文件格式(不能强制修改拓展名!),也可以调AudioSegment.from_mp3这个函数去处理.mp3文件

代码

# E:\ffmpeg\ffmpeg-master-latest-win64-gpl\bin
# C:\\Users\\loneve\\Desktop\\a.mp3
import subprocess

from pydub import AudioSegment
from pydub.silence import detect_silence
from pydub import AudioSegment
import os


def detect_silence_periods(audio_file, file_name="Undefined", silence_thresh=-40, min_silence_len=1000):
    print("计算文件:" + file_name + " 的静音片段")
    # silence_thresh表示静音的阈值,小于这个dB的会被认为是静音
    # min_silence_len表示静音最小时间段(毫秒为单位,小于这个时间段就认为不是静音)
    # 加载音频文件
    audio = AudioSegment.from_wav(audio_file)

    # 检测静音片段,返回的是静音的开始和结束时间的列表
    silence_periods = detect_silence(audio, min_silence_len=min_silence_len, silence_thresh=silence_thresh)
    # 将时间单位从毫秒转换为秒
    silence_periods = [(start / 1000.0, end / 1000.0) for start, end in silence_periods]
    print(silence_periods)
    return silence_periods


def calculate_delay(silence_periods_a, silence_periods_b):
    # 假设静音片段在两个录音文件中的顺序一致
    delays = []
    for (start_a, end_a), (start_b, end_b) in zip(silence_periods_a, silence_periods_b):
        delay_start = start_b - start_a
        delay_end = end_b - end_a
        delays.append((delay_start, delay_end))

    # 平均计算得到的延迟
    avg_delay_start = sum(delay[0] for delay in delays) / len(delays)
    avg_delay_end = sum(delay[1] for delay in delays) / len(delays)

    return avg_delay_start, avg_delay_end


def read_files(dic_path, file_format):
    # 读取该路径下所有文件,放到一个list中
    # 将该路径下所有文件通过ffmpeg转化成相应格式的文件,放到应该list中
    print("读取中...")
    print("===============")
    converted_files = []
    for file_name in os.listdir(dic_path):
        file_path = os.path.join(dic_path, file_name)
        output_file = os.path.splitext(file_path)[0] + f".{file_format}"
        # ffmpeg转化文件格式
        # command = f"ffmpeg -i \"{file_path}\" \"{output_file}\""
        # subprocess.run(command, shell=True)
        converted_files.append(file_path)  # output_file
    return converted_files


def handle_calculate(file_list):
    for i in range(0, len(file_list), 2):
        file1 = file_list[i]
        file2 = file_list[i + 1] if i + 1 < len(file_list) else None

        if file2:
            print("开始处理 " + file1.split("\\")[-1] + " " + file2.split("\\")[-1] + ": ")
            # 处理逻辑
            # 检测静音片段
            silence_a = detect_silence_periods(file1, file1.split("\\")[-1])
            silence_b = detect_silence_periods(file2, file2.split("\\")[-1])
            # 计算平均延迟
            avg_delay_start, avg_delay_end = calculate_delay(silence_a, silence_b)
            print(f"平均延迟开始: {avg_delay_start} 秒")
            print(f"平均延迟结束: {avg_delay_end} 秒")
            print("===============")
        else:
            print(file1.split("\\")[-1] + "没有文件与之对比!")


# 手动设置ffmpeg路径
AudioSegment.ffmpeg = r"E:\ffmpeg\ffmpeg-master-latest-win64-gpl\bin\ffmpeg.exe"
AudioSegment.converter = r"E:\ffmpeg\ffmpeg-master-latest-win64-gpl\bin\ffmpeg.exe"

# 读入数据,要处理的文件夹路径
dic_path = r"E:\audios"
file_format = "wav"
try:
    files = read_files(dic_path, file_format)
    if len(files) % 2 != 0:
        print("文件分组失败!")
    else:
        handle_calculate(files)
except FileNotFoundError:
    print("未找到文件!")
else:
    print("success")

'''
# 示例文件路径
# 注意,源文件格式如果是.m4a,就要使用ffmpeg -i a.m4a a.wav 进行格式转换,不能直接重名名修改拓展名来修改,这样会解码错误。
audio_file_a = r'E:\PythonProgram\pythonProject\mp3\d.wav'
audio_file_b = r'E:\PythonProgram\pythonProject\mp3\e.wav'
# 检测静音片段
silence_periods_a = detect_silence_periods(audio_file_a, audio_file_a.split("\\")[-1])
silence_periods_b = detect_silence_periods(audio_file_b, audio_file_b.split("\\")[-1])
# 计算延迟
avg_delay_start, avg_delay_end = calculate_delay(silence_periods_a, silence_periods_b)
print(f"平均延迟开始: {avg_delay_start} 秒")
print(f"平均延迟结束: {avg_delay_end} 秒")
'''

效果

image

image

标签:ffmpeg,python,录音,delay,periods,file,print,silence,延迟
From: https://www.cnblogs.com/rdisheng/p/18359305

相关文章