1. 程式人生 > >介紹幾個python的音頻處理庫

介紹幾個python的音頻處理庫

sys.argv 先來 方式 type begin format ani tags sts

  一、eyeD3

  直接在google上搜索python mp3 process ,推薦比較多的就是這個第三方庫了。先來看看官方介紹吧。

About

eyeD3 is a Python tool for working with audio files, specifically mp3 files containing ID3 metadata (i.e. song info).

It provides a command-line tool (eyeD3) and a Python library (import eyed3) that can be used to write your own applications or plugins that are callable from the command-line tool.

For example, to set some song information in an mp3 file called song.mp3:

$ eyeD3 -a Nobunny -A "Love Visions" -t "I Am a Girlfriend" -n 4 song.mp3

簡單來說,eyeD3 這個庫只要是用來處理MP3文件的,特別是帶ID3 metadata的文件(一般MP3文件都會帶有一些額外信息,比如說歌手、專輯之類的,後面會說怎麽提取這些信息)。eyeD3 提供了兩種使用方法,一種是使用command line 直接在命令行中執行 eyeD3 --...就可以對MP3進行處理,還有一種是在python中使用 import eyed3 導入。

上面的例子就是官方提供的一個使用eyeD3 命令行執行的語句,-a 是 --artist 的簡寫,即添加歌手信息,-A 是 --album的簡寫,即添加專輯信息,-t 是 --title的簡寫,即添加歌曲名字,-n 是 --track-num 的簡寫,即添加磁道數。這些一般都是 MP3文件ID3 tag 的默認屬性。我們如果直接輸入 eyeD3 song.mp3 就會直接顯示歌曲的基本信息,大概長下面這個樣子:

$ eyeD3 song.mp3

song.mp3      [ 3.06 MB ]
-------------------------------------------------------------------------
ID3 v2.4:
title: I Am a Girlfriend
artist: Nobunny
album: Love Visions
album artist: Various Artists
track: 4
-------------------------------------------------------------------------
如果你在windows下使用eyeD3,也許你會發現直接在cmd中輸入eyeD3 會提示找不到這個命令,我就遇到了這個問題。
因為我是直接pip安裝的,去site-packages目錄下,沒有找到名為 eyeD3.exe的可執行文件,全部是.py文件,官網對此沒有說明,
去google上找了半天也沒有找到相應的解決辦法。沒辦法,只好轉到linux下試一下了。linux下pip install eyeD3 之後,然後在
shell執行 eyeD3 song.mp3 是沒有問題的。下圖1是我在ubuntu14下的執行結果(部分):
技術分享

                              圖1

可以看出確實常見的信息都顯示出來了。順便提一下一個事情,這首MP3是我從win下直接傳到unix下的,以前我在windows與linux下互傳文件都是通過類似百度雲的方式來傳遞的,
但是這種傳遞方式有時候太過於麻煩。所以我在網上搜索了一下,發現了Putty這個好東西。PuTTY is an SSH and telnet client, developed originally by Simon Tatham for the Windows platform. 
PuTTY is open source software that is available with source code and is developed and supported by a group of volunteers.
即Putty是一個SSH(安全外殼協議)遠程登錄客戶端,專門在windows下使用的。下載地址在這:http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html。下載安裝之後,打開putty,然後會出現如下的界面(圖2):
技術分享

                              圖2
這個時候,打開你的linux機器,當然我的是裝在vmware虛擬機裏面的了,在shell裏面輸入ifconfig 命令,找到你的linux ip地址,如下圖3所示:
技術分享
                            圖 3

