Issues playing audio in pygame [duplicate] - python

I am recording audio using sounddevice and I want to play it through a virtual audio cable through pygame, I keep receiving this error Exception has occurred: error mpg123_seek: Invalid RVA mode. (code 12)
My code is below:
import sounddevice as sd
from scipy.io.wavfile import write
import random
import pygame
import time
pygame.init()
pygame.mixer.init(devicename='CABLE Input (VB-Audio Virtual Cable)')
fs = 44100 # Sample rate
seconds = 00.1 # Duration of recording
def main():
for x in range(10000):
number = random.randint(1,9999999)
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
sd.wait() # Wait until recording is finished
write(f'output/output{str(number)}.mp3', fs, myrecording) # Save as WAV file `
# PLAY MIC SOUND HERE
pygame.mixer.music.load(f'output/output{str(number)}.mp3') #Load the mp3
pygame.mixer.music.play() #Play it
time.sleep(00.1)
main()
Any help is appreciated.

There's a couple of issues.
The first is that scipi.io.wavefile.write() only writes an uncompressed WAV file (ref: https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.wavfile.write.html ). You might name it .mp3, but it's not compressed that way.
The next issue is that pygame.mixer.music will not .load() uncompressed WAV files. So... what to do...
One work-around is to use the base pygame.mixer, which is happy to load uncompressed WAV. And while I don't have an 'CABLE Input (VB-Audio Virtual Cable)' device, I do get a nice file of silence, which I validated with the sound-editing program Audacity, and this seems to play OK.
import sounddevice as sd
from scipy.io.wavfile import write
import pygame
import time
import random
pygame.init()
pygame.mixer.init(devicename='CABLE Input (VB-Audio Virtual Cable)')
fs = 44100 # Sample rate
seconds = 00.1 # Duration of recording
def main():
for x in range(10000):
number = random.randint(1,9999999)
myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=2)
sd.wait() # Wait until recording is finished
filename = f'output/output{str(number)}.wav'
write(filename, fs, myrecording) # Save as uncompressed WAV file
# PLAY MIC SOUND HERE
print( "Playing [" + filename + "]" )
#pygame.mixer.music.load(filename) #Load the wav
#pygame.mixer.music.play() #Play it
#while ( pygame.mixer.music.get_busy() ): # wait for the sound to end
# time.sleep(00.1)
sound = pygame.mixer.Sound(filename) #Load the wav
sound.play() #Play it
while ( pygame.mixer.get_busy() ): # wait for the sound to end
time.sleep(00.1)
main()

Related

Not synchronized audio and video recorded with python

i bought an USB microphone and a Camera module for the raspberry pi4. I managed to record Audio and Video but when i merge them with ffmpeg the are not synchronized, i'm trying to solve this for 2 days now.
Here my code, when the program starts it record video with the instruction "camera.start_recording("Video.h264")", this instruction return immediatly so when the program executes the instruction after camera.start_recording("Video.h264") the video is still recording.
For recording Audio i use a while loop that stops when i press a button. When i press the button the video recording also stops.
After everything is written i use ffmpeg to merge the video (After converting it to mp4) and the Audio.
# coding=utf-8
from picamera import PiCamera
import pyaudio
import wave
import os
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
print("Ready")
go = True
camera = PiCamera()
camera.resolution = (1920, 1080)
audio = pyaudio.PyAudio()
stream = audio.open(format=pyaudio.paInt16, channels=1, rate=44100, input=True)
frames = []
camera.start_recording("Video.h264")
while go:
print("Recording")
if GPIO.input(10) == GPIO.HIGH:
camera.stop_recording()
go = False
print("Recording has been stopped")
data = stream.read(1024, exception_on_overflow = False)
frames.append(data)
stream.stop_stream()
stream.close()
audio.terminate()
sound_file = wave.open("Audio.wav", "wb")
sound_file.setnchannels(1)
sound_file.setsampwidth(audio.get_sample_size(pyaudio.paInt16))
sound_file.setframerate(44100)
sound_file.writeframes(b''.join(frames))
sound_file.close()
print("Converting in mp4")
os.system("ffmpeg -i Video.h264 Video.mp4")
print("Merging audio and video")
os.system("ffmpeg -i Video.mp4 -i Audio.wav -c:v copy -c:a aac vea.mp4")

