2012-02-08 17 views
6

Chcę reprezentować plik audio na obrazku o maksymalnym rozmiarze 180 × 180 pikseli.Generowanie miniatury dowolnego pliku audio

Chcę wygenerować ten obraz, aby jakoś dał reprezentację pliku audio, myślę o nim jak o fali SoundCloud (wykres amplitudy)?.

Screenshot of Soundcloud's player

Zastanawiam się, czy ktoś z was ma coś do tego. Szukałem trochę, głównie "audio wizualizacji" i "miniatury audio", ale nie znalazłem nic przydatnego.

Po pierwsze posted this to ux.stackexchange.com, to jest moja próba dotarcia do programistów pracujących nad tym.

+0

Czy chcesz zrobić narzędzie do tego lub chcesz mieć wcześniej istniejące rozwiązanie? – Koof

+0

To nie jest spektrogram, to wykres amplitudowy. Spektrogramy audio są trójwymiarowe: zwykle czas na osi X, częstotliwość na y oraz amplituda reprezentowana przez kolor. –

+0

Dziękuję Josh Caswell, jak widzisz, nie byłem pewien co do nazwy tego przedstawienia przebiegu. – joar

Odpowiedz

3

Można również podzielić dźwięk na kawałki i zmierzyć RMS (miarę głośności). powiedzmy, że chcesz mieć obraz o szerokości 180 pikseli.

użyję pydub, otoki lekki napisałem wokół lib std wave modeule:

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) 

pętli for może być reprezentowana jako poniższej listy zrozumienia, po prostu chciałem to być jasne :

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

teraz myśleć tylko do zrobienia jest skalowania RMS w dół do 0 - skali 180 (ponieważ obraz ma być 180px wysoki)

max_rms = max(loudness_of_chunks) 

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

Zostawię rysunek rzeczywistych pikseli do ciebie, nie jestem bardzo doświadczony z PIL lub ImageMagick:/

+0

Najpierw konwertuj 'max_rms' na float. To pomaga. – Remco

1

podstawie odpowiedzi Jiaaro'S (dzięki za pisanie pydub!), A zbudowany dla Web2py tutaj moje dwa centy:

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