add audio and record widget
This commit is contained in:
parent
7d7f4ac472
commit
a922670413
@ -16,6 +16,7 @@ class Audio(AppLogger, pyaudio.PyAudio):
|
|||||||
self.chunk = 1024
|
self.chunk = 1024
|
||||||
self.devices = [ self.get_device_info_by_index(i) \
|
self.devices = [ self.get_device_info_by_index(i) \
|
||||||
for i in range(self.get_device_count()) ]
|
for i in range(self.get_device_count()) ]
|
||||||
|
self.recording = False
|
||||||
|
|
||||||
def get_input_device(self):
|
def get_input_device(self):
|
||||||
return [ d for d in self.devices if d.maxInputChannels > 0 ]
|
return [ d for d in self.devices if d.maxInputChannels > 0 ]
|
||||||
@ -27,24 +28,16 @@ class Audio(AppLogger, pyaudio.PyAudio):
|
|||||||
x = tempfile.mkstemp(suffix='.wav')
|
x = tempfile.mkstemp(suffix='.wav')
|
||||||
os.close(x[0])
|
os.close(x[0])
|
||||||
self.temp_filename = x[1]
|
self.temp_filename = x[1]
|
||||||
|
return self.temp_filename
|
||||||
|
|
||||||
def record_cb(self, in_data, frame_count, time_info, status):
|
def record_cb(self, in_data, frame_count, time_info, status):
|
||||||
bdata = pickle.dumps(in_data)
|
|
||||||
self.info('frame_count=%s, time_info=%s, status=%s, bytes count=%s', \
|
|
||||||
frame_count, time_info, status, len(bdata))
|
|
||||||
self.rec_frames += frame_count
|
|
||||||
self.current_ts = time.time()
|
|
||||||
self.wavfile.writeframesraw(in_data)
|
self.wavfile.writeframesraw(in_data)
|
||||||
if self.running:
|
if self.recording:
|
||||||
return (None, pyaudio.paContinue)
|
return (None, pyaudio.paContinue)
|
||||||
|
|
||||||
return (None, pyaudio.paComplete)
|
return (None, pyaudio.paComplete)
|
||||||
|
|
||||||
def replay_cb(self, in_data, frame_count, time_info, status):
|
def replay_cb(self, in_data, frame_count, time_info, status):
|
||||||
data = self.wavfile.readframes(frame_count)
|
data = self.wavfile.readframes(frame_count)
|
||||||
bdata = pickle.dumps(data)
|
|
||||||
self.info('frame_count=%s, data length in bytes=%s', \
|
|
||||||
frame_count, len(bdata))
|
|
||||||
if not data:
|
if not data:
|
||||||
return (None, pyaudio.paComplete)
|
return (None, pyaudio.paComplete)
|
||||||
|
|
||||||
@ -57,35 +50,42 @@ class Audio(AppLogger, pyaudio.PyAudio):
|
|||||||
print(x)
|
print(x)
|
||||||
return dev_cnt - 1
|
return dev_cnt - 1
|
||||||
|
|
||||||
def record(self, save_file=None, stop_cond_func=None):
|
def start_record(self,
|
||||||
filename = save_file
|
savefile=None,
|
||||||
if filename is None:
|
|
||||||
self.tmpfile()
|
|
||||||
filename = self.temp_filename
|
|
||||||
|
|
||||||
self.wavfile = wave.open(filename, 'wb')
|
|
||||||
self.wavfile.setnchannels(2)
|
|
||||||
self.wavfile.setsampwidth(2)
|
|
||||||
self.wavfile.setframerate(44100.00)
|
|
||||||
self.stream = self.open(format=pyaudio.paInt16,
|
|
||||||
channels=2,
|
channels=2,
|
||||||
rate=44100,
|
rate=44100
|
||||||
|
):
|
||||||
|
if savefile is None:
|
||||||
|
savefile = self.tmpfile()
|
||||||
|
self.save_file = savefile
|
||||||
|
self.wavfile = wave.open(self.save_file, 'wb')
|
||||||
|
self.wavfile.setnchannels(channels)
|
||||||
|
self.wavfile.setsampwidth(2)
|
||||||
|
self.wavfile.setframerate(rate)
|
||||||
|
self.stream = self.open(format=pyaudio.paInt16,
|
||||||
|
channels=channels,
|
||||||
|
rate=rate,
|
||||||
input=True,
|
input=True,
|
||||||
frames_per_buffer=self.chunk,
|
frames_per_buffer=self.chunk,
|
||||||
stream_callback=self.record_cb)
|
stream_callback=self.record_cb)
|
||||||
self.stream.start_stream()
|
self.stream.start_stream()
|
||||||
self.running = True
|
self.recording = True
|
||||||
self.rec_frames = 0
|
|
||||||
self.start_ts = self.current_ts = time.time()
|
def stop_record(self):
|
||||||
while self.stream.is_active():
|
if self.recording:
|
||||||
if stop_cond_func and stop_cond_func():
|
|
||||||
self.running = False
|
|
||||||
time.sleep(0.05)
|
|
||||||
self.stream.stop_stream()
|
self.stream.stop_stream()
|
||||||
self.stream.close()
|
self.stream.close()
|
||||||
self.wavfile.close()
|
self.wavfile.close()
|
||||||
if save_file is None:
|
|
||||||
self.replay()
|
def record(self, stop_cb,
|
||||||
|
savefile=None,
|
||||||
|
channels=2,
|
||||||
|
rate=44100,
|
||||||
|
):
|
||||||
|
self.start_record(savefile=savefile, channels=channels,rate=rate)
|
||||||
|
while not stop_cb():
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.stop_record()
|
||||||
|
|
||||||
def replay(self, play_file=None):
|
def replay(self, play_file=None):
|
||||||
idx = self.get_output_index()
|
idx = self.get_output_index()
|
||||||
@ -118,9 +118,12 @@ class Audio(AppLogger, pyaudio.PyAudio):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
|
t_begin = time.time()
|
||||||
def stop_func(audio):
|
def stop_func(audio):
|
||||||
if audio.current_ts - audio.start_ts >= 10:
|
t = time.time()
|
||||||
audio.running = False
|
if t - t_begin >= 10:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
create_logger('audio', levelname='debug')
|
create_logger('audio', levelname='debug')
|
||||||
a = Audio()
|
a = Audio()
|
||||||
@ -135,4 +138,4 @@ if __name__ == '__main__':
|
|||||||
if len(sys.argv) >= 2:
|
if len(sys.argv) >= 2:
|
||||||
sf = sys.argv[1]
|
sf = sys.argv[1]
|
||||||
f = partial(stop_func, a)
|
f = partial(stop_func, a)
|
||||||
a.record(sf, stop_cond_func=f)
|
a.record(f, savefile=sf)
|
||||||
|
@ -3,14 +3,14 @@ import tempfile
|
|||||||
import pyaudio
|
import pyaudio
|
||||||
import wave
|
import wave
|
||||||
from kivy.event import EventDispatcher
|
from kivy.event import EventDispatcher
|
||||||
from kivy.properties import NumericProperty
|
from kivy.properties import NumericProperty, StringProperty, ObjectProperty
|
||||||
from kivyblocks.baseWidget import HBox
|
from kivyblocks.baseWidget import HBox
|
||||||
from kviycv.micphone import Micphone
|
from kivycv.micphone import Micphone
|
||||||
|
|
||||||
class AudioRecorder(EventDispatcher):
|
class AudioRecorder(EventDispatcher):
|
||||||
fs = NumericProperty(None)
|
fs = NumericProperty(None)
|
||||||
filename = StringProperty(None)
|
filename = StringProperty(None)
|
||||||
voice_src = OjbectProperty(None)
|
voice_src = ObjectProperty(None)
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
super(AudioRecorder, self).__init__(**kw)
|
super(AudioRecorder, self).__init__(**kw)
|
||||||
self.saving = False
|
self.saving = False
|
||||||
|
@ -6,7 +6,7 @@ from kivy.uix.camera import Camera
|
|||||||
from kivy.properties import NumericProperty
|
from kivy.properties import NumericProperty
|
||||||
from kivy.event import EventDispatcher
|
from kivy.event import EventDispatcher
|
||||||
|
|
||||||
from .android_rotation import *
|
from kivyblocks.android_rotation import *
|
||||||
|
|
||||||
if kivy.platform in [ 'win', 'linux', 'macosx' ]:
|
if kivy.platform in [ 'win', 'linux', 'macosx' ]:
|
||||||
from PIL import ImageGrab
|
from PIL import ImageGrab
|
||||||
|
53
kivycv/recorder.py
Normal file
53
kivycv/recorder.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import pyaudio
|
||||||
|
from kivy.uix.label import Label
|
||||||
|
from kivy.properties import NumericProperty
|
||||||
|
from kivyblocks.baseWidget import HBox, VBox
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
try:
|
||||||
|
from .audio import Audio
|
||||||
|
except:
|
||||||
|
from audio import Audio
|
||||||
|
|
||||||
|
class Recorder(VBox):
|
||||||
|
rate = NumericProperty(44100)
|
||||||
|
channel = NumericProperty(2)
|
||||||
|
def __init__(self, **kw):
|
||||||
|
super().__init__(**kw)
|
||||||
|
self.audio = Audio()
|
||||||
|
self.register_event_type('on_recorded')
|
||||||
|
|
||||||
|
def on_recorded(self, record_file):
|
||||||
|
print('on_recorded:', record_file)
|
||||||
|
|
||||||
|
def on_touch_down(self, touch):
|
||||||
|
if self.collide_point(*touch.pos):
|
||||||
|
self.audio.start_record(channels=self.channel,
|
||||||
|
rate=self.rate)
|
||||||
|
return False
|
||||||
|
return super().on_touch_down(touch)
|
||||||
|
|
||||||
|
def on_touch_up(self, touch):
|
||||||
|
if self.audio.recording:
|
||||||
|
self.audio.stop_record()
|
||||||
|
self.dispatch('on_recorded', self.audio.save_file)
|
||||||
|
|
||||||
|
return super().on_touch_up(touch)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from kivy.app import App
|
||||||
|
class TestApp(App):
|
||||||
|
def build(self):
|
||||||
|
x = Recorder()
|
||||||
|
self.recorder = x
|
||||||
|
x.bind(on_recorded=self.play_audio)
|
||||||
|
return x
|
||||||
|
|
||||||
|
def play_audio(self, o, f):
|
||||||
|
print('play file', f)
|
||||||
|
self.recorder.audio.replay(f)
|
||||||
|
print('play finished')
|
||||||
|
# os.remove(f)
|
||||||
|
|
||||||
|
TestApp().run()
|
Loading…
Reference in New Issue
Block a user