Raspberry Pi でインカム自作計画
目標設定
ステージ撮影をするカメラ担当数人と、PA ブースのスイッチャ 1人が通話できること。
背景など
現在の自作インカム2代目?は、音が小さいという問題に見舞われている。また初代は、声はある程度聞き取れるが、そこそこノイズがのっていてやや耳障りだった記憶がある。
この初代と 2代は、いずれも XLR 4 Pin 接続でアナログ伝送の方式だった。
そこで、デジタルで伝送するというアプローチはどうかと考えた。
具体的には、Raspberry Pi と PC の LAN 通信で音声を送ろうという試みである。
基本構成計画
カメラ側: クライアントとして稼働, Raspberry Pi
スイッチャ側: サーバとして稼働, PC
追加: ヘッドセットは USB 接続, これにより、信号取り込みをすべてライブラリ (OS) 任せにできる
- 通信方式: Websocket
- 双方向でリアルタイムな通信が可能なため
- 音声形式: 生データ伝送, 44100kHz, 16bit, 1ch
- インターネット経由でないネットワークなら十分なスピードが出るのではとの見積もり
- 概算 - 44100Hz * 16bit * 1ch * 3 カメラ * 2 (双方向) = 4233600bit/s ≒ 0.5MB/s
- 言語: いずれも Python
- ライブラリの充実さのため
ライブラリ選定
-
pydub
- 音声処理演算ライブラリ
- サーバ側ではクライアント音声&スイッチャ音声のミキシングをするため
- 2022/12/09 からしばらく更新無しでやや不安が残る・・・
-
sounddevice
- デバイスからの音声入力・出力ができる
- PortAudio というライブラリのラッパらしい
- 公式ドキュメントによると Mac と Windows は自動で PortAudio がインストールされるが、他では手動インストールが要るらしい
-
websockets
- Websocket ライブラリ
- これが最も有名?というかこれくらいしか知らない
- curses
- TUI を実装できる
- 標準ライブラリのため追加インストール不要
sounddevice 試し書き
公式リファレンスを参考に、以下は 0.05 秒毎にデータをやりとりできるサンプル (Ctrl-C で停止)
import sounddevice as sd
def callback(indata, outdata, frames, time, status):
print("---")
print(indata, end=", ")
print(frames)
outdata[:] = indata
try:
with sd.Stream(channels=1, samplerate=44100, blocksize=2205, dtype="int16", callback=callback):
while(True):
sd.sleep(1000)
except KeyboardInterrupt:
print("end")
クライアント実装イメージ
サーバ実装イメージ
- sounddevice での音声キャプチャ・再生
-
sounddevice の音声データ <-->
bytes
変換 - Websocket での音声データ伝送
- pydub での音声ミキシング
-
pydub.AudioSegment
<-->bytes
変換
クライアント側の実装について、新案としてスマートフォンを用いることを提唱。
Raspberry Pi + Python での実装を考えていたが、スマートフォン + Web (JavaScript) での実装を考案。
これにより、クライアント機に必要な自作回路は無くなる上、(WebApp でインストール不要のために) セットアップの手間が完全になくなる。
サーバ側について、Web サーバをやりながら TUI でミキサー操作をやる、というような動作を当初は考えていた。
だが、Web をやりながら同一端末上でミキサーコンソールを開く (キー入力待ちなども行う) という動作が、あまり安定しなかったり、サブプロセスを実装する必要があったりするのではないかとの懸念が出てきた。
そこで、ミキサーも Web で実装してしまい、Web サーバのコンソールは Web サーバのみ行うことを検討する。サーバ自体はマイク入力処理などを行わず、Websocket にのみ集中する。
サーバの実装を、Python + FastAPI から Deno に変更した。
これにより、パケット変換のコードを Python と JavaScript の両方で実装する必要はなくなり、JavaScript のみで済むようになった。必要なコード量が大幅に削減できた。
使用する言語は、Python が無くなったことになる。
概ね設計はまとまってきた。また、設計ドキュメントも、リポジトリの designs
ディレクトリにファイルを作ってまとめた。
本スクラップの役割は終わったのでクローズ。