how to fix Error while recording data of unknown length?

0

I am trying to record the audio from my microphone of required duration. I want to control the duration of the file by taking the user input.Based on its decision I have to stop recording and save the file for that duration.

import pyaudio
import wave
from multiprocessing import Process

global flag
global frames

def try_recording(stream,RATE, CHUNK):
    while flag != 1:
        #for i in range(0,int(RATE/CHUNK*DURATION): 
        for i in range(0,int(RATE/CHUNK)):
            data = stream.read(CHUNK)
            frames.append(data)

def scan_input():
    num = input('Enter input number: ')
    if int(num) == 1:
       flag = 1
    else:
       scan_input()

if __name__=='__main__':
    FORMAT = pyaudio.paInt16
    CHANNELS = 2
    RATE = 44100
    CHUNK = 1024

    WAVE_OUTPUT_FILENAME = "file.wav"
    flag = 0

    audio = pyaudio.PyAudio()

    # start Recording
    stream = audio.open(format=FORMAT, channels=CHANNELS,
                    rate=RATE, input=True,
                    frames_per_buffer=CHUNK)
    print("recording...")
    frames = []
    #sys.setrecursionlimit(1500)
    p1 = Process(target=try_recording, args = (stream,RATE,CHUNK))
    p1.start()
    p2 = Process(target=scan_input)
    p2.start()

    #frames = try_recording(stream, RATE, CHUNK)
    print('finished recording')
    # stop Recording
    stream.stop_stream()
    stream.close()
    audio.terminate()

    waveFile = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
    waveFile.setnchannels(CHANNELS)
    waveFile.setsampwidth(audio.get_sample_size(FORMAT))
    waveFile.setframerate(RATE)
    waveFile.writeframes(b''.join(frames))
    waveFile.close()

I am able to record files when I define the time in seconds. Now I want to scan the input from user end when to stop the recording. So I modified the program by adding parallel processing so that two functions run simultaneously. When I got a recursion error, I tried to resolve it by adding sys.setrecursionlimit(1500) but the result doesn't change anything.

How to resolve the issue so that I can record the audio for my required duration.

Update: Error and traceback

recording...
Traceback (most recent call last):
  File "D:/Projects/Trails/try.py", line 14, in try_recording
try_recording(stream,RATE,CHUNK)
  File "D:/Projects/Trails/try.py", line 14, in try_recording
try_recording(stream,RATE,CHUNK)
  File "D:/Projects/Trails/try.py", line 14, in try_recording
try_recording(stream,RATE,CHUNK)
  [Previous line repeated 995 more times]
  File "D:/Projects/Trails/try.py", line 9, in try_recording
     if flag == 1:
  RecursionError: maximum recursion depth exceeded in comparison

If I increase the limit to 44000 sys.setrecursionlimit(44000) the code runs for approx 1 sec and ends with error

 Process finished with exit code -1073741571 (0xC00000FD)

UPDATE2: updated code as suggested by @quamrana.

The two processes are not working simultaneously. Loop doesnt come outside of the process 2 function. testing with print statements I understand that until I press 1 it is looping only in process 1, later it is moving to second process but not able to scan input from first function to end the recordings.

Update 3: updating the Process arguments

Traceback (most recent call last):
File "D:/Projects/Trails/try.py", line 42, in <module>
p1.start()
File "C:\Program Files\Python36\lib\multiprocessing\process.py", line 105, in start
self._popen = self._Popen(self)
File "C:\Program Files\Python36\lib\multiprocessing\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Program Files\Python36\lib\multiprocessing\context.py", line 322, in _Popen
return Popen(process_obj)
File "C:\Program Files\Python36\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
File "C:\Program Files\Python36\lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: can't pickle _portaudio.Stream objects
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
File "C:\Program Files\Python36\lib\multiprocessing\spawn.py", line 115, in _main
self = reduction.pickle.load(from_parent)
EOFError: Ran out of input

how to resolve multiprocessing pickle error ?

python
recursion
multiprocessing
ipc
audio-recording
asked on Stack Overflow Apr 26, 2018 by Raady • edited Apr 26, 2018 by Raady

2 Answers

1

I assume that you don't actually require try_recording to be recursive, so it can be rewritten like this:

def try_recording(stream,RATE, CHUNK):
    while flag != 1:
        for i in range(0,int(RATE/CHUNK)):
            data = stream.read(CHUNK)
            frames.append(data)

Also you are not starting your processes correctly. They should be:

p1 = Process(target=try_recording, args=(stream,RATE,CHUNK))
p2 = Process(target=scan_input)

And your flag should be a shared variable:

# flag = 0
flag = multiprocessing.Value('i', 0)
answered on Stack Overflow Apr 26, 2018 by quamrana • edited Apr 26, 2018 by quamrana
0

once you try_recording goes into else, how are you expecting flag to be updated. you have implemented any IPC mechanism here. Causing it go into an infinite loop

answered on Stack Overflow Apr 26, 2018 by akshat

User contributions licensed under CC BY-SA 3.0