为任意音频文件生成缩略图

6 投票
2 回答
2093 浏览
提问于 2025-04-17 12:36

我想把一个音频文件用一张最大为180×180像素的图片来表示。

我想生成这张图片,让它能在某种程度上反映这个音频文件的内容,可以想象成像SoundCloud的波形图(振幅图)那样。

Soundcloud播放器的截图

我在想有没有人能帮我实现这个。我搜索了一段时间,主要是“音频可视化”和“音频缩略图”,但没有找到什么有用的东西。

我最开始在ux.stackexchange.com上发过这个问题,现在想试着联系一些正在做这个的程序员。

2 个回答

1

根据Jiaaro的回答(感谢他写了pydub!),这是我对web2py的一些看法:

def generate_waveform():
    img_width = 1170
    img_height = 140
    line_color = 180
    filename = os.path.join(request.folder,'static','sounds','adg3.mp3')


    # first I'll open the audio file
    sound = pydub.AudioSegment.from_mp3(filename)

    # break the sound 180 even chunks (or however
    # many pixels wide the image should be)
    chunk_length = len(sound) / img_width

    loudness_of_chunks = [
        sound[ i*chunk_length : (i+1)*chunk_length ].rms
        for i in range(img_width)
    ]
    max_rms = float(max(loudness_of_chunks))
    scaled_loudness = [ round(loudness * img_height/ max_rms)  for loudness in loudness_of_chunks]

    # now convert the scaled_loudness to an image
    im = Image.new('L',(img_width, img_height),color=255)
    draw = ImageDraw.Draw(im)
    for x,rms in enumerate(scaled_loudness):
        y0 = img_height - rms
        y1 = img_height
        draw.line((x,y0,x,y1), fill=line_color, width=1)
    buffer = cStringIO.StringIO()
    del draw
    im = im.filter(ImageFilter.SMOOTH).filter(ImageFilter.DETAIL)
    im.save(buffer,'PNG')
    buffer.seek(0)
    return response.stream(buffer, filename=filename+'.png')
3

你可以把音频分成小块,然后测量它们的RMS(这是一种衡量音量的方式)。假设你想要一张宽度为180像素的图片。

我会使用pydub,这是我为标准库中的wave模块写的一个轻量级封装:

from pydub import AudioSegment

# first I'll open the audio file
sound = AudioSegment.from_mp3("some_song.mp3")

# break the sound 180 even chunks (or however
# many pixels wide the image should be)
chunk_length = len(sound) / 180

loudness_of_chunks = []
for i in range(180):
    start = i * chunk_length
    end = chunk_start + chunk_length

    chunk = sound[start:end]
    loudness_of_chunks.append(chunk.rms)

这个for循环可以用下面的列表推导式来表示,我只是想让它更清晰:

loudness_of_chunks = [
    sound[ i*chunk_length : (i+1)*chunk_length ].rms
    for i in range(180)]

现在剩下的就是把RMS缩放到0到180的范围(因为你想要的图片高度是180像素)

max_rms = max(loudness_of_chunks)

scaled_loudness = [ (loudness / max_rms) * 180 for loudness in loudness_of_chunks]

至于实际绘制像素的部分就留给你了,我对PIL或ImageMagik不是很熟悉 :/

撰写回答