概要
スピーカーやヘッドフォンから出力されるシステム音を録音します。
デモ
環境
Windows 10とUbuntu 18.04での動作を確認しました。
インストール
SoundCardとSoundFileをインストールします。
pip install SoundCard
pip install SoundFile
ドキュメントによると、LinuxでSoundFileを使うためにはlibsndfileをaptなどのパッケージマネージャーでインストールする必要があるようです。
ソースコード
GitHubにも置いてあります。
import soundcard as sc
import soundfile as sf
output_file_name = "out.wav" # 出力するファイル名
samplerate = 48000 # サンプリング周波数 [Hz]
record_sec = 5 # 録音する時間 [秒]
with sc.get_microphone(id=str(sc.default_speaker().name), include_loopback=True).recorder(samplerate=samplerate) as mic:
# デフォルトスピーカーから録音
data = mic.record(numframes=samplerate*record_sec)
# マルチチャンネルで保存したい場合は、"data=data[:, 0]"を"data=data"に変更
sf.write(file=output_file_name, data=data[:, 0], samplerate=samplerate)
説明
with sc.get_microphone(id=str(sc.default_speaker().name), include_loopback=True).recorder(samplerate=samplerate) as mic:
get_microphone().recorder()で録音をするインスタンスを取得します。include_loopbackをTrueにすると、スピーカーやヘッドフォンなどから録音するインスタンスを取得できます。idとして、SoundCardが定めるデバイスのID(int型)かデバイスの名前(str型)が使えます。今回は現在システム音を出力しているデバイスから録音したいので、idをシステムのデフォルトのデバイスの名前にします。
data = mic.record(numframes=samplerate*record_sec)
record()でデバイスから録音します。1秒間にsamplerateフレームだけ録音されます。今回はrecord_sec秒間だけ録音したいので、numframesをsamplerate*record_secとします。録音したデータはnumpyの配列として、変数に格納されます。
sf.write(file=output_file_name, data=data[:, 0], samplerate=samplerate)
write()を使ってnumpyの配列をwavファイルとして出力します。モノラルで保存したい場合はdata=data[:, 0]とします。マルチチャンネルで保存したい場合はdata=dataとします。
上手く動かない条件
プログラムを開始するときに無音だと、プログラムが指定した秒数を待たずに終了してしまいます。現在、原因は不明です。ライブラリのバグかもしれないため、Issueを開きました( https://github.com/bastibe/SoundCard/issues/166 )。追記:Windowsにおけるこのバグはmasterブランチでは取り除かれました。リリースはまだです( https://github.com/bastibe/SoundCard/pull/167 )。