近日在django項(xiàng)目中采用了librosa來分析用戶上傳的音頻,主要是對(duì)其做一定間隔的采樣用于繪制波形圖。在本地(MacOS)上工作正常,部署到Ubuntu服務(wù)器后,自己手動(dòng)用python方式運(yùn)行django的server時(shí),工作都是正常的,然而當(dāng)我用superviosr掛起之后就一直報(bào)NoBackendError的錯(cuò)誤,反復(fù)檢查了FFmpeg的安裝,應(yīng)該是沒有問題的。網(wǎng)上搜了一下沒有看到比較合適的解決辦法,故不得不自己讀源碼來調(diào)試了。
由于我的程序中只采用了librosa.load這個(gè)命令,通過源代碼可以發(fā)現(xiàn)librosa實(shí)際上是用audioread這個(gè)庫的audioread.audio_open來讀取音頻文件的。這個(gè)函數(shù)的源代碼如下:
def audio_open(path):
"""Open an audio file using a library that is available on this
system.
"""
# Standard-library WAV and AIFF readers.
from . import rawread
try:
return rawread.RawAudioFile(path)
except DecodeError:
pass
# Core Audio.
if _ca_available():
from . import macca
try:
return macca.ExtAudioFile(path)
except DecodeError:
pass
# GStreamer.
if _gst_available():
from . import gstdec
try:
return gstdec.GstAudioFile(path)
except DecodeError:
pass
# MAD.
if _mad_available():
from . import maddec
try:
return maddec.MadAudioFile(path)
except DecodeError:
pass
# FFmpeg.
from . import ffdec
try:
return ffdec.FFmpegAudioFile(path)
except DecodeError:
pass
# All backends failed!
raise NoBackendError()
可見之前我們遇到的NoBackendError就是這里的最后一行拋出的了,由于我安裝的FFmpeg,進(jìn)一步進(jìn)入ffdec.py這個(gè)文件中。不難發(fā)現(xiàn)實(shí)際打開文件的是下面這個(gè)函數(shù):
def popen_multiple(commands, command_args, *args, **kwargs):
"""Like `subprocess.Popen`, but can try multiple commands in case
some are not available.
`commands` is an iterable of command names and `command_args` are
the rest of the arguments that, when appended to the command name,
make up the full first argument to `subprocess.Popen`. The
other positional and keyword arguments are passed through.
"""
for i, command in enumerate(commands):
cmd = [command] + command_args
try:
return subprocess.Popen(cmd, *args, **kwargs)
except OSError:
if i == len(commands) - 1:
# No more commands to try.
raise
這里的commands是直接傳入的第33行的COMMANDS變量
COMMANDS = ('ffmpeg', 'avconv')
我這里倒騰了好幾下,最終發(fā)現(xiàn)實(shí)際是錯(cuò)誤的原因是沒有找到ffmpeg這個(gè)命令。我們?cè)谶@里將ffmpeg替換成ffmpeg的絕對(duì)路徑。你可以通過下面這行命令找到。
which ffmpeg
最終我改成了
COMMANDS = ('/usr/bin/ffmpeg', 'avconv')
Boom!一切就工作正常了。這么想起來應(yīng)該是安裝ffmpeg的時(shí)候的環(huán)境變量有問題,導(dǎo)致在command line方式下調(diào)用ffmpeg命令出錯(cuò)吧。