How to stop audio with playsound module?

How do I stop the audio playing through playaudio module in Python code?
I have played music but I can't stop that music. How can I stop it?
playsound.playsound("name_of_file")
You can use the multiprocessing module to play the sound as a background process, then terminate it anytime you want:
import multiprocessing
from playsound import playsound
p = multiprocessing.Process(target=playsound, args=("file.mp3",))
p.start()
input("press ENTER to stop playback")
p.terminate()
Playsound is a single function module that plays sounds, and nothing else. It would seem that means it does not stop playing sounds either. From their own documentation:
The playsound module contains only one thing - the function (also named) playsound.
Personally, I like to use pyaudio. The following code is adapted from the example here. The code plays audio and has the space bar set as a pause/play button.
import pyaudio
import wave
import time
from pynput import keyboard
paused = False # global to track if the audio is paused
def on_press(key):
global paused
print (key)
if key == keyboard.Key.space:
if stream.is_stopped(): # time to play audio
print ('play pressed')
stream.start_stream()
paused = False
return False
elif stream.is_active(): # time to pause audio
print ('pause pressed')
stream.stop_stream()
paused = True
return False
return False
# you audio here
wf = wave.open('audio\\songs\\And_Your_Bird_Can_Sing_mp3_2_wav.wav', 'rb')
# instantiate PyAudio
p = pyaudio.PyAudio()
# define callback
def callback(in_data, frame_count, time_info, status):
data = wf.readframes(frame_count)
return (data, pyaudio.paContinue)
# open stream using callback
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True,
stream_callback=callback)
# start the stream
stream.start_stream()
while stream.is_active() or paused==True:
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
time.sleep(0.1)
# stop stream
stream.stop_stream()
stream.close()
wf.close()
# close PyAudio
p.terminate()
On windows try:
import winsound
winsound.PlaySound(r'C:\sound.wav', winsound.SND_ASYNC)
Stop Playback:
winsound.PlaySound(None, winsound.SND_PURGE)
#pip install pygame
from pygame import mixer
import time
mixer.init() #Initialzing pyamge mixer
mixer.music.load('lovingly-618.mp3') #Loading Music File
mixer.music.play() #Playing Music with Pygame
time.sleep(5)
mixer.music.stop()
Here is a much easier way:
wmp = win32com.client.dynamic.Dispatch("WMPlayer.OCX")
wmp.settings.autoStart = True
wmp.settings.volume = 100
wmp.URL = file
while globals()["allowSound"]:
PumpWaitingMessages()
You can change globals()["allowSound"] from another thread and set it to false when the audio has ended (you can get the length of the audio with wmp.durationString)
Here is some more info about this: Windows Media Player COM Automation works from VBS but not from Python
Although this does not use the playsound module it is a good alternative.
After successful execution of the program, audio file will start playing. Now Click on terminal, once you see the cursor, type Ctrl+C, it will bring you out of the terminal and audio will also stop playing.
Programming Instructions used:
from playsound import playsound
playsound('//path//to//a//sound//file//you//want//to//play.mp3')
EASY......
on your terminal tab, look for kill(delete) option on the right hand side.
click the delete option and it will stop playing

Raspberry pi I2S MEMS Microphone Right CHN Mono Using pyaudio

