如何用Kivy开发Android实时麦克风输入回传应用?
基于Kivy的Android实时音频回传应用开发需求
需求说明
我想要用Kivy开发一款Android应用,用户点击按钮后即可将麦克风输入实时回传播放。目前已实现将音频输入保存到文件的功能,但无法实现不保存文件的实时回传。做这个是为了开发一款基于Python和socket的音频聊天应用,最终用buildozer导出为.apk文件。
已实现的音频文件录制代码(非目标功能)
from kivy.uix.boxlayout import BoxLayout from kivy.uix.label import Label from kivy.uix.button import Button from kivy.lang import Builder from kivy.app import App from kivy.clock import Clock from kivy.uix.textinput import TextInput from kivy.uix.switch import Switch from jnius import autoclass Builder.load_string(''' <AudioTool> orientation: 'vertical' Label: id: display_label text: '00:00' BoxLayout: size_hint: 1, .2 TextInput: id: user_input text: '5' disabled: duration_switch.active == False #TUT 3 IF SWITCH IS OFF TEXTINPUT IS DISABLED on_text: root.enforce_numeric() Switch: id: duration_switch BoxLayout: Button: id: start_button text: 'Start Recording' on_release: root.startRecording_clock() Button: id: stop_button text: 'Stop Recording' on_release: root.stopRecording() disabled: True ''') class MyRecorder: def __init__(self): '''Recorder object To access Android Hardware''' self.MediaRecorder = autoclass('android.media.MediaRecorder') self.AudioSource = autoclass('android.media.MediaRecorder$AudioSource') self.OutputFormat = autoclass('android.media.MediaRecorder$OutputFormat') self.AudioEncoder = autoclass('android.media.MediaRecorder$AudioEncoder') # create out recorder self.mRecorder = self.MediaRecorder() self.mRecorder.setAudioSource(self.AudioSource.MIC) self.mRecorder.setOutputFormat(self.OutputFormat.THREE_GPP) self.mRecorder.setOutputFile('/sdcard/MYAUDIO.3gp') self.mRecorder.setAudioEncoder(self.AudioEncoder.AMR_NB) self.mRecorder.prepare() class AudioApp(App): def build(self): return AudioTool() class AudioTool(BoxLayout): def __init__(self, **kwargs): super(AudioTool, self).__init__(**kwargs) self.start_button = self.ids['start_button'] self.stop_button = self.ids['stop_button'] self.display_label = self.ids['display_label'] self.switch = self.ids['duration_switch'] # Tutorial 3 self.user_input = self.ids['user_input'] def enforce_numeric(self): '''Make sure the textinput only accepts numbers''' if self.user_input.text.isdigit() == False: digit_list = [num for num in self.user_input.text if num.isdigit()] self.user_input.text = "".join(digit_list) def startRecording_clock(self): self.mins = 0 #Reset the minutes self.zero = 1 # Reset if the function gets called more than once self.duration = int(self.user_input.text) #Take the input from the user and convert to a number Clock.schedule_interval(self.updateDisplay, 1) self.start_button.disabled = True # Prevents the user from clicking start again which may crash the program self.stop_button.disabled = False self.switch.disabled = True #TUT Switch disabled when start is pressed Clock.schedule_once(self.startRecording) ## NEW start the recording def startRecording(self, dt): #NEW start the recorder self.r = MyRecorder() self.r.mRecorder.start() def stopRecording(self): Clock.unschedule(self.updateDisplay) self.r.mRecorder.stop() #NEW RECORDER VID 6 self.r.mRecorder.release() #NEW RECORDER VID 6 Clock.unschedule(self.startRecording) #NEW stop the recording of audio VID 6 self.display_label.text = 'Finished Recording!' self.start_button.disabled = False self.stop_button.disabled = True #TUT 3 self.switch.disabled = False #TUT 3 re enable the switch def updateDisplay(self,dt): if self.switch.active == False: if self.zero < 60 and len(str(self.zero)) == 1: self.display_label.text = '0' + str(self.mins) + ':0' + str(self.zero) self.zero += 1 elif self.zero < 60 and len(str(self.zero)) == 2: self.display_label.text = '0' + str(self.mins) + ':' + str(self.zero) self.zero += 1 elif self.zero == 60: self.mins +=1 self.display_label.text = '0' + str(self.mins) + ':00' self.zero = 1 elif self.switch.active == True: if self.duration == 0: # 0 self.display_label.text = 'Recording Finished!' self.stopRecording() # NEW VID 6 / THIS ONE LINE SHOULD TAKE CARE OF THE RECORDING NOT STOPPING. #self.start_button.disabled = False # Re enable start #self.stop_button.disabled = True # Re disable stop #Clock.unschedule(self.updateDisplay) #DELETE FOR VID 6 #self.switch.disabled = False # Re enable the switch elif self.duration > 0 and len(str(self.duration)) == 1: # 0-9 self.display_label.text = '00' + ':0' + str(self.duration) self.duration -= 1 elif self.duration > 0 and self.duration < 60 and len(str(self.duration)) == 2: # 0-59 self.display_label.text = '00' + ':' + str(self.duration) self.duration -= 1 elif self.duration >= 60 and len(str(self.duration % 60)) == 1: # EG 01:07 self.mins = self.duration / 60 self.display_label.text = '0' + str(self.mins) + ':0' + str(self.duration % 60) self.duration -= 1 elif self.duration >= 60 and len(str(self.duration % 60)) == 2: # EG 01:17 self.mins = self.duration / 60 self.display_label.text = '0' + str(self.mins) + ':' + str(self.duration % 60) self.duration -= 1 if __name__ == '__main__': AudioApp().run()
尝试过的模块及问题
pyaudio:无法带着该模块导出apkaudiostream:无法正常运行soundcard:无法正常运行
寻求解决方案
正在寻找使用jnius或其他支持Kivy(及Android)的模块的解决方案。
内容的提问来源于stack exchange,提问作者CocaColaCoder
相关产品推荐
相关产品推荐

