LoginSignup
11
10

More than 5 years have passed since last update.

PyAudioを使って音声ファイルを割り込みで再生させる

Posted at

Pythonのタグを新着順で眺めているとこんな記事がありました。
Pythonから音声ファイルを割り込みで再生させる

PyAudio使ったことあるけどそんな使い方してなかったので、「PyAudioでもできそうだけどできないのかな?」と思いながら、読んでいました。


気がついたら作ってました。

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

CHUNK = 1024


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

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

        # 止める用のフラグ
        self.paused = threading.Event()

    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()

        self.stream = p.open(format=p.get_format_from_width(self.wf.getsampwidth()),
                             channels=self.wf.getnchannels(),
                             rate=self.wf.getframerate(),
                             output=True)

        data = self.wf.readframes(CHUNK)

        # play stream (3)
        while len(data) > 0:
            # もし、止めるフラグが立ってたら
            if self.paused.is_set():
                # 再生を止める
                self.stream.stop_stream()
                # フラグを初期状態に
                self.paused.clear()
                break
            self.stream.write(data)
            data = self.wf.readframes(CHUNK)

        # stop stream (4)
        self.stream.stop_stream()
        self.stream.close()
        # close PyAudio (5)
        p.terminate()


def play(player):
    # 再生は別のスレッドでする
    audio_thread = threading.Thread(target=player.playAudio)
    audio_thread.start()


if __name__ == "__main__":
    player1 = AudioPlayer()
    player1.setAudioFile("1.wav")
    player2 = AudioPlayer()
    player2.setAudioFile("2.wav")

    play(player1)
    # 例えば0,5秒後に別の音源に変える
    sleep(0.5)
    # 1を止めて
    player1.paused.set()
    # 2を再生
    play(player2)

一応できたのですが、 バグ というかがあって。。。
メインの部分を、一度止めてもう一度再生するみたいにすると、

if __name__ == "__main__":
    player1 = AudioPlayer()
    player1.setAudioFile("1.wav")

    play(player1)
    # 例えば0,5秒後にもう一度同じのを再生する
    sleep(0.5)
    # 1を止めて
    player1.paused.set()
    # もう一度1を再生
    play(player1)

Python(39927,0x105607000) malloc: *** error for object 0x100886800: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
zsh: abort      python audio.py

ってエラーがでるので、適宜

if __name__ == "__main__":
    player1 = AudioPlayer()
    player1.setAudioFile("1.wav")

    play(player1)
    # 例えば0,5秒後にもう一度同じのを再生する
    sleep(0.5)
    # 1を止めて
    player1.paused.set()
    # もう一度1を再生

    # エラー出るからスリープかける
    sleep(0.6)
    play(player1)

として、スリープをかけてあげてください。私の環境では0.6秒以上休まないとこのエラーがでます。

11
10
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10