I am using Adafruit I2S MEMS Microphone Breakout for recording. ref. https://learn.adafruit.com/adafruit-i2s-mems-microphone-breakout?view=all
When i wire the Mic to RPI in Mono configuration as per below image I am able record audio using arecord command and below python code
arecord -D dmic_sv -c2 -r 48000 -f S32_LE -t wav -V mono -v recording.wav
Python Code snippet:
channels=1, rate=48000, frames_per_buffer=2400
def start_recording(self):
try:
self.logger.info("start_recording()> enter")
# Use a stream with a callback in non-blocking mode
self._stream = self._pa.open(format=pyaudio.paInt32,
channels=self.channels,
rate=self.rate,
input=True,
frames_per_buffer=self.frames_per_buffer,
stream_callback=self.get_callback())
self._stream.start_stream()
self.logger.info("start_recording()> exit")
return self
except Exception, e:
self.logger.error("start_recording()>", exc_info = True)
But If I connect channel selection pin to logic high vltage i am able to record audio using arecord command but uanble to record using python code.
Any changes required in python code to record right channel mono audio?
I did something similar but using python-sounddevice. Here's my repo
EDIT:
here is the specific audio recording class for clarification
import threading
import queue
import numpy
import sounddevice as sd
import soundfile as sf
class AudioRecorder():
def __init__(self):
self.open = True
self.file_name = 'name_of_file.wav'
self.channels = 1
self.q = queue.Queue()
# Get samplerate
device_info = sd.query_devices(2, 'input')
self.samplerate = int(device_info['default_samplerate'])
def callback(self, indata, frames, time, status):
# This is called (from a separate thread) for each audio block.
if status:
print(status, file=sys.stderr)
self.q.put(indata.copy())
def record(self):
with sf.SoundFile(self.file_name, mode='x', samplerate=self.samplerate, channels=self.channels) as file:
with sd.InputStream(samplerate=self.samplerate, channels=self.channels, callback=self.callback):
while(self.open == True):
file.write(self.q.get())
EDIT 2: The code is a Python Class that creates an audio file using an I2S microphone similar to the image shown in the question. While the value self.open is true, sounddevice will write the audio data into a queue (def callback) and then write the data into a file. All you have to do is toggle self.open to start and stop recording.

Python 'sounddevice' library - disable audio output

This script checks sound level and visualizes it on the terminal. My only problem is that the script outputs the stream to the assigned audio output (HDMI or headphone jack). With the microphone on, it can create feedback. I could turn the volume down but I wonder if I can disable the audio output at all?
import sounddevice as sd
from numpy import linalg as LA
import numpy as np
duration = 10 # seconds
def print_sound(indata, outdata, frames, time, status):
volume_norm = np.linalg.norm(indata)*10
print (int(volume_norm))
with sd.Stream(callback=print_sound):
sd.sleep(duration * 1000)

Pygame plays a mp3 file faster than normal speed

I use Python to play a short mp3 audio file. But the playing speed is faster than other music players.
My Code:
import pygame
import time
pygame.mixer.init(frequency=22050, size=16, channels=2, buffer=4096)
file=r'test.mp3'
try:
pygame.mixer_music.load(file)
pygame.mixer_music.play()
while pygame.mixer_music.get_busy():
time.sleep(0.1)
except Exception as err:
print(err)
Please help me to solve this issue!
This will work:
import time, os
from pygame import mixer
from pydub import AudioSegment
# original file: "slow.mp3"
# new fast file: "fast.mp3"
# speed: 1.3 (1.0 is actual speed)
def speed_swifter(sound, speed=1.0):
sound_with_altered_frame_rate = sound._spawn(sound.raw_data, overrides={"frame_rate": int(sound.frame_rate * speed)})
return sound_with_altered_frame_rate
newSpeed = 1.3
sound = AudioSegment.from_file("slow.mp3")
speed_sound = speed_swifter(sound, newSpeed)
speed_sound.export(os.path.join("fast.mp3"), format="mp3")
mixer.init()
mixer.music.load("fast.mp3")
mixer.music.play()
while mixer.music.get_busy():
time.sleep(0.1)
import pygame, mutagen.mp3
song_file = "your_music.mp3"
mp3 = mutagen.mp3.MP3(song_file)
pygame.mixer.init(frequency=mp3.info.sample_rate)
pygame.mixer.music.load(song_file)
pygame.mixer.music.play()

Categories

Resources