質問: Herokuに関する質問ですが.heroku上でシェルのコマンドを実行することはできますか? ローカルの環境では,Pythonスクリプト内に記載したコマンド ``` "sox -t raw -r 16k -e signed -b 16 -B -c 1 " + tmp + binary_file + " " + sound_dir + wav_file ``` を実行すると,正常にwavファイルが作成されますが, heroku上でそのスクリプトを起動するとうまくいきません. 試しに, heroku run bashとして,シェルコマンドを使用できるようにしてみたのですが, ``` bash: sox: command not found ``` となって,リモートの環境にsoxコマンドがないことが原因の1つのようです. 先のコマンドをremoteのheroku上で実行するようにできますでしょうか.
回答: こちら にも書きましたが、単にPCMファイルをWAVファイルに変換するだけであれば、わざわざ**sox** を使わなくても、Pythonの標準ライブラリの wave を使って簡単に行うことができます。 簡単ですがサンプルを書いてみましたので参考にしてください。 > > 今回のデータが**ビックエンディアン**とのことなので struct をつかって**リトルエンディアン** に変換しております。この部分はもう少しスマートな方法があるかもしれません。 > > > ``` import wave from struct import pack, unpack # pcmデータの読み込み with open("test.pcm", "rb") as f: data = f.read() # ビックエンディアン->リトルエンディアン変換 lst = unpack(">{}h".format(int(len(data)/2)), data) data = pack("{}h".format(len(lst)), *lst) #wavファイルに書き込み with wave.open("test.wav", "w") as wav: wav.setnchannels(1) # 1ch wav.setsampwidth(2) # 16bit wav.setframerate(16000) # 16k wav.writeframes(data) ``` #### エンディアン変換の補足 行っていることは 「バイト配列(バイナリデータ)」→「Int型のリスト(実データ)」→「バイト配列」 です。 順番に説明しますと、 まず第1ステップとして `struct.unpack()` にてバイナリデータを実データに変換します。 その際にどのようなフォーマットで変換するかは第一引数にて指定します。 今回の場合は * ビックエンディアン(*'>'*) * 1つデータは2Byte(*'h'*) なので `">##h"` としております。(ここで **##**には変換するデータ数が入りますので、`format()` を使用して、もとのバイナリ長の1/2の値を入れております。) > > ここで変換されたデータは実データとなりますので、信号処理や波形表示などを行う場合はこの**lst** を使うことができます。(一般的には **lst**はLR交互のデータなので、更に `l,r=lst[0::2],lst[1::2]` などとしてLRを分離して使用することになります。) > > > で、次のステップとして `struct.pack()` にて再度、Int配列をバイナリデータに変換しております。 ここも同様にフォーマット指定が必要な為、 * リトルエンディアン(*'<'* :省略可能) * 1つデータは2Byte(*'h'*) の `"##h"` を指定しております。(**##**には変換するデータ数を入れる必要がありますので、`format()` を使用して、実データのサイズを入れております。) structパッケージの詳細に関しては、公式ドキュメントを見てください。 以上です。