比如我的機器的地址就是 192.168.152.130。然後將這個ip地址填入 圖2 的Host Name 一欄,註意默認端口為22,不要去改它,然後點擊open,就會彈出一個登陸界面,接著輸入你在linux
下登陸的用戶名和密碼就可以ssh連上linux啦。http://www.infoworld.com/article/2617683/linux/linux-moving-files-between-unix-and-windows-systems.html這篇文章介紹了
幾種在unix與windows之間傳遞文件的方法。我只講第一種,使用putty的pscp的secure copy(安全拷貝)。你安裝了putty之後,會自帶一個叫 pscp.exe的可執行文件,將其目錄加入windows
環境變量。然後 cmd執行命令 pscp myfile.txt [email protected]:/home/shs 即可以把你的文件 myfile.txt 復制到 linux 下的 /home/shs 目錄下了。解釋一下,你在執行的時候需要把shs
換成你的用戶名,@後面跟你的linux ip地址, /home/shs 是你要把文件移動的位置。執行完之後,文件就會成功拷貝過去了。其他方法不講了,有興趣可以自行搜索,或者看我上面說的那篇文章。
  回到正題,eyeD3 命令行講完之後,再來說下如何在Python中使用。還是看官方給的例子吧:
 1 import eyed3
 2 
 3 audiofile = eyed3.load("song.mp3")
 4 audiofile.tag.artist = u"Nobunny"
 5 audiofile.tag.album = u"Love Visions"
 6 audiofile.tag.album_artist = u"Various Artists"
 7 audiofile.tag.title = u"I Am a Girlfriend"
 8 audiofile.tag.track_num = 4
 9 
10 audiofile.tag.save()

上面的代碼,使用 import eyed3 導入eyeD3 庫,然後使用load方法加載mp3文件,後面的幾行分別是設置 artist,album等等 ID3 tag ,直接看代碼就能看出來,就不說了。如果想顯示mp3文件內部的ID3 tag信息,直接print 相應的tag就行了,比如 print(audiofile.tag.artist)等等,當然,前提是你的MP3 metadata得儲存了這些信息。其實還有一些更復雜和高級的用法,我就不講了,大家有興趣直接去官方文檔看吧,地址:http://eyed3.nicfit.net/index.html。eyeD3 主要就是處理 MP3文件的metadata的,至於解析音頻之類的就得用其他的庫了。

二、pydub

  第一個介紹的eyeD3 一般只能處理MP3文件,功能上相對來說也是比較簡單一點。下面介紹的pydub庫就要強大的多。老規矩,還是
先看一下它的官方介紹:
Manipulate audio with a simple and easy high level interface http://pydub.com 就一句話,簡單,易用的處理音頻
的高度抽象的接口,嘿,這不就是我們要找的麽。github項目地址為:https://github.com/jiaaro/pydub/ 有1800多的star,說明這個
庫還是很受歡迎的。安裝直接很簡單,直接 pip install pydub 就可以安裝。但是需要註意的是:

Dependencies


You can open and save WAV files with pure python. For opening and saving non-wav files – like mp3 – you‘ll need ffmpeg orlibav.

這裏是說python自帶的wave模塊只能處理 wav 格式的音頻文件,如果要想處理類似MP3格式的文件,就得要裝 ffmpeg或者libav了。

什麽是ffmpeg 呢?

A complete, cross-platform solution to record, convert and stream audio and video.

ffmpeg 是一個跨平臺的 可以用來 記錄、轉化音頻與視頻的工具,如果你做過數字信號處理方面的工作,對它應該不陌生。還有一個libav,其實是從ffmpeg分出來的一個分支,功能和 ffmpeg差不多,二者你任選一個下載就可以了。windows下直接選擇可執行文件安裝即可。

還是看官網的例子來介紹吧。

I:打開 mp3或者mp4等文件

可以采用如下的命令:

 1 from pydub import AudioSegment
 2 
 3 song = AudioSegment.from_wav("never_gonna_give_you_up.wav")
 4 song = AudioSegment.from_mp3("never_gonna_give_you_up.mp3")
 5 
 6 ogg_version = AudioSegment.from_ogg("never_gonna_give_you_up.ogg")
 7 flv_version = AudioSegment.from_flv("never_gonna_give_you_up.flv")
 8 
 9 mp4_version = AudioSegment.from_file("never_gonna_give_you_up.mp4", "mp4")
10 wma_version = AudioSegment.from_file("never_gonna_give_you_up.wma", "wma")
11 aac_version = AudioSegment.from_file("never_gonna_give_you_up.aiff", "aac")

可以打開任何 ffmpeg支持的文件類型,從上面可以看出,主要有 from_filetype()方法,filetype為具體的文件類型,比如 wav,mp3等

或者通用的 from_file()方法,但是這個方法必須在第二個參數指定打開文件的類型,返回的結果都是 AudioSegment對象。

II:切割音頻

1 # pydub does things in milliseconds
2 ten_seconds = 10 * 1000
3 
4 first_10_seconds = song[:ten_seconds]
5 
6 last_5_seconds = song[-5000:]

