当前位置: 首页 > news >正文

简单音频比较

简单的音频比较

频谱算法

import os
import numpy as np
import matplotlib.pyplot as plt
from pydub import AudioSegment
from imagehash import phash
from PIL import Image
import ioimport random
import timedef audio_to_spectrogram(audio_path, output_path=None, return_bytes=False):"""将音频文件转换为频谱图:param audio_path: 音频文件的路径:param output_path: 频谱图的输出路径,如果为None则不保存到文件:param return_bytes: 是否返回字节形式的频谱图:return: 如果return_bytes为True,返回内存中的图像字节;否则返回None"""audio = AudioSegment.from_file(audio_path)samples = np.array(audio.get_array_of_samples())if audio.channels == 2:samples = samples.reshape((-1, 2))samples = samples.mean(axis=1)print(f'处理音频: {audio_path}')plt.figure(figsize=(10, 4))plt.specgram(samples, Fs=audio.frame_rate, NFFT=1024, noverlap=512)plt.axis('off')# 保存到内存if return_bytes or not output_path:buf = io.BytesIO()plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0)buf.seek(0)# 如果同时需要保存到文件if output_path:plt.savefig(output_path, bbox_inches='tight', pad_inches=0)print(f'频谱图已保存至: {output_path}')plt.close()return buf.getvalue() if return_bytes else buf# 只保存到文件if output_path:plt.savefig(output_path, bbox_inches='tight', pad_inches=0)print(f'频谱图已保存至: {output_path}')plt.close()return Nonedef get_audio_perceptual_hash(audio_path):"""获取音频的感知哈希值:param audio_path: 音频文件的路径:return: 音频的感知哈希值"""# 直接获取内存中的频谱图数据spectrogram_buffer = audio_to_spectrogram(audio_path, return_bytes=False)# 从内存数据创建PIL图像对象image = Image.open(spectrogram_buffer)# 计算感知哈希hash_value = phash(image)return hash_valuedef compare_audio_similarity(audio_path1, audio_path2):"""对比两个音频文件的相似性:param audio_path1: 第一个音频文件的路径:param audio_path2: 第二个音频文件的路径:return: 汉明距离,值越小表示越相似"""hash1 = get_audio_perceptual_hash(audio_path1)hash2 = get_audio_perceptual_hash(audio_path2)hamming_distance = hash1 - hash2return hamming_distanceif __name__ == "__main__":audio_path1 = "audio1.wav"audio_path2 = "audio2.wav"print(compare_audio_similarity(audio_path1, audio_path2))

dtw比较

