Maison  >  Questions et réponses  >  le corps du texte

python - pyaudio stream.close() provoque le crash du programme et l'exception ne peut pas être interceptée

Je souhaite utiliser fréquemment pyaudio pour lire de l'audio. Bien qu'il ne s'agisse pas d'un module multithread, il n'utilise qu'un seul sous-thread pour lire. Il ne devrait y avoir aucun problème avec le thread principal contrôlant le commutateur de lecture. Mais quand je l'ai utilisé pour jouer, j'ai rencontré des problèmes que je n'ai pas pu résoudre.

import threading
import wave
import pyaudio
import time
pa=pyaudio.PyAudio()
f=wave.open('/home/dyan/catkin_ws/src/hlf_robot/scripts/hlf_voice/my.wav','rb')
raw_data=f.readframes(f.getnframes())
f.close()
samplewidth,channels,framerate,raw_data=2,1,16000,raw_data

i=0
stream1=''
def test():
    while True:
        global i,pa,stream1
        try:
            print i
            stream1=pa.open(format=pa.get_format_from_width(samplewidth),
                            channels=channels,
                            rate=framerate,
                            output=True)
            stream1.write(raw_data)
    
            i+=1
            print i
        except IOError,e:
                print e
        except Exception,e:
                print e
                break
t0=threading.Thread(target=test)
t0.start()
time.sleep(3)
while True:
    if stream1.is_active():
        print "is_active"
    else:
        print "not active"
    if stream1.is_stopped():
        print "is_stopped"
    else:
        print "not stopped"
    print stream1._is_running
    print stream1._stream
    print '123'
    try:
        stream1.stop_stream()
        print '456'
        stream1.close()
    except Exception,e:
        print e
        break
    print '789'
    time.sleep(3)

La sortie est comme ça, puis elle plante

0                                                #子线程循环第一次
is_active                                        #
not stopped                                      #
True                                             #stream1._is_running
<_portaudio.Stream object at 0x7efd71e00cb0>     #stream1._stream
123                                              #调用stop_stream()之前
456                                              #调用stop_stream()之后,close()之前
[Errno Unanticipated host error] -9999           #子线程捕获到主线程调用stream1.stop_stream()时由stream1.write()抛出的异常IOError,忽略这个异常继续执行
0                                                #子线程stream1.write()抛出异常i+=1未执行继续循环在pa.open()之前的print

1. En d'autres termes, appeler stream1.close() après avoir appelé stream1.stop_stream() a provoqué le crash du programme, et ni le thread enfant ni le thread principal n'ont détecté l'exception ! ! ! !
2. Si vous commentez close() après stop_stream(), il n'y aura aucun problème pendant une courte période. Cependant, s'il continue à fonctionner pendant environ 10 minutes, il ne plantera pas mais ne pourra plus le faire. pour continuer à jouer. pa.open() continue de lancer une exception [Errno Combinaison illégale de périphériques d'E/S] -9993 Lorsque je ferme le programme et que je le redémarre, pa.open() lèvera une exception (« Taux d'échantillonnage non valide », -9997). .Pour la lecture Pas plus ! ! !

Comment résoudre ce problème ?


Pour le moment, la solution consiste à rouvrir un objet pyaudio.Pyaudio() à chaque fois qu'il est lu, ce qui consomme environ 10 ms de temps CPU supplémentaire. Je l'ai fait fonctionner en continu pendant près de 20 heures sans aucun problème.

...
try:
    self.pa=pyaudio.PyAudio()
                    
    self.stream=self.pa.open(format=self.pa.get_format_from_width(samplewidth),
                    channels=channels,
                    rate=framerate,
                    output=True)
    self.stream.write(raw_data)
except IOError,e:
    pass
finally:
    self.stream.close()
    self.pa.terminate()
...
我想大声告诉你我想大声告诉你2686 Il y a quelques jours1181

répondre à tous(1)je répondrai

  • 阿神

    阿神2017-06-12 09:27:06

    Voici une solution de contournement possible, a commenté ghost le 30 juillet 2016

    répondre
    0
  • Annulerrépondre