Play audio files from Python with interrupts

I made a program to play audio on Rasberry Pi using Python. I had a hard time, so I will show you the way.

As a specification, when an event occurs, the sound corresponding to the event is played, If another event occurs during audio playback, it's like stopping the audio being played and playing the audio of the new event.

This will come into effect later.

First of all, the royal road PyAudio

For the time being, it seems that PyAudio is often used if you google it like "Python audio playback", so I will try it from this time.

Install according to the official apt-get install python-pyaudio python3-pyaudio Since the version of Python is 2.7.9, I feel that I don't need python3-pyaudio.

And [reference site](https://fififactory.com/2015/04/29/python-python%E3%81%A7%E9%9F%B3%E6%A5%BD%E5%86%8D%E7% Let's implement a class for audio playback while watching 94% 9F-wave-pyaudio /)

audio_player.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pyaudio
import wave
from time import sleep

class AudioPlayer:
    """ A Class For Playing Audio """

    def __init__(self):
        self.audio_file = ""

    def setAudioFile(self, audio_file):
        self.audio_file = audio_file

    def playAudio(self):
        if(self.audio_file == ""):
            return
        self.wf = wave.open(self.audio_file, "rb")
        p = pyaudio.PyAudio()
        stream = p.open(format=p.get_format_from_width(self.wf.getsampwidth()),
                channels=self.wf.getnchannels(),
                rate=self.wf.getframerate(),
                output=True,
                stream_callback=self.callback)
        stream.start_stream()

        while stream.is_active():
            sleep(0.1)

        stream.stop_stream()
        stream.close()
        self.wf.close()

        p.terminate()


    def callback(self, in_data, frame_count, time_info, status):
        data = self.wf.readframes(frame_count)
        return (data, pyaudio.paContinue)
        

I can't stop, I can't stop

In this way, I succeeded in playing the audio safely, but as you might expect, there was a problem. ** I can't stop ... ** It may be purely my lack of skill, but I didn't know how to stop playback with an interrupt. Is it possible to take a peek at the process?

Let Linux do it

From a slightly different point of view, I wondered if instead of playing the audio from Python, I would execute a command for audio playback from Python and interrupt it as appropriate.

aplay you too ...

So next I will try aplay. It's easy because it can be played with ʻaplay hoge.wav`. Rewrite the previous class to execute the aplay command.

audio_player.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess

class AudioPlayer:
    """ A Class For Playing Audio """

    def __init__(self):
        self.audio_file = ""
        self.is_playing = False

    def setAudioFile(self, audio_file):
        self.audio_file = audio_file

    def playAudio(self):
        if(self.audio_file == ""):
            return
        subprocess.call(["aplay", self.audio_file])

The command module is deprecated, so use the subprocess module. Alright, I can play it with this, and when I look at ʻaplay --help`, I wonder how to interrupt it ... there is no such thing. It seems that the only way to stop the playback of aplay is to check Ctl + C or PID and kill it. This is crazy.

And to mpc ...

No, I believed that the direction should not be wrong, and when I investigated further, I arrived at mpc. As far as I can see the contents at the bottom of this page, there is also a command to interrupt the audio. I can go!

So I will rewrite the class again. However, using subprocess.call is the same.

audio_player.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess

class AudioPlayer:
    """ A Class For Playing Audio """

    def __init__(self):
        self.audio_file = ""
        self.is_playing = False

    def setAudioFile(self, audio_file):
        self.audio_file = audio_file

    def playAudio(self):
        if(self.audio_file == ""):
            return
        print 'play ' + self.audio_file
        subprocess.call(["mpc", "stop"])   #Voice stop
        subprocess.call(["mpc", "clear"])  #Clear playlist
        subprocess.call(["mpc", "update"]) #Reading audio files
        subprocess.call(["mpc", "add", self.audio_file]) #Add to playlist
        subprocess.call(["mpc", "play"]) #Regeneration

When I tested it with this ... I did, the audio was interrupted and a new audio was played! This will win!

Reference page

Recommended Posts

Play audio files from Python with interrupts
Play audio files with interrupts using PyAudio
Play with 2016-Python
Decrypt files encrypted with openssl from python with openssl
Manipulate excel files from python with xlrd (personal notes)
Sorting image files with Python (2)
Sort huge files with python
Sorting image files with Python (3)
[Python] Play with Discord's Webhook.
Sorting image files with Python
Integrate PDF files with Python
Reading .txt files with Python
Play WAVE files from WSL
Play RocketChat with API / Python
With skype, notify with skype from python!
Remove headings from multiple format CSV files with python
Discord Bot with recording function starting with Python: (4) Play music files
Call C from Python with DragonFFI
Recursively unzip zip files with python
Using Rstan from Python with PypeR
Manipulating EAGLE .brd files with Python
Install Python from source with Ansible
Create folders from '01' to '12' with python
[Python] POST wav files with requests [POST]
Read and use Python files from Python
Decrypt files encrypted with OpenSSL with Python 3
Let's play with Excel with Python [Beginner]
Run Aprili from Python with Orange
Handle Excel CSV files with Python
Read files in parallel with Python
Call python from nim with Nimpy
Read fbx from python with cinema4d
Extract strings from files in Python
Collecting information from Twitter with Python (Twitter API)
Play video with sound with python !! (tkinter / imageio)
[AWS] Using ini files with Lambda [Python]
Receive textual data from mysql with python
Get html from element with Python selenium
[Note] Get data from PostgreSQL with Python
Create wordcloud from your tweet with python3
Play handwritten numbers with python Part 2 (identify)
Tweet from python with Twitter Developer + Tweepy
Fractal to make and play with Python
Business efficiency starting from scratch with Python
Working with Azure CosmosDB from Python Part.2
I want to play with aws with python
Image acquisition from camera with Python + OpenCV
Reading and writing JSON files with Python
Download files on the web with Python
[Easy Python] Reading Excel files with openpyxl
Getting started with Dynamo from Python boto
Try calling Python from Ruby with thrift
Scraping from an authenticated site with python
Convert HEIC files to PNG files with Python
[Easy Python] Reading Excel files with pandas
Use C ++ functions from python with pybind11
Play with Prophet
Collecting information from Twitter with Python (Environment construction)
Python hand play (let's get started with AtCoder?)
FizzBuzz with Python3
Csv output from Google search with [Python]! 【Easy】