-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaudio_queue.py
51 lines (43 loc) · 2 KB
/
audio_queue.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import subprocess
import pyaudio
import soundfile as sf
import numpy as np
import io
class AudioQueue:
def __init__(self, pa, output_device, frames_per_buffer=1024, volume=1):
self.pa = pa
self.output_device = output_device
self.frames_per_buffer = frames_per_buffer
self.volume = volume
self.audiodata = None
self.stream = None
def play(self, format=pyaudio.paInt16, channels=2, rate=48000):
self.stream = self.pa.open(format=format,
channels=channels,
rate=rate,
output=True,
stream_callback=self.callback,
output_device_index=self.output_device,
frames_per_buffer=self.frames_per_buffer)
def add_to_queue(self, file):
audio = subprocess.Popen(["ffmpeg", "-i", file, "-loglevel", "panic", "-vn", "-f", "wav", "-c:a", "pcm_s16le", "pipe:1"],
stdout=subprocess.PIPE)
audiofile = sf.SoundFile(io.BytesIO(audio.stdout.read()))
if self.audiodata is None:
self.audiodata = audiofile.read(dtype="int16")
else:
self.audiodata = np.concatenate((self.audiodata, audiofile.read(dtype="int16")))
try:
if not self.stream.is_active():
self.play(format=pyaudio.paInt16, channels=audiofile.channels, rate=audiofile.samplerate)
except AttributeError:
self.play(format=pyaudio.paInt16, channels=audiofile.channels, rate=audiofile.samplerate)
def callback(self, in_data, frame_count, time_info, status):
size = frame_count
data = self.audiodata[:size]
self.audiodata = self.audiodata[size:]
for i in range(len(data)):
chunk = np.fromstring(data[i], np.int16)
chunk = chunk * self.volume
data[i] = chunk.astype(np.int16)
return data, pyaudio.paContinue