Python 'sounddevice' library - disable audio output - python

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)

Related

Issues playing audio in pygame [duplicate]

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()

Stop and restart rtsp stream in opencv for object detection

I am working on an object_detection API implemented in tensorflow 1.14 and opencv 4.1, where my task is to recognize personal protection equipment weard by workers at various construction site gates. We are using RTSP streams, where I am already using threading to minimize latency, but still some times the stream crashes.
So I decided to restart the whole python script every 'n' times of detection to prevent the whole thing to crash because of corrupted frames and so on, but tensorflow is very slow with the loading of inference graph and such for the first time (for me its ~20 seconds), which is unacceptable to wait for the workers to get inside the site at the gate.
So now I am considering to just stop and then restart JUST the RTSP stream with opencv, which constantly feeds with frames the inference machinery for executing object detection on them.
Now I have not found any helpful threads on this topic, so that is why I am writing it here.
The relevant part of my code is here:
from threading import Thread
import cv2, time
import numpy as np
import os
import six.moves.urllib as urllib
import sys
import tarfile
from threading import Thread
import tensorflow as tf
import tensorflow.contrib.tensorrt as trt
import zipfile
from distutils.version import StrictVersion
from collections import defaultdict
from io import StringIO
from matplotlib import pyplot as plt
from PIL import Image
from object_detection.utils import ops as utils_ops
import streamlit as st
######Initialize some important stuff###############
...
###### End of initialization###############
class VideoStreamWidget(object): # create threading
detected_counter1 = 0
detected_counter2 = 0
PASS_score1 = 0
NOPASS_score1 = 0
PASS_score2 = 0
NOPASS_score2 = 0
scoresumCounter1=0
scoresumCounter2=0
PASS_score_tmp =0
NOPASS_score_tmp=0
detection_index = 0
detboxesAreaTMP1 = [0,0,0,0]
detboxesAreaTMP2 = [0,0,0,0]
def __init__(self, src=rtsp_Url):
# Create a VideoCapture object
self.capture = cv2.VideoCapture(src)
# Start the thread to read frames from the video stream
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
self.counter = 0
def update(self): # here the update of "raw" frames happen
# Read the next frame from the stream in a different thread
while True:
if self.capture.isOpened():
(self.status, self.frame) = self.capture.read()
def show_frame(self): # here inference and post processing of images happen
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget(rtsp_Url)
with detection_graph.as_default():
with tf.Session(config=tf.ConfigProto(gpu_options=tf.GPUOptions(per_process_gpu_memory_fraction=0.35))) as sess:
# Get handles to input and output tensors
ops = tf.get_default_graph().get_operations()
all_tensor_names = {output.name for op in ops for output in op.outputs}
tensor_dict = {}
for key in ['num_detections', 'detection_boxes', 'detection_scores','detection_classes', 'detection_masks']:
tensor_name = key + ':0'
if tensor_name in all_tensor_names:
tensor_dict[key] = tf.get_default_graph().get_tensor_by_name(tensor_name)
resfresherCounter = 0
while True:
# I think here it should be implemented somehow to close the stream and reopen it
try:
video_stream_widget.show_frame() # here the objec tdetection happens
except cv2.error as e:
print(e)
continue
My whole code is here:
https://pastebin.com/7qBFwwfy
Thank you in advance!

How to make Python wait while QGIS renders a shapefile

