как исправить ошибку при записи данных неизвестной длины? - PullRequest
0 голосов
/ 26 апреля 2018

Я пытаюсь записать звук с моего микрофона требуемой длительности. Я хочу контролировать продолжительность файла, принимая пользовательский ввод. Исходя из его решения, я должен остановить запись и сохранить файл на эту длительность.

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

Я могу записывать файлы, когда определяю время в секундах. Теперь я хочу отсканировать ввод со стороны пользователя, когда остановить запись. Поэтому я изменил программу, добавив параллельную обработку , чтобы две функции выполнялись одновременно. Когда я получил ошибку рекурсии, я попытался разрешить , добавив sys.setrecursionlimit(1500), но результат ничего не изменил.

Как решить проблему, чтобы я мог записать звук в течение требуемой продолжительности.

Обновление: Ошибка и трассировка

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

Если я увеличу предел до 44000 sys.setrecursionlimit(44000), код запускается в течение примерно 1 секунды и заканчивается с ошибкой

 Process finished with exit code -1073741571 (0xC00000FD)

UPDATE2: обновленный код, предложенный @quamrana.

Два процесса не работают одновременно. Цикл не выходит за пределы функции процесса 2. тестируя операторы печати, я понимаю, что пока я не нажму 1, он зацикливается только в процессе 1, позже он переходит ко второму процессу, но не может сканировать ввод из первой функции для завершения записи.

Обновление 3: обновление аргументов процесса

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

как устранить ошибку многопроцессорной обработки?

Ответы [ 2 ]

0 голосов
/ 26 апреля 2018

Я предполагаю, что на самом деле try_recording не требуется для рекурсии, поэтому ее можно переписать так:

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

Также вы неправильно запускаете свои процессы Они должны быть:

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

И ваш флаг должен быть общей переменной:

# flag = 0
flag = multiprocessing.Value('i', 0)
0 голосов
/ 26 апреля 2018

как только вы try_recording войдете в else, как вы ожидаете обновления flag. Вы реализовали любой механизм IPC здесь. Вызывая это войти в бесконечный цикл

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...