Raspberry Piで音楽(wav/mp3)ファイルを再生する方法 python編

# pythonで音楽再生する方法
主な方法として以下の5つが挙げられます。

1. [pygame](#1pygame)
2. [PyAudio](#2pyaudio)
3. [vlc](#3vlc)
4. [aplay](#4aplay)
5. [mpg321](#5mpg321)

本投稿では、

* モジュールのインストール方法
* 各方法を使用するための簡易なコード
* エラー時の挙動、原因
* 音楽再生時のRaspberry Piの設定等(後述のおまけ参照)

を主に記していきます。

また、3.~5.はpythonからでなくともただRaspberry Piで音楽を再生したい場合によく使用されます。
4.のaplayはデフォルトで入っていますが、vlcあたりはインストールしておくとGUIベースで音楽再生・簡単な編集が行えるので、便利かと思います。

## 1.pygame

Raspberry Piのpythonパッケージにはpygameというモジュールがデフォルトでインストールされているそうです。
以下コード。

```python:audio_pygame.py
#!/usr/bin/env python
#-*- cording: utf-8 -*-

import pygame.mixer
import time

# mixerモジュールの初期化
pygame.mixer.init()
# 音楽ファイルの読み込み
pygame.mixer.music.load("ファイル名.mp3")
# 音楽再生、および再生回数の設定(-1はループ再生)
pygame.mixer.music.play(-1)

time.sleep(60)
# 再生の終了
pygame.mixer.music.stop()
```

mixer.musicは音楽再生用のモジュールです。mp3ファイルとoggファイルを読み込むことが出来ます。
<font color="red">※ 2017年2月12日 追記</font>
pygame.mixer.musicは<font color="red">wavファイル再生に対応していません</font>でした！

効果音などの短い音を鳴らすにはmixer.Soundモジュールを使うと良いです。
Soundモジュールならwavファイルを再生できますが、[500kB以下という制限があります。](https://www.raspberrypi.org/forums/viewtopic.php?f=32&t=36878)

詳しくは以下の日本語リファレンスをご参考ください。
[pygame.mixer全般](http://westplain.sakuraweb.com/translate/pygame/Mixer.cgi#pygame.mixer.Sound)
[pygame.mixer.music](http://westplain.sakuraweb.com/translate/pygame/Music.cgi)

## 2.PyAudio

まずはインストール方法。
LXTerminal(コマンドライン)でapt-get installします。

```LXTerminal
$ sudo apt-get install python-pyaudio python3-pyaudio
```
参考：[PyAudio](http://people.csail.mit.edu/hubert/pyaudio/)

コードは以下の通り。

```python:audio_PyAudio.py
#-*- cording: utf-8 -*-

import wave
import pyaudio

# チャンク数を指定
CHUNK = 1024
filename = "ファイル名.wav"

wf = wave.open(filename, 'rb')

# PyAudioのインスタンスを生成
p = pyaudio.PyAudio()

# Streamを生成
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                output=True)

"""
 format: ストリームを読み書きする際のデータ型
 channels: モノラルだと1、ステレオだと2、それ以外の数字は入らない
 rate: サンプル周波数
 output: 出力モード
"""

# データを1度に1024個読み取る
data = wf.readframes(CHUNK)

# 実行
while data != '':
    # ストリームへの書き込み
    stream.write(data)
    # 再度1024個読み取る
    data = wf.readframes(CHUNK)

# ファイルが終わったら終了処理
stream.stop_stream()
stream.close()

p.terminate()
```
参考：[たけし備忘録](http://takeshid.hatenadiary.jp/entry/2016/01/10/153503) 様

色々とググってみましたが、PyAudioでmp3ファイルを再生している例がありませんでした。
みなwavファイルです。

↑のプログラムから分かる通り、常時ストリーミングでデータの読み込みを行いながら音楽を再生します。

また、音が途切れ途切れに再生されることがあります。
Stack overflowにも[報告例](http://ja.stackoverflow.com/questions/23655/raspberry-piでpyaudioを使ってwavファイルが正常に鳴らない)がありましたが、根本的な解決はなされていないようです。
<font color="red">※ 2017年2月12日 追記</font>
途切れ途切れに再生される原因は、音楽ファイルのサンプルサイズ・サンプルレート・チャンネル数にあることが分かりました。
以下のようなwavファイルの再生を確認しました。特にサンプルサイズは、これ以上大きいと上手く再生ができません。

* サンプルサイズ: 16bit
* サンプルレート: 44100Hz
* チャンネル数: 2

## 3.vlc
以下からはsubprocessを使用したコマンド実行になります。

<font color="red">※ 2017年2月12日 追記</font>
[multiprocessing](http://docs.python.jp/2.6/library/multiprocessing.html)等でマルチスレッドを立てることで、suborocessを用いて音楽再生しながらpython上で別の処理を行うことができました。

まずはvlcをインストール。

```LXTerminal
$ sudo apt-get install vlc
```

すると以下のようにメニューにVLCメディアプレイヤーが追加されます。

<img width="300" alt="スクリーンショット 2016-12-02 02.12.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/130506/94ca5b13-6606-3049-3912-44661016dbc2.png">

開くとこんな感じ。

<img width="200" alt="スクリーンショット 2016-12-02 02.12.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/130506/af1759fb-3ee2-7a0c-c4a3-73768d732664.png">

これでGUIベースで音楽・ビデオ再生や編集ができるようになりました。
(vlcではwavファイルをmp3ファイルに変換することもできます。
参考：[ブログというより備忘録](http://ticklerfile.blogspot.jp/2013/09/vlcmp4mp3.html)様)

さて、vlcをコマンドライン上で操作するには2つの方法があります。

1. cvlcコマンドの利用
2. vlc -I rcコマンドの利用

今回は2.の方法で進めていきます。

```python:audio_vlc.py
#-*- cording: utf-8 -*-

import subprocess

subprocess.call("vlc -I rc --play-and-stop ファイル名.wav", shell=True)
```

再生を終わらせるためにはコマンドラインで

```LXTerminal
> stop
```

と打つ必要があります。もちろんCtrl+Cでも大丈夫ですが。

vlcはroot権限で再生ができません。
ので、プログラムの他のライブラリの関係でsudo実行しなければならない等の場合、vlcは使用できません。

vlcのコマンドは[野利庵日録](http://norian.blog50.fc2.com/blog-entry-118.html)様に一通り書いてあります。helpコマンドでも確認できます。
vlcには[公式Wiki](https://wiki.videolan.org/VLC/)が存在するので、そちらで探すのも良いでしょう。

そして、vlcはwavもmp3も再生可能です。ファイルサイズの上限等も無いようです。

今回はコマンドライン上での実行を紹介しましたが、[python-vlc](https://pypi.python.org/pypi/python-vlc/1.1.2)なるライブラリも存在するようです。
ネット上にはこのpython-vlc情報がとても少ないので、使用するにはexamplesのpyファイルを読み込むしか無さそうですね。

また、subprocessが初出なのでその話も少々。
os.system等のosモジュールは古いとして、[公式で使用が推奨されていない](http://docs.python.jp/2/library/subprocess.html)ようです。
なのでos.systemの代わりにsubprocess.callを使うのがこれからのナウでヤングなやり方だそうな。

## 4.aplay
aplayはLinuxにおける代表的な音楽再生コマンドです。
これもvlcと同じくsubprocessから呼び出します。

```python:audio_aplay.py
#-*- cording: utf-8 -*-

import subprocess

subprocess.call("aplay ファイル名.wav", shell=True)
```

サンプルサイズの大きさによって、以下のようなERRORが出ます。

```LXTerminal
aplay: set_params:1233: サンプルフォーマットが使用不可能
Available formats:
- U8
- S16_LE
```

pyAudioのときにもサンプルサイズの話は出ましたが、aplayでもサンプルサイズは16bitにしなければなりません。

aplayはvlcと違い、root権限で再生が行えます。なのでsudoでの処理が必要なときはこちらを用いると良いでしょう。

また、aplayはmp3ファイルを再生できません。wavのみです。
試しにmp3ファイルを再生してみたところ、ひたすらノイズが流れ続けました。
参考：[IT女子のラズベリーパイ入門奮闘記](http://deviceplus.jp/hobby/raspberrypi_entry_012/)様

## 5.mpg321
mp3ファイルを再生するためにmpg321というモジュールがあるそうです。
(正直、vlcさえインストールしてしまえば何でも出来てしまうのですが…)

まずはインストール。

```LXTerminal
$ sudo apt-get install mpg321
```

これらも3.や4.と同様にsubprocessでコマンド実行します。

```python:audio_mpg321.py
#-*- cording: utf-8 -*-

import subprocess

subprocess.call("mpg321 ファイル名.mp3", shell=True)
```

mpg321での動画再生等は上記の[IT女子ラスパイ奮闘記](http://deviceplus.jp/hobby/raspberrypi_entry_012/)様に詳細が記してあります。


# おまけ1：音楽出力先の指定
HDMIかイヤホンジャックかどちらから音楽出力するかを指定する方法として、

1. コマンドラインでの指定
2. raspi-configでの操作

の2種類があります。

## 1. コマンドラインでの操作

```LXTerminal
$ amixer cset numid=3 <1>
```

<>の部分が1でイヤホンジャック、2でHDMIでの出力になります。
0だと自動判別です。
参考：[Nosの日記](http://d.hatena.ne.jp/Nos/20150218/1424217597)様
　　　[Raspberry Pi公式ドキュメントを日本語訳](http://igarashi-systems.com/sample/translation/raspberry-pi/configuration/audio-configuration.html)様

## 2.raspi-configでの操作
まずConfigration Toolを開きます。

```LXTerminal
$ sudo raspi-config
```

その後 7.Advanced Option → A9 Audio から出力先を選択します。

<img width="250" alt="スクリーンショット 2016-12-02 03.02.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/130506/9aeceb32-381f-cc12-27df-7a3f978f6736.png">

<img width="250" alt="スクリーンショット 2016-12-02 03.02.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/130506/870a7093-3333-7fb4-a914-e3051d95c002.png">

<img width="250" alt="スクリーンショット 2016-12-02 03.03.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/130506/fc83a642-197d-d101-cca3-5eb74feb099c.png">

完了。

# おまけ2：音質
どの方法を使用したにせよ、イヤホンジャックからそのまま出力させるとノイズが乗ります。
解決方法としては、

1. DACを使用する
2. USBスピーカー、ヘッドフォンを使用する
3. HDMI端子から何とかして音楽を引き出す

という3つがありそうです。(もしかしたら他にもあるかもしれませんが…)
試しに[USB-イヤフォンジャック変換器](https://www.amazon.co.jp/gp/product/B007WPMIN8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1)を用いてUSBから音楽を出力させてみましたが、ノイズが乗らなくなりました。

USBからの音楽出力には[このような準備](http://www.tapun.net/raspi/raspberry-pi-usb-speaker)が必要になります。

# まとめ
pythonで音楽再生をしようとした際、ERRORばかり吐かれて発狂したのでまとめ記事を書きました。
お役立ていただければ幸いです。