import librosa
import numpy as np
from librosa.sequence import dtw
import matplotlib.pyplot as plt
import matplotlib
# 设置matplotlib支持中文显示
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
matplotlib.rcParams['axes.unicode_minus'] = False  # 正常显示负号from pathlib import Path
import time
import logginglogger = logging.getLogger(__name__)def compare_audio_dtw(audio1_path, audio2_path, chunk_duration=1.0, visualize=False, save_dir=None):"""使用DTW算法分析audio1的每个片段在audio2中的位置和相似度参数:audio1_path: 第一个音频文件路径(会被分段)audio2_path: 第二个音频文件路径(完整搜索空间)chunk_duration: 每个分段的时长(秒)visualize: 是否生成MFCC可视化图像save_dir: 可视化图像保存目录,如果为None则为'images'返回:list: 包含每个片段的匹配信息的列表,每项为(片段索引, 匹配时间点, 相似度得分)"""start_time = time.time()# 创建可视化保存目录if visualize:save_dir = save_dir or 'images'img_dir = Path(save_dir)if not img_dir.exists():img_dir.mkdir(parents=True, exist_ok=True)# === 加载音频 ===logger.info(f"加载音频文件: {audio1_path}, {audio2_path}")y1, sr = librosa.load(audio1_path, sr=None, res_type='kaiser_fast', offset=0.0, duration=None, mono=True)y2, _ = librosa.load(audio2_path, sr=sr, res_type='kaiser_fast', mono=True)  # 保持同采样率logger.info(f"{audio1_path} 采样率: {sr}")logger.info(f"{audio2_path} 采样率: {sr}")# === 参数设置 ===chunk_samples = int(chunk_duration * sr)num_chunks = len(y1) // chunk_sampleslogger.info(f"音频1 总共 {num_chunks} 段,每段 {chunk_duration} 秒")# 结果列表results = []# === 对每段做 DTW 匹配 audio2 ===for i in range(num_chunks):chunk = y1[i * chunk_samples : (i + 1) * chunk_samples]mfcc_chunk = librosa.feature.mfcc(y=chunk, sr=sr, n_mfcc=13)mfcc2 = librosa.feature.mfcc(y=y2, sr=sr, n_mfcc=13)# 可视化 mfcc_chunk 和 mfcc2if visualize:plt.figure(figsize=(12, 6))# 显示第一个音频片段的MFCCplt.subplot(1, 2, 1)plt.imshow(mfcc_chunk, aspect='auto', origin='lower')plt.title(f'MFCC - audio1 segment {i}')plt.ylabel('MFCC coefficients')plt.xlabel('Frames')plt.colorbar(format='%+2.0f dB')# 显示第二个音频文件的MFCCplt.subplot(1, 2, 2)plt.imshow(mfcc2, aspect='auto', origin='lower')plt.title('MFCC - audio2 full file')plt.ylabel('MFCC coefficients')plt.xlabel('Frames')plt.colorbar(format='%+2.0f dB')plt.tight_layout()plt.savefig(f'{img_dir}/mfcc_comparison_{i}.png')  # 保存图像到文件plt.close()  # 关闭图形以避免内存问题# 计算DTWD, wp = dtw(mfcc_chunk, mfcc2, subseq=True, metric='euclidean')# 找到最佳匹配位置best_idx = np.argmin(D[-1])best_time = librosa.frames_to_time(best_idx, sr=sr)# 获取最小代价和归一化相似度min_cost = D[-1, best_idx]max_possible_cost = np.max(D)similarity_score = 1 - (min_cost / max_possible_cost) if max_possible_cost > 0 else 1# 添加到结果列表results.append((i, best_time, similarity_score))logger.info(f"第{i}段 匹配位置: {best_time:.2f} 秒,相似度: {similarity_score:.2f}")# 计算耗时elapsed_time = time.time() - start_timelogger.info(f"分析完成,耗时: {elapsed_time:.2f} 秒")return resultsdef format_results(results):"""格式化结果为易读的字符串"""output = []for idx, time_pos, score in results:output.append(f"片段 {idx}: 在 {time_pos:.2f} 秒处匹配,相似度 {score:.2f}")return "\n".join(output)if __name__ == "__main__":# 设置基本日志配置logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s',datefmt='%Y-%m-%d %H:%M:%S')# 示例用法audio1_path = "audio1.wav"audio2_path = "audio2.wav"results = compare_audio_dtw(audio1_path, audio2_path, visualize=True)print("\n匹配结果:")print(format_results(results))

相关文章:

  • 信息科技伦理与道德3-4:面临挑战
  • 前端与后端开发详解:从概念到就业技能指南
  • 【零基础】Ubuntu22.04本地部署Dify
  • Nginx 核心功能笔记
  • 案例解析:基于量子计算的分子对接-QDOCK(Quantum Docking)
  • 告别碎片化!两大先进分块技术如何提升RAG的语义连贯性?
  • ImageDataGenerator ()用法简介
  • 排序算法详解笔记(二)
  • 测试——BUG篇
  • C++算法(17):reverse函数用法详解,头文件<algorithm>与实战示例
  • Linux基础篇、第一章_01_2安装虚拟机手动安装Rocky Linux 9.5
  • CentOS一键安装MySQL5.7(源码安装)
  • PHP代码-服务器下载文件页面编写
  • tarjan缩点+强联通分量
  • 数据库day-08
  • 医药生产的“神助攻”:疆鸿智能JH-ECT012,EtherCAT转CC LINK IE超靠谱
  • 如何有效保护iOS应用?分享一款实用的IPA混淆工具
  • Java高频面试之并发编程-10
  • 【无需安装额外软件,JavaScript脚本】B站批量取消关注
  • Consul安装部署(Windows环境)
  • 中国海油总裁:低油价短期影响利润,但也催生资产并购机会
  • 阿迪达斯一季度营收增近13%,称美国加征关税对业绩带来不确定性
  • 78家公募年度业绩比拼:23家营收净利双升,十强座次微调
  • 向总书记汇报具身智能发展的“稚辉君”:从期待到兴奋再到备受鼓舞
  • 华夏银行一季度营收降逾17%、净利降逾14%,公允价值变动损失逾24亿
  • 古籍新书·2025年春季|中国土司制度史料集成