註意pydub中的標準時間為毫秒,上面的代碼就得到了音樂的前10秒和後5秒,非常簡單。

III:調整音量

1 # boost volume by 6dB
2 beginning = first_10_seconds + 6
3 
4 # reduce volume by 3dB
5 end = last_5_seconds - 3

+6 就表示將音樂的音量提高6分貝,-3就表示將音樂的音量降低3分貝

IV: 拼接兩段音樂

without_the_middle = beginning + end
without_the_middle.duration_seconds

拼接之後的音樂時長是兩段音樂時長之和,可以通過 .duration_seconds方法來獲取一段音樂的時長。這與使用 len(audio)/1000.0得到的結果是一樣的。

V:將音樂翻轉(reverse)

1 # song is not modified
2 # AudioSegments are immutable
3 backwards = song.reverse()

註意 AudioSegment 對象是不可變的,上面使用reverse 方法不會改變song這個對象,而是會返回一個新的AudioSegment對象,其他的方法也是這樣,需要註意。reverse簡單來說就是 將音樂從尾部向頭部開始逆序播放,我試了一下,發現轉換之後還真的挺有意思的。

VI:crossfade(交叉漸入漸出方法)

1 # 1.5 second crossfade
2 with_style = beginning.append(end, crossfade=1500)

crossfade 就是讓一段音樂平緩地過渡到另一段音樂,上面的crossfade = 1500 表示過渡的時間是1.5秒。

VII:repeat(重復音樂片段)

# repeat the clip twice
do_it_over = with_style * 2

上面的代碼讓音樂重復播放兩次

VIII:fade in and fade out(逐漸增強與逐漸減弱)

# 2 sec fade in, 3 sec fade out
awesome = do_it_over.fade_in(2000).fade_out(3000)

逐漸增強2秒,逐漸減弱3秒

XI:save(保存)

awesome.export("mashup.mp3", format="mp3")

awesome.export("mashup.mp3", format="mp3", tags={artist: Various artists, album: Best of 2011, comments: This album is awesome!})

這裏展示了兩種保存的形式,都是使用export方法,要指定保存的格式,使用format 參數,但第二種方法多了一個tags參數,其實看一下應該就很容易明白,是保存 歌曲ID3 tag信息的。

以上只是pydub 使用方法的初步介紹,還有其他非常多的功能,請自行移步官方API 文檔:https://github.com/jiaaro/pydub/blob/master/API.markdown

介紹的非常詳細。

三、PyAudio


又是一個功能強大的處理音頻庫。官方介紹:

PyAudio provides Python bindings for PortAudio, the cross-platform audio I/O library. With PyAudio, you can easily use Python to play and record audio on a variety of platforms. PyAudio is inspired by:

  • pyPortAudio/fastaudio: Python bindings for PortAudio v18 API.
  • tkSnack: cross-platform sound toolkit for Tcl/Tk and Python.

Pyaudio 提供了對於跨平臺的 PortAudio(處理 audio輸入輸出的庫)的綁定,PyAudio可以讓你輕松錄制與播放音頻。

廢話不多說,直接看官方文檔(https://people.csail.mit.edu/hubert/pyaudio/docs/)提供的一個quick start 的代碼

 1 """PyAudio Example: Play a wave file."""
 2 
 3 import pyaudio
 4 import wave
 5 import sys
 6 
 7 CHUNK = 1024
 8 
 9 if len(sys.argv) < 2:
10     print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
11     sys.exit(-1)
12 
13 wf = wave.open(sys.argv[1], rb)
14 
15 # instantiate PyAudio (1)
16 p = pyaudio.PyAudio()
17 
18 # open stream (2)
19 stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
20                 channels=wf.getnchannels(),
21                 rate=wf.getframerate(),
22                 output=True)
23 
24 # read data
25 data = wf.readframes(CHUNK)
26 
27 # play stream (3)
28 while len(data) > 0:
29     stream.write(data)
30     data = wf.readframes(CHUNK)
31 
32 # stop stream (4)
33 stream.stop_stream()
34 stream.close()
35 
36 # close PyAudio (5)
37 p.terminate()

當然,這個提供的是使用命令行參數接收音頻文件的形式,CHUNK 是一次讀取的音頻byte數量,p = pyaudio.PyAudio()初始化一個

