ラズパイでmp3を再生するコマンドと Python のプログラム | そう備忘録

ラズパイでmp3を再生するコマンドと Python のプログラム

mp3ファイルの再生

Raspberry Piでmp3ファイルを再生するプログラムについての記事。

この記事は金丸隆志さんの「Raspberry Piで学ぶ電子工作」を参考にしている。

今回の自分の試した環境はRaspberry Pi 3 B+だが今購入するのであればRaspberry Pi 4だと思うので4対応の書籍も紹介しておく。

必要なモジュールのインストール

まずmp3ファイルを再生するためのモジュールをラズパイにインストールする。

最初に以下のコマンドでupdateを行う。

sudo apt-get update
sudo apt-get update

続いて以下のコマンドでmpg321をインストールする。

sudo apt-get install mpg321
sudo apt-get install mpg321

実行してみる

mp3を再生するプログラムの作成前にコマンドラインからmp3ファイルが再生されるかを試してみる。

ラズパイのヘッドホンジャック(アナログ)にヘッドホンを差し込んで、以前の「音声をニューラルネットワークを使ってテキスト化~GCP~」の記事で使ったmp3ファイル(何でもOK)をラズパイにコピーして以下のコマンドで再生してみる。

mpg321 ファイル名.mp3

上記のコマンドで最終的には再生はできたのが何点か気づいた事がある。

HDMI接続時に音が出ない

ラズパイのディスプレイをスピーカーの付いていないモニターに HDMI 出力していたのだが、 HDMI 接続した状態でラズパイを起動すると再生しても音がでない。

HDMI 接続をせずにラズパイを起動して後からモニターに HDMI 接続すればヘッドホンジャックから音声が再生された。

起動時にHDMI接続していると音声もHDMIでモニターに出力されてしまって、しかもモニターにスピーカーが付いていないのでこのような状態になるのだと思い/boot/config.txtを確認した所、hdmi_drive=2の指定がされていたので1を指定してみた。

hdmi_drive=1

hdmi_drive=0

自動

hdmi_drive=1

アナログ出力(ヘッドホンジャック)

hdmi_drive=2

HDMI出力

しかし残念ながら自分の環境では状況は変わらず音が出なかったので、結局、amixerコマンドで設定を変更した。

amixer cset numid=3 1

最後の数字の1は上記の一覧表に対応している。(2ならHDMI)

また以下のコマンドで現在のAudioの状態を確認することもできる。

amixer cget numid=3

雑音が入る

音声再生時に時々「プチッ」と雑音が入る時がある。

ヒス音(高音のスーという連続音)の場合は /boot/config.txt に下記の指定をすると収まるとの記述を見つけた。

disable_audio_dither=1

上記の指定を行った所、自分のRaspberry Pi 3 B+では「若干雑音が減ったかも」というレベルで特に大きな効果は得られなかった。

結局、音声はアナログでは無くて映像と一緒にHDMI出力する方が良い気がする。

プログラム

ソースコード

プログラムからmpg321を使ってmp3を再生してみる。

# -*- coding: utf-8 -*-
"""
Created on Fri Aug  7 07:50:49 2020

@author: Souichirou Kikuchi
"""

import RPi.GPIO as GPIO
from time import sleep
import subprocess

LED_GPIO = 4 # LEDに接続するGPIO番号
TACT_GPIO = 17 # Tack Switchに接続するGPIO番号
MP3_FILE = './LEGO-MINDSTORMS.mp3' # 再生したいファイルPath

def toggle_switch(channel):
    global isPlaying
    global process
    if channel == TACT_GPIO:
        if isPlaying == False:
            isPlaying = True
            GPIO.output(LED_GPIO, GPIO.HIGH)
            args = ['mpg321', MP3_FILE]
            process = subprocess.Popen(args)
        else:
            isPlaying = False
            GPIO.output(LED_GPIO, GPIO.LOW)
            args = ['kill', str(process.pid)]
            subprocess.Popen(args)

GPIO.setmode(GPIO.BCM)
GPIO.setup(LED_GPIO, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(TACT_GPIO, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(TACT_GPIO, GPIO.RISING, callback=toggle_switch, bouncetime=200)

isPlaying = False
process = None

try:
    while True:
        sleep(0.01)

except KeyboardInterrupt:
    pass

GPIO.cleanup()

補足説明

定数の定義

14行目に再生したいmp3ファイル(今回はレゴ関係のmp3を使用した)を指定している。

タクトスイッチ

タクトスイッチはトグルになっており、

  1. 一回押すと先頭から再生
  2. もう一度押すと再生停止

1.と2.を交互に繰り返している。

再生の切り替え

現在再生中がどうかはisPlaying変数で制御しており、24行目のsubprocess.Popenでmp3ファイルの再生を行い、29行目にてkill(プロセスの終了)にてsubprocess.Popenでプロセスを停止している。

add_event_detect

34行目のadd_event_detectについて詳細は以前の記事の補足説明を参照して欲しい。

GPIO17がLOWからHIGHになる瞬間をトリガーとしてtoggle_switch関数を呼び出すように設定している。

以上で今回の記事は終了とする。

最後に

この記事が何処かで誰かの役に立つことを願っている。

尚、当記事中の商品へのリンクはAmazonアソシエイトへのリンクが含まれています。Amazonのアソシエイトとして、当メディアは適格販売により収入を得ていますのでご了承ください。

souichirou

やった事を忘れない為の備忘録 同じような事をやりたい人の参考になればと思ってブログにしてます。 主にレゴ、AWS(Amazon Web Services)、WordPress、Deep Learning、RaspberryPiに関するブログを書いています。 仕事では工場に協働ロボットの導入や中小企業へのAI/IoT導入のアドバイザーをやっています。 2019年7月にJDLA(一般社団法人 日本デイープラーニング協会)Deep Learning for GENERALに合格しました。 質問は記事一番下にあるコメントかメニュー上部の問い合わせからお願いします。

おすすめ

質問やコメントや励ましの言葉などを残す

名前、メール、サイト欄は任意です。
またメールアドレスは公開されません。