转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn]
目录
这个问题隐藏的比较深,明明读取是对的,但就是报错:
或者我被迫改成48K,虽然读取的时长是对的,但返回为空数组:
用pydub.utils.mediainfo()去分析,可以发现,它对音频start_time=0的音频都会报这个错,而start_time != 0的就可以正确加载。
# pip install pydub
import pydub
mp3_file_path = "sample-000001.mp3"
print(pydub.utils.mediainfo(mp3_file_path))
这里提出了一个临时的、最简单粗暴解决方法:
load时候指定一下他的持续时间duration即可,但注意需要比真正的时长短一点且为整数。
import math
duration=math.floor(librosa.get_duration(filename=mp3_file_path))
y, sr = librosa.load(mp3_file_path, sr=48000, duration=duration)
缺点也很明显,后面的数据没有了:
方法太蠢了,不建议使用。
我发现他读取wav时候不会出现这个问题,因此我们可以先转为wav格式,然后在load。
sound = pydub.AudioSegment.from_mp3("sample-000001.mp3")
sound.export("sample-000001.wav", format="wav")
y, sr = librosa.load("sample-000001.wav", sr=44000)
这样就完整了:
推荐。
既然方案二中可以通过pydub正确读取mp3来导出wav,那我能不能直接通过pydub读取后转为librosa格式呢?一顿好找后:
import librosa
import numpy as np
import os
sr = 44000
sound = pydub.AudioSegment.from_file(mp3_file_path).set_frame_rate(sr)
channel_sounds = sound.split_to_mono()
samples = [s.get_array_of_samples() for s in channel_sounds]
y= np.array(samples).T.astype(np.float32)
y/= np.iinfo(samples[0].typecode).max
y = y.reshape(-1)
效果也是可以的:
推荐推荐。
一个想法是,既然方案一中的start_time=0会影响读取,那如果我直接把mp3文件的metadata中的start_time改成N/A或者0.0001,会不会也有用呢?不过暂时没有多找方法,因此这里没有尝试。
# Plot the signal stored in 'y'
from matplotlib import pyplot as plt
import librosa.display
plt.figure(figsize=(12, 3))
plt.title("Audio signal as waveform")
librosa.display.waveshow(y, sr=sr)
def audio_load1(file_path, sr):
'''直接使用pydub读取mp3,用librosa读取wav'''
if file_path.endswith('.mp3'):
sound = pydub.AudioSegment.from_file(file_path).set_frame_rate(sr)
channel_sounds = sound.split_to_mono()
samples = [s.get_array_of_samples() for s in channel_sounds]
y = np.array(samples).T.astype(np.float32)
y /= np.iinfo(samples[0].typecode).max
y = y.reshape(-1)
else:
y, sr = librosa.load(file_path, sr=sr)
return y, sr
def audio_load2(file_path, sr):
'''先尝试用pydub读取,失败则用librosa读取'''
try:
y, sr = librosa.load(file_path, sr=sr)
_ = y[0]
except Exception as e:
print('使用librosa读取失败,将转用pydub')
sound = pydub.AudioSegment.from_file(file_path).set_frame_rate(sr)
channel_sounds = sound.split_to_mono()
samples = [s.get_array_of_samples() for s in channel_sounds]
y = np.array(samples).T.astype(np.float32)
y /= np.iinfo(samples[0].typecode).max
y = y.reshape(-1)
return y, sr
欢迎补充!