I made a program that records files and saves them to a file directory and it does save them properly. However, when I try and open it and see what was recorded I see that it has no stored audio data. I am not sure what I am doing wrong. Please take a look and let me know.
from playsound import playsound
from random import randrange
import pyttsx3
from datetime import datetime
import pyaudio
import speech_recognition as sr
import requests
import wave
import numpy as np
import sounddevice as sd
import math
import time
import os
import sys
import sounddevice as sd
from scipy.io.wavfile import write
import struct
def voiceDetection():
SoundThreshHold = 50
TimeoutLength = 5
chunk = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2 #Basicly audio output
RATE = 16000 #Rate at which you sample
f_name_directory = r"C:\Users\x\OneDrive\Desktop\Record"
def rms(data):
count = len(data)/2
format = "%dh"%(count)
shorts = struct.unpack( format, data )
sum_squares = 0.0
for sample in shorts:
n = sample * (1.0/32768)
sum_squares += n*n
return math.sqrt( sum_squares / count)*1000
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
frames_per_buffer=chunk)
currentTime = time.time()
end = time.time() + TimeoutLength
frames = []
while currentTime < end:
currentTime = time.time()
data = stream.read(chunk)
if rms(data) >= SoundThreshHold:
#print(rms(data))
end = time.time() + TimeoutLength
frames.append(data)
n_files = len(os.listdir(f_name_directory))
filename = os.path.join(f_name_directory,'{}.wav'.format(n_files))
wf = wave.open(filename,'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(data)
wf.close()
print('Written to file: {}'.format(filename))
stream.stop_stream()
stream.close()
p.terminate()
voiceDetection()
The current code writes a separate WAV file once per chunk, and always with the same name, so the file overwrites any WAV written for a previous chunk. You probably intend to call wave.open once before the loop and wf.close after the loop, so that one WAV is written for the whole the session.
Edit: Interspersing file IO during the audio recording might be too much overhead to record properly without dropping samples. You could try instead buffering up all the samples in memory and then writing the WAV all at once afterward. On the pyaudio homepage, there is a "record" example to record several seconds of audio and write it as a WAV file:
"""PyAudio example: Record a few seconds of audio and save to a WAVE file."""
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
As a general note, beware that unfortunately the (standard CPython) Python interpreter has limited ability to execute threads truly simultaneously, which makes Python a poor language for real time audio applications (see also Does python support multiprocessor/multicore programming?). Depending on your project goals, you might want to switch to C++ and use the portaudio C library (on which pyaudio is based).
Related
I'm not really that good with Python. Recently I've been toying around with pyAudio and using a simple script managed to record system sound. Thing is, the script I'm using is ran using a fixed timer. Instead, I want to end the recording whenever I want, from command line.
Does anyone know how to achieve this, if possible at all?
import pyaudio
import wave
import sys
DURATION = int(sys.argv[1])
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
CHUNK = 1024
RECORD_SECONDS = DURATION
WAVE_OUTPUT_FILENAME = "file.wav"
print("hello")
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT, channels=CHANNELS, rate=RATE, input=True, frames_per_buffer=CHUNK)
print("Recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("Finished recording")
stream.stop_stream()
stream.close()
p.terminate()
waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
waveFile.setnchannels(CHANNELS)
waveFile.setsampwidth(p.get_sample_size(FORMAT))
waveFile.setframerate(RATE)
waveFile.writeframes(b''.join(frames))
waveFile.close()
I'm trying to work with Audio on Python 3.7 on Mac(Catalina) only with the built-in Microphone and Speakers.
My Problem is that with any code I tried, when recording I receive nothing and when playing sound nothing comes out.
I tried the answers from this question: first I tried with PyAudio like this:
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
Which returns me a silent file.
Then I tried with SoundDevice:
import sounddevice as sd
import matplotlib.pyplot as plt
fs = 44100 # frames per sec
sd.default.samplerate = fs
sd.default.channels = 2
duration = 3.0 # Aufnahmezeit
recording = sd.rec( int( duration * fs) )
print("* recording")
sd.wait()
print("* done!")
t = [ i for i in range( int( duration * fs) )]
plt.plot(t, recording, 'r-')
plt.show()
Which returns an array filled with zeros: Screenshot of the Plot.
Both didn't cause any errors or warnings.
After that I tried to play a simple Sin-Wave with 440 Hz, the speaker stayed silent.
The same code, works on my friends mac without problems. The Microphone & Speakers are also working fine. And in System Preferences I allowed every app to use the microphone.
This person seems to have a similar issue. Also tried this code without result.
I have no idea what else I could try to fix this.
The failure reason and two solutions can be found at https://www.reddit.com/r/MacOS/comments/9lwyz0/mojave_not_privacy_settings_blocking_all_mic/
To reset PRAM, follow the instructions at https://thenextweb.com/lifehacks/2017/06/14/how-when-why-to-reset-the-pram-smc-on-your-mac/
I was trying to get audio data in raw format using pyaudio, to then use in pocketsphinx for my project. However, when I use the raw file generated the output by this program the output contains random noise.
I want the raw file to be usable in pocketsphinx.
import pyaudio
import wave
FORMAT = pyaudio.paInt32
CHANNELS = 1
RATE = 16000
CHUNK = 1024
RECORD_SECONDS = 2
audio = pyaudio.PyAudio()
# start Recording
stream = audio.open(format=FORMAT, channels=CHANNELS,
rate=RATE, input=True,
frames_per_buffer=CHUNK)
print "recording..."
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print "finished recording"
# stop Recording
stream.stop_stream()
stream.close()
audio.terminate()
file = open("newfile.raw", "w")
file.write(b''.join(frames))
file.close()
I want to play many input data from a microphone without buffering. I tried, but there is buffering. Here is my code.
import pyaudio
import wave
import urllib.request
import struct
import numpy as np
import sounddevice as sd
import matplotlib.pyplot as plt
# Callback function---------------------------------
def callback(indata, outdata, frames, time, status):
# if status:
# print(status)
outdata[:] = indata
#---------------------------------------------------
# Parameters ----------------------------------------------
Window_Size = 22050 # Point
FORMAT_D = pyaudio.paFloat32; FORMAT_W = pyaudio.paInt32
CHANNELS = 1 # Mono
Sample_Rate = 22050 # Hz
dT = 1/Sample_Rate
RECORD_SECONDS = 20 # s
NOFFRAMES = int(Sample_Rate/Window_Size * RECORD_SECONDS)
WAVE_OUTPUT_FILENAME = "output.wav"
#-----------------------------------------------------------
p = pyaudio.PyAudio()
stream_D = p.open(format=FORMAT_D,
channels=CHANNELS,
rate=Sample_Rate,
input=True,
frames_per_buffer=Window_Size)
stream_W = p.open(format=FORMAT_W,
channels=CHANNELS,
rate=Sample_Rate,
input=True,
frames_per_buffer=Window_Size)
print("* recording")
frames = []
# "I think the problem appears from here"------------------------------
for i in range(0, int(Sample_Rate/Window_Size * RECORD_SECONDS)):
data_D = stream_D.read(Window_Size)
# data_W = stream_W.read(Window_Size)
decoded = np.fromstring(data_D, 'Float32')
# np.savetxt(str(i)+'ttt.txt',transform)
sd.play(decoded,22050)
# frames.append(data_W)
#-------------------------------------------------------
print("* done recording")
stream_D.stop_stream()
stream_D.close()
p.terminate()
#plt.plot(transform)
#plt.show()
# Save as a wave file---------------------------
#wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
#wf.setnchannels(CHANNELS)
#wf.setsampwidth(p.get_sample_size(FORMAT_W))
#wf.setframerate(Sample_Rate)
#wf.writeframes(b''.join(frames))
#wf.close()
#-------------------------------------------
This code performs to save input data from a microphone at 1s intervals, transform byte data to nparray data (np.transform()), and play the data with a speaker (sd.play()). This code works, but there is buffering when for loop start again. I want to play the sound from a microphone smoothly. When I asked first, someone recommended to use callback function, so I added it, But, I don't know how to use it. How do I get rid of the buffering? Is there some examples? Should I use Threads or multiprocessing?
The delay is due to buffer size ... you will get a negligible delay using a 1k buffer as per
# Window_Size = 22050 # Point
Window_Size = 1024 # Point
Im been experimenting with audio recording and playback using pyaudio.
I'm able to record a file but I need to be able to add layers on top of it. What I'm trying to do is record a 10 second file then start playing.
While its playing I want to continue to record additional 10 sec layers and add them over top of the prior recording.
Is there a way to do this with Python?
import pyaudio
import wave
CHUNK = 2
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 44100
RECORD_SECONDS = 3
WAVE_OUTPUT_FILENAME = "output.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print(int(RATE / CHUNK * RECORD_SECONDS))
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
I found a module called "PyDub" which does this easily.
http://pydub.com/
from pydub import AudioSegment
track1 = AudioSegment.from_file(track1wav)
track2 = AudioSegment.from_file(track2wav)
combined = track1.overlay(track2)
print ("overlaying recording")
combined.export(track1wav, format='wav')