[英]Trying to convert an mp3 file to a Numpy Array, and ffmpeg just hangs
我正在使用 Scikit-learn 研究音樂分類方法,該過程的第一步是將音樂文件轉換為 numpy 數組。
在嘗試從 python 腳本調用 ffmpeg 失敗后,我決定直接將文件通過管道輸入:
FFMPEG_BIN = "ffmpeg"
cwd = (os.getcwd())
dcwd = (cwd + "/temp")
if not os.path.exists(dcwd): os.makedirs(dcwd)
folder_path = sys.argv[1]
f = open("test.txt","a")
for f in glob.glob(os.path.join(folder_path, "*.mp3")):
ff = f.replace("./", "/")
print("Name: " + ff)
aa = (cwd + ff)
command = [ FFMPEG_BIN,
'-i', aa,
'-f', 's16le',
'-acodec', 'pcm_s16le',
'-ar', '22000', # ouput will have 44100 Hz
'-ac', '1', # stereo (set to '1' for mono)
'-']
pipe = sp.Popen(command, stdout=sp.PIPE, bufsize=10**8)
raw_audio = pipe.proc.stdout.read(88200*4)
audio_array = numpy.fromstring(raw_audio, dtype="int16")
print (str(audio_array))
f.write(audio_array + "\n")
問題是,當我運行該文件時,它會啟動 ffmpeg,然后什么都不做:
[mp3 @ 0x1446540] Estimating duration from bitrate, this may be inaccurate
Input #0, mp3, from '/home/don/Code/Projects/MC/Music/Spaz.mp3':
Metadata:
title : Spaz
album : Seeing souns
artist : N*E*R*D
genre : Hip-Hop
encoder : Audiograbber 1.83.01, LAME dll 3.96, 320 Kbit/s, Joint Stereo, Normal quality
track : 5/12
date : 2008
Duration: 00:03:50.58, start: 0.000000, bitrate: 320 kb/s
Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 320 kb/s
Output #0, s16le, to 'pipe:':
Metadata:
title : Spaz
album : Seeing souns
artist : N*E*R*D
genre : Hip-Hop
date : 2008
track : 5/12
encoder : Lavf56.4.101
Stream #0:0: Audio: pcm_s16le, 22000 Hz, mono, s16, 352 kb/s
Metadata:
encoder : Lavc56.1.100 pcm_s16le
Stream mapping:
Stream #0:0 -> #0:0 (mp3 (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
它只是坐在那里,掛着,比歌曲長得多。 我在這里做錯了什么?,
我推薦你 pymedia 或 audioread 或decoder.py。 還有 pyffmpeg 和類似的模塊可以做你想做的事。 看看 pypi.python.org。
當然,這些不會幫你把數據變成numpy數組。
無論如何,這就是使用管道到 ffmpeg 粗略地完成的方式:
from subprocess import Popen, PIPE
import numpy as np
def decode (fname):
# If you are on Windows use full path to ffmpeg.exe
cmd = ["./ffmpeg.exe", "-i", fname, "-f", "wav", "-"]
# If you are on W add argument creationflags=0x8000000 to prevent another console window jumping out
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
data = p.communicate()[0]
return np.fromstring(data[data.find("data")+4:], np.int16)
這就是它應該如何用於基本用途。
它應該可以工作,因為 ffmpeg 的輸出默認是 16 位音頻。 但是如果你亂來,你應該知道 numpy 沒有 int24,所以你將被迫做一些位操作並將 24 位音頻表示為 32 位音頻。 只是,不要使用 24 位,世界就快樂了。 :D
如果您需要更復雜的東西,我們可能會在注釋中討論改進代碼。
這是我正在使用的:它使用pydub (使用 ffmpeg)和scipy 。
完整設置(在 Mac 上,在其他系統上可能有所不同):
pip install scipy
pip install pydub
brew install ffmpeg # Or probably "sudo apt-get install ffmpeg on linux"
然后閱讀mp3:
import tempfile
import os
import pydub
import scipy
import scipy.io.wavfile
def read_mp3(file_path, as_float = False):
"""
Read an MP3 File into numpy data.
:param file_path: String path to a file
:param as_float: Cast data to float and normalize to [-1, 1]
:return: Tuple(rate, data), where
rate is an integer indicating samples/s
data is an ndarray(n_samples, 2)[int16] if as_float = False
otherwise ndarray(n_samples, 2)[float] in range [-1, 1]
"""
path, ext = os.path.splitext(file_path)
assert ext=='.mp3'
mp3 = pydub.AudioSegment.from_mp3(file_path)
_, path = tempfile.mkstemp()
mp3.export(path, format="wav")
rate, data = scipy.io.wavfile.read(path)
os.remove(path)
if as_float:
data = data/(2**15)
return rate, data
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.