374 日記 | 物理ボタンでプレイリスト再生を制御 episode artwork

EPISODE · Jul 4, 2026 · 25 MIN

374 日記 | 物理ボタンでプレイリスト再生を制御

from TanaRadio · host たな

物理ボタンでプレイリスト再生の制御ができるようになりました(フェーズ5D完了)。*以下のtanaradio_5d.pyのコードは,修正済みのものです(この収録後も1回修正しました)。フェーズ5D 詳細マニュアル 既存3ボタンでRSSプレイリストを操作する 0. 今回の目標 今回やることは、これです。 フェーズ5Cで playlist.m3u を作る ↓ mpvで playlist.m3u を再生する ↓ GPIOの3ボタンでmpvを操作する 3つのボタンの役割は、今回は次のようにします。 再生/一時停止ボタン:再生・一時停止 戻るボタン:前のエピソードへ 次へボタン:次のエピソードへ mpvへの命令は次の3つです。 再生/一時停止:cycle pause 戻る:playlist-prev 次へ:playlist-next 構想メモでは、戻るボタンに「1回押し=先頭へ、2回押し=前へ、長押し=10秒戻る」という発展案があります。 ただし、5Dではまだ入れません。ここで欲張ると、ボタン判定の沼に入ります。沼は楽しいですが、今日はまだ岸辺でお茶を飲みます。 ステップ1:作業フォルダへ移動する Raspberry Piでターミナルを開きます。 cd ~/tanaradio5 確認します。 pwd 次のような表示になればOKです。 /home/ユーザー名/tanaradio5 ステップ2:5Cまでのファイルを確認する ls 少なくとも、次のようなファイルがあるはずです。 feeds.txt make_playlist_5c.py playlist.m3u スクリプト名は、たなさんが5Cで作った名前に合わせてください。 以下では、5Cのスクリプト名を make_playlist_5c.py として進めます。 ステップ3:5Cのプレイリストをもう一度作る まず、5Cのスクリプトを実行して、最新の playlist.m3u を作ります。 ./make_playlist_5c.py または、実行権限を付けていない場合は、 python3 make_playlist_5c.py うまくいけば、たとえば次のような表示になります。 playlist.m3u を作成しました。 音声URL数: 12 件 完了しました。 確認します。 ls -l playlist.m3u playlist.m3u が存在し、サイズが0でなければOKです。 中身も少し見ます。 head playlist.m3u 次のように、音声URLが入っていればOKです。 #EXTM3U # エピソードタイトル https://... ステップ4:mpvだけで再生できるか確認する ボタン操作に入る前に、まず普通に再生します。 mpv playlist.m3u 音が出ればOKです。 この状態では、キーボードで操作できます。 スペースキー:一時停止/再開 Enter:次へ q:終了 確認できたら、q を押してmpvを終了します。 ここで音が出ない場合は、5Dには進まず、音声出力側を先に確認してください。 ステップ5:GPIOライブラリを確認する 今回はPythonからGPIOボタンを読むために gpiozero を使います。 まず確認します。 python3 -c "import gpiozero; print('gpiozero OK')" 次のように出ればOKです。 gpiozero OK もしエラーが出たら、次を実行します。 sudo apt update sudo apt install -y python3-gpiozero python3-lgpio インストール後、もう一度確認します。 python3 -c "import gpiozero; print('gpiozero OK')" ステップ6:GPIO番号を確認する 今回のコードでは、フェーズ4で使ってきた3つのGPIOを次のように使います。 GPIO17:再生/一時停止 GPIO27:戻る、つまり前のエピソードへ GPIO22:次へ、つまり次のエピソードへ 配線はこれまで通り、基本形は次です。構想メモでも、ボタン入力には保険として抵抗を残す方針になっています。 GPIO ─ 1kΩ程度の抵抗 ─ ボタン ─ GND つまり、ボタンを押すとGPIOがGNDにつながる形です。 Python側では pull_up=True にします。 ステップ7:5D用スクリプトを作る 新しいファイルを作ります。 nano tanaradio_5d.py 次のコードをそのまま貼り付けます。 #!/usr/bin/env python3 from gpiozero import Button from signal import pause import json import os import signal import socket import subprocess import sys import time from pathlib import Path # ===== 設定ここから ===== BASE_DIR = Path(__file__).resolve().parent PLAYLIST_FILE = BASE_DIR / "playlist.m3u" SOCKET_PATH = "/tmp/tanaradio-mpv.sock" # フェーズ4で使った既存3ボタンのGPIO番号 PIN_PLAY_PAUSE = 17 # 再生/一時停止 PIN_BACK = 27 # 戻る:前のエピソードへ PIN_NEXT = 22 # 次へ:次のエピソードへ # ===== 設定ここまで ===== mpv_process = None def check_playlist(): if not PLAYLIST_FILE.exists(): print(f"{PLAYLIST_FILE} が見つかりません。") print("先にフェーズ5Cのスクリプトを実行して playlist.m3u を作ってください。") sys.exit(1) text = PLAYLIST_FILE.read_text(encoding="utf-8", errors="ignore").strip() if not text: print(f"{PLAYLIST_FILE} は空です。") sys.exit(1) def start_mpv(): global mpv_process if os.path.exists(SOCKET_PATH): os.remove(SOCKET_PATH) print("mpvを起動します。") print(f"プレイリスト: {PLAYLIST_FILE}") mpv_process = subprocess.Popen( [ "mpv", "--no-video", f"--input-ipc-server={SOCKET_PATH}", str(PLAYLIST_FILE), ], cwd=str(BASE_DIR), ) # mpvのIPCソケットができるまで少し待つ for _ in range(50): if os.path.exists(SOCKET_PATH): print("mpv操作用ソケットを確認しました。") return time.sleep(0.1) print("mpv操作用ソケットが見つかりません。") print("mpvが起動できていない可能性があります。") def send_mpv_command(command): payload = json.dumps({"command": command}).encode("utf-8") + b"\n" try: with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as client: client.settimeout(1.0) client.connect(SOCKET_PATH) client.sendall(payload) # mpvからの返事を少し読む。 # これをしないと、mpv側に Broken pipe が出ることがある。 try: client.recv(4096) except socket.timeout: pass except FileNotFoundError: print("mpvのソケットが見つかりません。mpvが終了している可能性があります。") except ConnectionRefusedError: print("mpvに接続できませんでした。") except Exception as e: print("mpvへの命令送信でエラーが出ました。") print(e) def play_pause(): print("ボタン: 再生/一時停止") send_mpv_command(["cycle", "pause"]) def back_episode(): print("ボタン: 戻る:前のエピソードへ") send_mpv_command(["playlist-prev"]) def next_episode(): print("ボタン: 次へ") send_mpv_command(["playlist-next"]) def setup_buttons(): print("GPIOボタンを準備します。") print(f"再生/一時停止: GPIO{PIN_PLAY_PAUSE}") print(f"戻る: GPIO{PIN_BACK}") print(f"次へ: GPIO{PIN_NEXT}") play_button = Button(PIN_PLAY_PAUSE, pull_up=True, bounce_time=0.08) back_button = Button(PIN_BACK, pull_up=True, bounce_time=0.08) next_button = Button(PIN_NEXT, pull_up=True, bounce_time=0.08) play_button.when_pressed = play_pause back_button.when_pressed = back_episode next_button.when_pressed = next_episode # main側で保持するために返す return play_button, back_button, next_button def cleanup(signum=None, frame=None): global mpv_process print("\n終了します。") if mpv_process is not None and mpv_process.poll() is None: mpv_process.terminate() try: mpv_process.wait(timeout=5) except subprocess.TimeoutExpired: mpv_process.kill() if os.path.exists(SOCKET_PATH): try: os.remove(SOCKET_PATH) except OSError: pass sys.exit(0) def main(): signal.signal(signal.SIGINT, cleanup) signal.signal(signal.SIGTERM, cleanup) check_playlist() start_mpv() # 重要: # setup_buttons() の戻り値を変数に入れて保持する。 # これをしないと、環境によってはボタンが反応しなくなることがある。 buttons = setup_buttons() print("準備完了です。") print("3つの物理ボタンで操作できます。終了は Ctrl + C です。") pause() if __name__ == "__main__": main() 保存します。 Ctrl + O Enter Ctrl + X ステップ8:実行権限を付ける chmod +x tanaradio_5d.py ステップ9:5Dを実行する ./tanaradio_5d.py うまくいくと、次のような表示になります。 mpvを起動します。 プレイリスト: /home/ユーザー名/tanaradio5/playlist.m3u mpv操作用ソケットを確認しました。 GPIOボタンを準備します。 再生/一時停止: GPIO17 戻る: GPIO27 次へ: GPIO22 準備完了です。 3つの物理ボタンで操作できます。終了は Ctrl + C です。 この状態で、音声が流れ始めます。 ステップ10:3つのボタンを試す 10-1. 再生/一時停止ボタン GPIO17につながっているボタンを押します。 ターミナルに次のように出ればOKです。 ボタン: 再生/一時停止 音声が一時停止します。 もう一度押すと再開します。 10-2. 次へボタン GPIO22につながっているボタンを押します。 ボタン: 次へ 次のエピソードへ進めばOKです。 10-3. 戻るボタン GPIO27につながっているボタンを押します。 ボタン: 戻る:前のエピソードへ 前のエピソードへ戻ればOKです。 ただし、プレイリストの最初のエピソードを再生しているときは、それ以上前へ戻れないので、動きがわかりにくい場合があります。 その場合は、先に「次へ」を1〜2回押してから「戻る」を試してください。 ステップ11:終了する 終了するときは、ターミナルで次を押します。 Ctrl + C 次のように出ればOKです。 終了します。 mpvも一緒に終了します。 ステップ12:今回の成功条件 フェーズ5Dの成功条件は、次の4つです。 1. フェーズ5Cの playlist.m3u が作れている 2. tanaradio_5d.py を実行すると mpv が起動する 3. 再生/一時停止ボタンで pause / resume ができる 4. 戻る・次へボタンで playlist-prev / playlist-next ができる ここまでできれば、5Dは成功です。 これはかなり大きいです。 5Cまでは「RSSから音声を集める仕組み」でしたが、5Dでついに「物理ボタンで声の流れを操る装置」になります。ラジオ感が、ぐっと前に出てきます。#声日記 #TanaRadioPi LISTENで開く

Episode metadata supplied by the publisher feed · Published Jul 4, 2026

Embed this episode

NOW PLAYING

374 日記 | 物理ボタンでプレイリスト再生を制御

0:00 25:57

No transcript for this episode yet

We transcribe on demand. Request one and we'll notify you when it's ready — usually under 10 minutes.

No similar episodes found.

No similar podcasts found.

Frequently Asked Questions

How long is this episode of TanaRadio?

This episode is 25 minutes long.

When was this TanaRadio episode published?

This episode was published on July 4, 2026.

Can I download this TanaRadio episode?

Yes. Use the download control on the episode player to save the publisher-provided media file.
URL copied to clipboard!