質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

1回答

2698閲覧

mfccを求めるプログラムのエラーの解消

gopan

総合スコア19

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

0クリップ

投稿2016/10/26 05:05

###前提・実現したいこと
とあるサイトを参考にして類似楽曲検索システムの作成がしたいのですが、その第一歩にメル周波数ケプストラム係数(mfcc)を求めるプログラムを作成しました。実行してみたところ、以下のようなエラーが起きてしまいました。
なお、このエラーは自分が自宅で使用しているPCで起きたもので、大学の研究室のPCでは問題なく動作したのでプログラムが間違っているということは恐らくないと思います。一応下のほうにプログラムも載せておきます。
以上のことから自分のPCの開発環境などに問題があるとおもうのですが、そういったPCの環境構築に関して初心者と同じようなものなので、以下のエラーの解決方法が分かりません。
なので今回質問させていただきました。
どうかよろしくお願いします。

###発生している問題・エラーメッセージ

λ python mp3_to_mfcc.py mp3 mfcc raw lame: excess arg Greed.mp3' Could not find "temp.mp3". Can't init infile 'temp.mp3' sox FAIL formats: can't open input file `temp.wav': No such file or directory lame: excess arg temp.mp3 Could not find "temp.mp3". Can't init infile 'temp.mp3' sox FAIL formats: can't open input file `temp.wav': No such file or directory Could not find "'mp3\02-霈昴″縺ェ縺後i窶ヲ.mp3'". Could not find "temp.mp3". Can't init infile 'temp.mp3' sox FAIL formats: can't open input file `temp.wav': No such file or directory lame: excess arg temp.mp3 Could not find "temp.mp3". Can't init infile 'temp.mp3' sox FAIL formats: can't open input file `temp.wav': No such file or directory lame: excess arg temp.mp3 Could not find "temp.mp3". Can't init infile 'temp.mp3' sox FAIL formats: can't open input file `temp.wav': No such file or directory

###該当のソースコード

python

1#coding:utf-8 2import os 3import sys 4 5# mp3_to_mfcc.py 6# usage: python mp3_to_mfcc.py [mp3dir] [mfccdir] [rawdir] 7# ディレクトリ内のMP3ファイルからMFCCを抽出する 8 9def mp3ToRaw(mp3File, rawFile): 10 # mp3を16kHz, 32bitでリサンプリング 11 os.system("lame --resample 16 -b 32 -a '%s' temp.mp3" % mp3File) 12 # mp3をwavに変換 13 os.system("lame --decode temp.mp3 temp.wav") 14 # wavをrawに変換 15 os.system("sox temp.wav %s" % rawFile) 16 os.remove("temp.mp3") 17 os.remove("temp.wav") 18 19def calcNumSample(rawFile): 20 # 1サンプルはshort型(2byte)なのでファイルサイズを2で割る 21 filesize = os.path.getsize("temp.raw") 22 numsample = filesize / 2 23 return numsample 24 25def extractCenter(inFile, outFile, period): 26 # 波形のサンプル数を求める 27 numsample = calcNumSample(inFile) 28 29 fs = 16000 30 center = numsample / 2 31 start = center - fs * period 32 end = center + fs * period 33 34 # period*2秒未満の場合は範囲を狭める 35 if start < 0: start = 0 36 if end > numsample - 1: end = numsample - 1 37 38 # SPTKのbcutコマンドで切り出す 39 os.system("bcut +s -s %d -e %d < '%s' > '%s'" \ 40 % (start, end, "temp.raw", rawFile)) 41 42def calcMFCC(rawFile, mfccFile): 43 # サンプリング周波数: 16kHz 44 # フレーム長: 400サンプル 45 # シフト幅 : 160サンプル 46 # チャンネル数: 40 47 # MFCC: 19次元 + エネルギー 48 os.system("x2x +sf < '%s' | frame -l 400 -p 160 | mfcc -l 400 -f 16 -n 40 -m 19 -E > '%s'" 49 % (rawFile, mfccFile)) 50 51if __name__ == "__main__": 52 if len(sys.argv) != 4: 53 print "usage: python mp3_to_mfcc.py [mp3dir] [mfccdir] [rawdir]" 54 sys.exit() 55 56 mp3Dir = sys.argv[1] 57 mfccDir = sys.argv[2] 58 rawDir = sys.argv[3] 59 60 if not os.path.exists(mfccDir): 61 os.mkdir(mfccDir) 62 if not os.path.exists(rawDir): 63 os.mkdir(rawDir) 64 65 for file in os.listdir(mp3Dir): 66 if not file.endswith(".mp3"): continue 67 mp3File = os.path.join(mp3Dir, file) 68 mfccFile = os.path.join(mfccDir, file.replace(".mp3", ".mfc")) 69 rawFile = os.path.join(rawDir, file.replace(".mp3", ".raw")) 70 71 try: 72 # MP3を変換 73 mp3ToRaw(mp3File, "temp.raw") 74 75 # 中央の30秒だけ抽出してrawFileへ 76 extractCenter("temp.raw", rawFile, 15) 77 78 # MFCCを計算 79 calcMFCC(rawFile, mfccFile) 80 81 print "%s => %s" % (mp3File, mfccFile) 82 83 # 後片付け 84 os.remove("temp.raw") 85 except: 86 continue

###試したこと
SPTK、lame、soxは無事にインストールされていると思うので、環境変数に間違いがあると思い見直したのですが、間違いはないと思います。

###補足情報
○自宅PC
OS : Windows10
コンソール : cmder
エディター : VScode
python2系

○研究室PC
OS : Linux
コンソール : Terminal
エディター : emacs
python2系

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

コマンドラインの引数のエスケープのしかたはオペレーティングシステムによって違います。今回の場合で言うと、引数を'...'で囲うのはUnix系のシェルの多くで動作しますが、Windowsのcmd.exeでは期待通りにならないようです。いずれにせよ、ファイル名に'が入っていればうまく動きません。

さらに言うと、誰かがファイル名を工夫したファイルを作って処理するファイルにまぎれこませておくことで、質問者さんがプログラムを実行したときにlame以外の任意のコマンドを実行させることもできてしまいます。恐ろしいことです。

subprocess.call()などではコマンドライン文字列の代わりに引数のシーケンスを渡せるので、シェルの引数処理にかかわる上のような問題が起きません。

lang

1import subprocess 2... 3 4subprocess.call(['/path/to/lame', '--resample', '16', '-b', '32', '-a', mp3File, 'temp.mp3'])

(11/04 10:19のコメント後に追記)

リダイレクトについては次のように書けると思います。

lang

1fdin = open('temp.raw', 'rb') 2fdout = open(rawFile, 'wb') 3subprocess.call(['bcut', '+s', '-s', str(start), '-e', str(end)], stdin=fdin, stdout=fdout) 4

open()の第2引数の「'rb'」「'wb'」は、Linuxの場合は「'r'」「'w'」でもかまわないのですが、Windowsではbが必要です。

投稿2016/10/29 02:18

編集2016/11/04 03:17
ikedas

総合スコア4227

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gopan

2016/10/31 08:57

ご指摘いただいたことを考えまして、Cygwin上で動かしてみたところ、正常に動きました。 色々教えていただきありがとうございました。
gopan

2016/11/04 01:13

現在、色々ありまして回答いただいたようなやり方を試しているのですが、 os.system("bcut +s -s %d -e %d < '%s' > '%s'" \ % (start, end, "temp.raw", rawFile)) この部分はどのようにしたら良いのでしょうか?
gopan

2016/11/04 01:19

連続してすみません。 ちなみに今は3系の最新バージョンを使用しています。
gopan

2016/11/09 23:56

本当に何度もすみません os.system("x2x +sf < '%s' | frame -l 400 -p 160 | mfcc -l 400 -f 16 -n 40 -m 19 -E > '%s'"      % (rawFile, mfccFile)) この部分はどのようにしたら良いのでしょうか?
ikedas

2016/11/10 04:06

うむ。 複数のsubprocess.call()に分けて処理することもできますが、大変ですね。 ファイル名以外の部分は変数ではなく決まった文字列なので、回答に書いたような危険はないですね。だから、以下のようにしてもいいのでは。 fdin = open(rawFile, 'rb') fdout = open(mfccFile, 'wb') subprocess.call('x2x +sf | frame -l 400 -p 160 | mfcc -l 400 -f 16 -n 40 -m 19 -E', stdin=fdin, stdout=fdout, shell=True)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問