Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Working with audio multimedia in pyqt5



  • I am trying to make a mp3 player for e-radio.

    I want to manage audio stream in real-time (volume,speed,time position).

    For the microphone, i have found/make this:

    import data
    from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia
    
    class MicrophoneDeck():
    	def __init__(self,ui,MainWindow):
    		self.microphone_on = False
    		ui.speakers_deck_open_or_close_microphone.setText("Click to talk - Now off")
    	
    		self.default_primary_output_device = data.read_setting("primary output device")[0]["current value"]
    		self.default_input_device = data.read_setting("input device")[0]["current value"]
    		
    		self.input_devices_qt  = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioInput)
    		self.output_devices_qt = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioOutput)
    		
    		self.input_device_index = 0
    		self.output_device_index = 0
    		
    		counter = 0
    		for input_device in self.input_devices_qt:
    			if(input_device.deviceName()==self.default_input_device):
    				self.input_device_index = counter
    				break
    			counter = counter+1
    			
    		counter = 0
    		for output_device in self.output_devices_qt:
    			if(output_device.deviceName()==self.default_primary_output_device):
    				self.output_device_index = counter
    				break
    			counter = counter+1
    			
    		self.play_from_microphone(ui,MainWindow)
    		
    		#self.start_player(ui,MainWindow)
    		
    		ui.speakers_deck_open_or_close_microphone.clicked.connect(lambda state:self.change_microphone_status(ui,MainWindow))
    		ui.speakers_deck_click_to_talk.pressed.connect(lambda:self.microphone_pressed(ui,MainWindow))
    		ui.speakers_deck_click_to_talk.released.connect(lambda:self.microphone_released(ui,MainWindow))
    		ui.speakes_deck_volume_control.valueChanged.connect(lambda volume:self.microphone_volume_changed(volume,ui,MainWindow))
    		
    		self.microphone_volume_changed(100,ui,MainWindow)
    		
    	def microphone_volume_changed(self,volume,ui,MainWindow):
    		vol = volume/100
    		self.m_audio_input.setVolume(vol)
    		
    		vol_text = round(vol,1)
    		ui.speakers_deck_volume_label.setText(str(vol_text)+"/1.0")
    	
    	def microphone_pressed(self,ui,MainWindow):
    		if self.microphone_on==False:
    			self.microphone_on = True
    			ui.speakers_deck_open_or_close_microphone.setText("Click to talk - Now On")
    			self.start_player(ui,MainWindow)
    			ui.speakers_deck_open_or_close_microphone.setEnabled(False)
    		
    	def microphone_released(self,ui,MainWindow):
    		self.microphone_on = False
    		ui.speakers_deck_open_or_close_microphone.setText("Click to talk - Now off")
    		self.stop_player(ui,MainWindow)
    		ui.speakers_deck_open_or_close_microphone.setEnabled(True)
    	
    	def change_microphone_status(self,ui,MainWindow):
    		if self.microphone_on:
    			self.microphone_on = False
    			ui.speakers_deck_open_or_close_microphone.setText("Click to talk - Now off")
    			self.stop_player(ui,MainWindow)
    			ui.speakers_deck_click_to_talk.setEnabled(True)
    		else:
    			self.microphone_on = True
    			ui.speakers_deck_open_or_close_microphone.setText("Click to talk - Now On")
    			self.start_player(ui,MainWindow)
    			ui.speakers_deck_click_to_talk.setEnabled(False)
    
    	def play_from_microphone(self,ui,MainWindow):
    		self.buffer_min_value = 0
    		self.buffer_max_value = 0
    			
    			
    		self.mid_strength = 0
    		self.min_value = -25
    		self.max_value = 25
    			
    		self.m_play_called = False	
    		self.m_buffer = QtCore.QByteArray()
    			
    
    			
    		self.m_buffer_requested = True
    		#self.m_time_to_buffer = 1000
    		#self.MAX_BUFFERED_TIME = 1000
    		self.m_time_to_buffer = 50
    		self.MAX_BUFFERED_TIME = 100
    			
    		self.m_input_device_info = QtMultimedia.QAudioDeviceInfo.defaultInputDevice()
    		self.m_output_device_info = QtMultimedia.QAudioDeviceInfo.defaultOutputDevice()
    						
    			
    		self.format = QtMultimedia.QAudioFormat()
    		self.format.setCodec("audio/pcm")
    		self.format.setSampleRate(44100)
    		self.format.setChannelCount(1)
    		self.format.setSampleSize(16)
    		self.format.setByteOrder(QtMultimedia.QAudioFormat.LittleEndian)
    		self.format.setSampleType(QtMultimedia.QAudioFormat.SignedInt)
    			
    		self.m_audio_input = QtMultimedia.QAudioInput(self.input_devices_qt[int(self.input_device_index)],self.format)
    			
    		#self.m_input_device = self.m_audio_input.start()
    		#self.m_audio_input.resume()
    		
    		self.m_audio_input.setNotifyInterval(100)
    		self.m_audio_input.notify.connect(lambda: self.send_input_to_buffer(MainWindow,ui))
    		
    			
    			
    		if (self.format.sampleRate() >= 44100):
    			self.internal_buffer_size = (1024 * 10) * self.format.channelCount()
    		elif (self.format.sampleRate() >= 24000):
    			self.internal_buffer_size = (1024 * 6) * self.format.channelCount()
    		else:
    			self.internal_buffer_size = (1024 * 4) * self.format.channelCount()
    				
    		self.m_audio_output = QtMultimedia.QAudioOutput(self.output_devices_qt[self.output_device_index], self.format)
    		#self.m_audio_output = QtMultimedia.QAudioOutput(self.output_devices_qt[0], self.format)
    		self.m_audio_output.setBufferSize(self.internal_buffer_size)
    			
    		self.m_size_to_buffer = int(self.timeToSize_1())
    			
    		self.m_max_size_to_buffer = self.m_size_to_buffer + int(self.timeToSize_2())
    		
    		#self.m_output_device = self.m_audio_output.start()
    		
    		self.timer_play = QtCore.QTimer(MainWindow)
    		self.timer_play.setTimerType(QtCore.Qt.PreciseTimer)
    		self.timer_play.timeout.connect(lambda:self.preplay(MainWindow))
    		self.timer_play.start(10)
    		
    		self.timer_verifier = QtCore.QTimer(MainWindow)
    		self.timer_verifier.timeout.connect(self.verifier)
    		self.timer_verifier.start(max(self.m_time_to_buffer, 10))
    		
    		#ui.stop_push_button.setEnabled(True)
    		
    	def verifier(self):
    		if (self.m_buffer.size() >= self.m_max_size_to_buffer):
    			self.m_buffer.clear()
    					
    	def timeToSize_1(self):
    		return ((self.format.channelCount() * (self.format.sampleSize() / 8) * self.format.sampleRate()) * self.m_time_to_buffer / 1000)
    		
    	def timeToSize_2(self):
    		return ((self.format.channelCount() * (self.format.sampleSize() / 8) * self.format.sampleRate()) * self.MAX_BUFFERED_TIME / 1000)
    			
    	def send_input_to_buffer(self,MainWindow,ui):
    		bytes_ready = self.m_audio_input.bytesReady()
    		if(type(bytes_ready) == int and bytes_ready>0):
    			data = self.m_input_device.readAll()
    			self.m_buffer.append(data)
    			#self.plot_buffer.append(data)
    			#self.calculate_mid_strength(ui)
    			self.preplay(MainWindow)
    			
    	def preplay(self,MainWindow):
    		if(self.m_play_called==False):
    			self.m_play_called = True
    			self.timer = QtCore.QTimer(MainWindow)
    			self.timer.setSingleShot(True)
    			self.timer.singleShot(0, self.sound_microphone)
    			
    	def sound_microphone(self):
    		self.m_play_called = False
    		if self.m_buffer.isEmpty():
    			self.m_buffer_requested = True
    			return
    		elif self.m_buffer.size() < self.m_size_to_buffer:
    			if self.m_buffer_requested:
    				return
    		else:
    			self.m_buffer_requested = False
    			
    		readlen = int(self.m_audio_output.periodSize())
    		chunks = int(self.m_audio_output.bytesFree() / readlen)
    		
    		while (chunks>0):
    			samples = self.m_buffer.mid(0, readlen)
    			len = samples.size()
    			self.m_buffer.remove(0, len)
    
    			if (len>0):
    				if(self.m_audio_output.state()!=2):
    					self.m_output_device.write(samples)
    				else:
    					return 1
    
    			if (len != readlen):
    				break;
    
    			chunks = chunks - 1
    			
    	def stop_player(self,ui,MainWindow):
    		self.m_audio_input.stop()
    		self.m_audio_output.stop()
    		
    	def start_player(self,ui,MainWindow):
    		self.m_input_device = self.m_audio_input.start()
    		self.m_audio_input.resume()
    		
    		self.m_output_device = self.m_audio_output.start()
    

    For the first deck i have made this:

    from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia
    from PyQt5 import QtCore, QtMultimedia, QtWidgets
    from PyQt5.QtTest import QSignalSpy
    from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal, QByteArray, QIODevice, QFileInfo
    from PyQt5.QtMultimedia import QAudioDecoder, QAudioFormat, QMediaObject, QAudioBuffer, QAudioOutput, QAudio
    import data
    
    class Deck1():
    	def __init__(self,ui,MainWindow):
    		self.output_devices_qt = QtMultimedia.QAudioDeviceInfo.availableDevices(QtMultimedia.QAudio.AudioOutput)
    		self.decode_test_sound(r"C:\Users\Χρήστος\Desktop\Papinhio player\project\disket box\mp3 files\ΑΓΙΑ ΚΥΡΙΑΚΗ.mp3",ui,MainWindow)
    		ui.deck_1_volume_control.valueChanged.connect(lambda volume:self.change_deck_1_volume(volume,ui,MainWindow))
    		
    	def change_deck_1_volume(self,volume,ui,MainWindow):
    		vol = volume/100
    		vol_text = round(vol,1)
    		ui.deck_1_volume_label.setText(str(vol_text)+"/1.0")
    		self.m_audio_output.setVolume(vol)
    			
    	def decode_test_sound(self,file_path,ui,MainWindow):
    		self.desiredFormat = QtMultimedia.QAudioFormat()
    		self.desiredFormat.setCodec("audio/pcm")
    		self.desiredFormat.setSampleRate(44100)
    		self.desiredFormat.setChannelCount(1)
    		self.desiredFormat.setSampleSize(16)
    		self.desiredFormat.setByteOrder(QtMultimedia.QAudioFormat.LittleEndian)
    		self.desiredFormat.setSampleType(QtMultimedia.QAudioFormat.SignedInt)
    		
    		self.m_buffer = QByteArray()
    		self.m_buffer_copy = QByteArray()
    		
    		self.decoder = QAudioDecoder()
    		self.decoder.bufferReady.connect(lambda:self.readBuffer(ui,MainWindow))
    		self.decoder.setAudioFormat(self.desiredFormat)
    		self.decoder.setSourceFilename(file_path)	
    		self.decoder.start()
    		
    		
    		
    		#self.start_player(ui,MainWindow)
    		self.play_status = 0
    		
    	def readBuffer(self,ui,MainWindow):
    		buffer = self.decoder.read()
    		count = buffer.byteCount()
    		if(count>0):
    			buffer_data = buffer.constData().asstring(count)
    			self.m_buffer.append(buffer_data)
    			if(self.play_status!=1):
    				self.start_player(ui,MainWindow)
    				self.play_status = 1
    		else:
    			return 1
    			
    	def timeToSize_1(self):
    		return ((self.desiredFormat.channelCount() * (self.desiredFormat.sampleSize() / 8) * self.desiredFormat.sampleRate()) * self.m_time_to_buffer / 1000)
    	
    	def timeToSize_2(self):
    
    		return ((self.desiredFormat.channelCount() * (self.desiredFormat.sampleSize() / 8) * self.desiredFormat.sampleRate()) * self.MAX_BUFFERED_TIME / 1000)
    	
    			
    	def preplay(self,ui,MainWindow):
    		if(self.play_status!=0):
    			if(self.m_play_called==False):
    				self.m_play_called = True
    				self.timer = QtCore.QTimer(MainWindow)
    				self.timer.setSingleShot(True)
    				self.timer.singleShot(0,lambda:self.sound_mp3(ui,MainWindow))
    			
    	def sound_mp3(self,ui,MainWindow):
    		if(self.play_status!=0):
    			self.m_play_called = False
    			if self.m_buffer.isEmpty():
    				self.stop_player(ui,MainWindow)
    				self.m_buffer_requested = True
    				return
    			elif self.m_buffer.size() < self.m_size_to_buffer:
    				if self.m_buffer_requested:
    					return
    			else:
    				self.m_buffer_requested = False
    				
    			readlen = int(self.m_audio_output.periodSize())
    			chunks = int(self.m_audio_output.bytesFree() / readlen)
    			
    			
    			while (chunks>0):
    				samples = self.m_buffer.mid(0, readlen)
    				len = samples.size()
    				self.m_buffer.remove(0, len)
    				
    				samples_data = samples.data()
    				print(samples_data)
    				if (len>0):
    					if(self.m_audio_output.state()!=2):
    						self.m_output_device.write(samples)
    					else:
    						return 1
    
    				if (len != readlen):
    					break
    
    				chunks = chunks - 1
    	
    	def start_player(self,ui,MainWindow):
    		self.m_play_called = False
    		self.m_buffer_requested = True
    		self.m_time_to_buffer = 50
    		self.MAX_BUFFERED_TIME = 100
    		
    		if (self.desiredFormat.sampleRate() >= 44100):
    			self.internal_buffer_size = (1024 * 10) * self.desiredFormat.channelCount()
    		elif (self.desiredFormat.sampleRate() >= 24000):
    			self.internal_buffer_size = (1024 * 6) * self.desiredFormat.channelCount()
    		else:
    			self.internal_buffer_size = (1024 * 4) * self.desiredFormat.channelCount()
    			
    		#self.m_audio_output = QtMultimedia.QAudioOutput(self.output_devices_qt[self.output_device_index], self.desiredFormat)
    		self.m_audio_output = QtMultimedia.QAudioOutput(self.output_devices_qt[0], self.desiredFormat)
    		self.m_audio_output.setBufferSize(self.internal_buffer_size)
    		
    		self.m_size_to_buffer = int(self.timeToSize_1())
    		
    		self.m_max_size_to_buffer = self.m_size_to_buffer + int(self.timeToSize_2())
    		
    		self.m_output_device = self.m_audio_output.start()
    		
    		self.timer_play = QtCore.QTimer(MainWindow)
    		self.timer_play.setTimerType(QtCore.Qt.PreciseTimer)
    		self.timer_play.timeout.connect(lambda:self.preplay(ui,MainWindow))
    		self.timer_play.start(10)
    		
    	def stop_player(self,ui,MainWindow):
    		self.play_status = 0
    		self.m_audio_output.stop()
    		self.timer_play.stop()
    

    I want:

    1. change the strength of audio bit rate (deck 1,microphone),
    2. change the speed of audio bit rate (deck 1)
    3. change the time position of audio bit rate (deck 1)

    Any advice would be useful.



  • @papinhio said in Working with audio multimedia in pyqt5:

    Any advice would be useful.

    Start experimenting...Oh, and read class docs.


Log in to reply