I have written code for my QGIS 2.8.1 which can successfully take screenshot of one shape file, but unfortunately it doesn't work when I try with multiple shapefiles.
So basically if I replace allFiles = ["C:/Shapefiles/Map_00721.shp"] in the code below with allFiles = ["C:/Shapefiles/Map_00721.shp", "C:/Shapefiles/Map_00711.shp", "C:/Shapefiles/Map_00731.shp", "C:/Shapefiles/Map_00791.shp", "C:/Shapefiles/Map_00221.shp"], the loop iterates over the array without waiting for the rendering and snapshot process to happen.
I have tried using time.sleep in the code below, but it stops the rendering of shapefiles too and the result doesn't came as expected.
import ogr,os
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from qgis.core import *
import qgis.utils
import glob
from time import sleep
import math
import processing
from processing.core.Processing import Processing
from PyQt4.QtCore import QTimer
Processing.initialize()
Processing.updateAlgsList()
OutputFileName = "ABC" # Temprory global placeholder for filename
canvas = iface.mapCanvas()
def startstuffs():
qgis.utils.iface.zoomToActiveLayer() # Zoom to Layer
scale=canvas.scale() # Get current Scale
scale = scale * 1.5
canvas.zoomScale(scale) # Zoomout a bit
QTimer.singleShot(2000,saveImg) # Jump to save img
def saveImg():
qgis.utils.iface.mapCanvas().saveAsImage(OutputFileName)
QgsMapLayerRegistry.instance().removeAllMapLayers()
# Add array of address below
allFiles = ["C:/Shapefiles/Map_00721.shp"]
filesLen = len(allFiles)
TexLayer = "C:/US_County_NAD27.shp"
for lop in range(filesLen):
currentShpFile = allFiles[lop]
currentShpFileName = currentShpFile.strip("C:/Shapefiles/")
OutputFileName = "C:/ImageOut/" + currentShpFileName + ".png"
wb = QgsVectorLayer(currentShpFile, currentShpFileName, 'ogr')
wbTex = QgsVectorLayer(TexLayer, 'CountyGrid', 'ogr')
QgsMapLayerRegistry.instance().addMapLayer(wb) # Add the shapefile
QgsMapLayerRegistry.instance().addMapLayer(wbTex) # Add the county shapefile
qgis.utils.iface.setActiveLayer(wb) # Makes wb as active shapefile
QTimer.singleShot(3000, startstuffs) # This start stuffs
print "Done!"
Avoid using time.sleep() since that will completely stall your entire program. Instead, use processEvents() which allows your program to render in the background.
import time
def spin(seconds):
"""Pause for set amount of seconds, replaces time.sleep so program doesn't stall"""
time_end = time.time() + seconds
while time.time() < time_end:
QtGui.QApplication.processEvents()
This method should work fine for a quick fix, but in the long term it may generate difficult problems to track. It is better to use a QTimer with a event loop for a permanent solution.

Threading in Python doesn't take keyboard interrupts

I am newbie in Threading and I am writing a simple program which can do two tasks simultaneously. One function will record audio for arbitrary duration and the other function will just print some messages. In the record function, the Ctrl+C keyboard interrupt is used to stop the recording. But, if I put this function into a python thread, the Ctrl+C is not working and I am not able to stop the recording. The code is as follows. Any help is kindly appreciated.
import argparse
import tempfile
import queue
import sys
import threading
import soundfile as sf
import sounddevice as sd
def callback(indata, frames, time, status):
"""
This function is called for each audio block from the record function.
"""
if status:
print(status, file=sys.stderr)
q.put(indata.copy())
def record(filename='sample_audio.wav'):
"""
Audio recording.
Args:
filename (str): Name of the audio file
Returns:
Saves the recorded audio as a wav file
"""
q = queue.Queue()
try:
# Make sure the file is open before recording begins
with sf.SoundFile(filename, mode='x', samplerate=48000, channels=2, subtype="PCM_16") as file:
with sd.InputStream(samplerate=48000, channels=2, callback=callback):
print('START')
print('#' * 80)
print('press Ctrl+C to stop the recording')
print('#' * 80)
while True:
file.write(q.get())
except OSError:
print('The file to be recorded already exists.')
sys.exit(1)
except KeyboardInterrupt:
print('The utterance is recorded.')
def sample():
for i in range(10):
print('---------------------------------------------------')
def main():
# Threading
thread_1 = threading.Thread(target=record, daemon=True)
thread_2 = threading.Thread(target=sample, daemon=True)
thread_1.start()
thread_2.start()
thread_1.join()
thread_2.join()
if __name__ == "__main__":
main()

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.

Categories

Resources