PyAudio對象,然後使用其open方法打開一個輸入輸出流,這裏指定了output=True說明這是一個輸出流,即我們是往stream中添加data,如果這裏改為 input = True就是變成輸入流了,一般是從設備的標準 audio device ,對於電腦來說可能就是麥克風了,來讀取音頻data。使用wave打開一個 .wav 文件,然後使用 readframes方法每次讀取 CHUNK 這麽多的數據,將數據寫入 stream,直到讀完為止。寫入stream的audio data 就會不斷通過麥克風播放出來了,於是我們就可以聽到音樂了。最後在結束的時候,註意要關閉相應的對象以釋放資源。

還有一種方法是使用callback(回調函數)函數,代碼如下:

 1 """PyAudio Example: Play a wave file (callback version)."""
 2 
 3 import pyaudio
 4 import wave
 5 import time
 6 import sys
 7 
 8 if len(sys.argv) < 2:
 9     print("Plays a wave file.\n\nUsage: %s filename.wav" % sys.argv[0])
10     sys.exit(-1)
11 
12 wf = wave.open(sys.argv[1], rb)
13 
14 # instantiate PyAudio (1)
15 p = pyaudio.PyAudio()
16 
17 # define callback (2)
18 def callback(in_data, frame_count, time_info, status):
19     data = wf.readframes(frame_count)
20     return (data, pyaudio.paContinue)
21 
22 # open stream using callback (3)
23 stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
24                 channels=wf.getnchannels(),
25                 rate=wf.getframerate(),
26                 output=True,
27                 stream_callback=callback)
28 
29 # start the stream (4)
30 stream.start_stream()
31 
32 # wait for stream to finish (5)
33 while stream.is_active():
34     time.sleep(0.1)
35 
36 # stop stream (6)
37 stream.stop_stream()
38 stream.close()
39 wf.close()
40 
41 # close PyAudio (7)
42 p.terminate()

不細說了。

下面來看一個使用pyaudio + numpy + pylab 可視化音頻的代碼,下面的代碼打開電腦的麥克風,然後接受音頻輸入,再以圖像的形式展示出來。

 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Fri May 12 10:30:00 2017
 4 @author: Lyrichu
 5 @description: show the sound in graphs
 6 """
 7 import pyaudio
 8 import numpy as np
 9 import pylab
10 import time
11 
12 RATE = 44100
13 CHUNK = int(RATE/20) # RATE/number of updates per second
14 
15 def sound_plot(stream):
16     t1 = time.time() # time starting
17     data = np.fromstring(stream.read(CHUNK),dtype = np.int16)
18     pylab.plot(data)
19     pylab.title(i)
20     pylab.grid()
21     pylab.axis([0,len(data),-2**8,2**8])
22     pylab.savefig("sound.png",dpi=50)
23     pylab.show(block = False)
    time.sleep(0.5)
24 pylab.close(all) 25 print("took %.2f ms." % (time.time() - t1)*1000) 26 27 if __name__ == __main__: 28 p = pyaudio.PyAudio() 29 stream = p.open(format = pyaudio.paInt16,channels = 1,rate = RATE, 30 input = True,frames_per_buffer = CHUNK) 31 for i in range(int(20*RATE/CHUNK)): 32 # for 10 seconds 33 sound_plot(stream) 34 stream.stop_stream() 35 stream.close() 36 p.terminate()

代碼應該比較容易理解。得到的大概是像下面這樣的圖形(圖4):

技術分享

圖 4

需要註意的是,如果不是在交互式命令下執行pylab或者matplotlib的plot命令,其plt.show()函數是一個block函數,這會導致最後的

plt.close(‘all‘) 關閉所有的窗口只會在手動關閉了圖像之後才會執行,所有我們無法看到連續變化的圖像,為了解決這個問題,我們將plt.show()函數block參數設為False,這樣show函數就不是block函數了,可以直接執行plt.close(‘all‘)命令,為了不因為圖像刷新太快我們看不清變化,所以使用time.sleep(0.5) 暫停0.5秒。

其實還沒介紹完,還有pygame模塊(python的一個做遊戲的模塊)以及librosa庫(專業的數字信號處理庫)等沒有講,等有機會再更吧。敬請關註!






介紹幾個python的音頻處理庫