2012-02-08 3 views
6

Desidero rappresentare un file audio in un'immagine con una dimensione massima di 180 × 180 pixel.Genera miniatura per file audio arbitrario

voglio generare questa immagine in modo che si dà in qualche modo una rappresentazione del file audio, pensare ad esso come forma d'onda (grafico ampiezza) di SoundCloud?.

Screenshot of Soundcloud's player

Mi chiedo se qualcuno di voi ha qualcosa per questo. Ho cercato un po ', principalmente "visualizzazione audio" e "audio thumbnailing", ma non ho trovato nulla di utile.

I primo posted this to ux.stackexchange.com, questo è il mio tentativo di raggiungere tutti i programmatori che lavorano su questo.

+0

Vuoi fare uno strumento per fare questo o vuoi una soluzione preesistente? – Koof

+0

Questo non è uno spettrogramma, è un grafico di ampiezza. Gli spettrogrammi dell'audio sono tridimensionali: solitamente il tempo sull'asse x, la frequenza su ye l'ampiezza rappresentata dal colore. –

+0

Grazie Josh Caswell, come vedi, non ero sicuro del nome di questa rappresentazione di una forma d'onda. – joar

risposta

2

Date un'occhiata a questo post del blog su wav2png.py.

3

È inoltre possibile suddividere l'audio in blocchi e misurare l'RMS (una misura del volume). diciamo che vuoi un'immagine di 180 pixel di larghezza.

userò pydub, un involucro leggero ho scritto tutto il 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) 

il ciclo for può essere rappresentato come il seguente elenco di comprensione, volevo solo che fosse chiaro :

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

Ora l'unica cosa che resta da fare è scalare le RMS verso il basso per un 0 - scala 180 (dal momento che si desidera che l'immagine sia 180px di altezza)

max_rms = max(loudness_of_chunks) 

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

Lascio il disegno dei pixel effettivi a voi, io non sono molto esperto con PIL o ImageMagik:/

+0

Convertire 'max_rms' in un float. Aiuta. – Remco

1

in base alla risposta del Jiaaro (grazie per la scrittura pydub!), E costruito per web2py ecco i miei due centesimi:

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