如何解决错误:NameError: name 'stream' is not defined (PyAudio, Python, RaspberryPi)

问题描述 投票:0回答:0

我正在通过此链接重新创建项目: PYAUDIO录音中断-旋转电话

我已经连接好所有东西并安装了所有必要的库。当我运行脚本(我已对其进行了相应修改)以播放我的音频文件并提起挂钩开关时,调试器会发布以下错误:

回溯(最后一次通话): 文件“/home/brian/Documents/imtest 2 RPi.py”,第 48 行,在 on_turn if stream.is_active(): # 暂停音频的时间 NameError:名称“流”未定义

全局暂停变量期间出现错误:

有人能告诉我如何解决这个问题吗?

Chat GPT 说:
您遇到的错误表明变量

stream
未在
on_turn
函数的范围内定义。似乎
stream
已在代码的
still_picked_up
部分中定义和使用,但在
on_turn
函数中无法访问它。

我已经尝试实施它建议的修复但无济于事。任何建议将不胜感激,并在此先感谢您。

global paused
paused = False    # global to track if the audio is skipped
def on_turn(skip):
    global paused
    if stream.is_active():   # time to pause audio
        print ('audio skipped')
        paused = False

完整代码在这里:

import RPi.GPIO as GPIO  
import math, sys, os
import random
import pyaudio
import wave
import multiprocessing
import time
from pydub import AudioSegment
from pydub.playback import play
from time import sleep, perf_counter
from subprocess import call

#blue wire = 3.3v ; white / green / black = ground ; blue wire = gpio17 ; white wire = gpio27 ; red wire = gpio22

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)  
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_UP) #this input is if the dial is turning, not at it's resting state 
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP) #this input counts the number of dial circuits, used to translate the dialed number
GPIO.setup(22,GPIO.IN, pull_up_down=GPIO.PUD_UP) #this input is the receiver switch, if the handset is lifted up or not

GPIO.add_event_detect(22, GPIO.BOTH) #this event is when the handset is lifted)

old_pick_up_state = GPIO.input(22)
pick_up_state = GPIO.input(22)

#global variables
global is_picked_up
is_picked_up = False
global has_recorded
has_recorded = False
global still_picked_up
still_picked_up = False
global shutdown
shutdown = False
global play_menu
play_menu = True
global sexy_noise
sexy_noise = False
global beast_number
beast_number = False
global has_recorded_options
has_recorded_options = False


global paused
paused = False    # global to track if the audio is skipped
def on_turn(skip):
    global paused
    if stream.is_active():   # time to pause audio
        print ('audio skipped')
        paused = False


GPIO.add_event_detect(27, GPIO.BOTH, callback=on_turn) #this event is when the dial is turning

def bigcheck():
    pick_up_state = GPIO.input(22)
    old_pick_up_state = 1
    if pick_up_state != old_pick_up_state:
        if pick_up_state == 1: #the handset is picked up!
            print("handset lifted")
            is_picked_up = True
            old_pick_up_state = 1
        else: #the handset is put down
            print("handset down")
            is_picked_up = False
            global still_picked_up
            still_picked_up = False
            global has_recorded
            has_recorded = False
            global has_recorded_options
            has_recorded_options = False
            play_menu = True
            old_pick_up_state = 0
            call(["amixer", "-D", "pulse", "sset", "Master", "100%+"])
            return


c=0 
last = 1

def count(pin):
    global c 
    c = c + 1
#this c and count script is used in translating the dialed number

while True:
    
    pick_up_state = GPIO.input(22)
    if pick_up_state != old_pick_up_state:
        if pick_up_state == 1: #the handset is picked up!
            print("handset lifted")
            is_picked_up = True
            old_pick_up_state = 1
        else: #the handset is put down
            print("handset down")
            is_picked_up = False
            still_picked_up = False
            has_recorded = False
            play_menu = True
            old_pick_up_state = 0
            call(["amixer", "-D", "pulse", "sset", "Master", "100%+"])

    if is_picked_up: #plays the intro upon handset pickup
        sleep(1)
        call(["amixer", "-D", "pulse", "sset", "Master", "100%+"])
        random_intro = random.choice(os.listdir("/home/pi/Music/Rotary_Recordings/mcgrath/")) #chooses one of the four intro recordings
        intro = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/mcgrath/"+random_intro)
        intro2 = intro - 20
        print('playing intro')
        play(intro2)
        still_picked_up = True
        is_picked_up = False
        paused = True
    
    if still_picked_up: #after the intro, goes to the main menu
        if play_menu:
            call(["amixer", "-D", "pulse", "sset", "Master", "75%-"])
            wf = wave.open('/home/pi/Music/Rotary_Recordings/menu-options-mcgrath.wav', 'rb') #your audio here
            p = pyaudio.PyAudio() #instantiate PyAudio
            def callback(in_data, frame_count, time_info, status): #define callback
                data = wf.readframes(frame_count)
                return (data, pyaudio.paContinue)
            stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), #open stream using callback
                channels=wf.getnchannels(),
                rate=wf.getframerate(),
                output=True,
                stream_callback=callback)
            stream.start_stream() #start the stream
            while stream.is_active() and paused==True: #wait for stream to finish
                #with on_turn as listener:
                    #listener.join()
                time.sleep(0.1)
            stream.stop_stream() #stop the stream
            stream.close()
            wf.close()
            p.terminate() #close pyaudio
            call(["amixer", "-D", "pulse", "sset", "Master", "75%+"])
            paused = True
            print('played menu')
            play_menu = False

        try:        
            if GPIO.event_detected(27):
                current = GPIO.input(27)
                if(last != current):
                    if(current == 0):
                        GPIO.add_event_detect(17, GPIO.BOTH, callback=count, bouncetime=10)
                    else:
                        GPIO.remove_event_detect(17)
                        number = int((c)/2)
                        print ("You dial", number)
                        c= 0

                        
                        if(number == 1):#code for the prefice audio and recording a message
                            prefice = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/prefice-mcgrath.wav")
                            prefice2 = prefice - 20
                            prefice_beep = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/beep.wav")
                            prefice_beep2 = prefice_beep - 20
                            print('playing prefice')
                            play(prefice2)
                            play(prefice_beep2)
                            print('prefice played now recording')
                            try:
                                file = open('count.txt','r')
                                n = int(file.read())
                                file.close()
                            except IOError:
                                file = open('count.txt','w')
                                file.write('1')
                                file.close()
                                n = 1
                            print(n)

                            n += 1

                            with open('count.txt','w') as file:
                                file.write(str(n))
                            print("Now the variable n persists and is incremented every time.")
                            #Do what you want to do further, the value of n will increase every time you run the program
                            
                            has_recorded = True
                            has_recorded_options = True
                            play_menu = True
                            
                            start_rtime = perf_counter()
                            
                            chunk = 1024  # Record in chunks of 1024 samples
                            sample_format = pyaudio.paInt16  # 16 bits per sample
                            channels = 2
                            fs = 44100  # Record at 44100 samples per second
                            seconds = 30
                            file="/home/pi/Music/Guest Recordings/"
                            wavey=".wav"
                            filename=file+str(n)+wavey

                            p = pyaudio.PyAudio()  # Create an interface to PortAudio

                            print('Recording')

                            stream = p.open(format=sample_format,
                                            channels=channels,
                                            rate=fs,
                                            frames_per_buffer=chunk,
                                            input=True)

                            frames = []  # Initialize array to store frames

                            # Store data in chunks for 3 seconds
                            for i in range(0, int(fs / chunk * seconds)):
                                data = stream.read(chunk)
                                frames.append(data)
                                bigcheck()
                                if still_picked_up==False:
                                    break

                            # Stop and close the stream 
                            stream.stop_stream()
                            stream.close()
                            # Terminate the PortAudio interface
                            p.terminate()

                            print('Finished recording')

                            # Save the recorded data as a WAV file
                            wf = wave.open(filename, 'wb')
                            wf.setnchannels(channels)
                            wf.setsampwidth(p.get_sample_size(sample_format))
                            wf.setframerate(fs)
                            wf.writeframes(b''.join(frames))
                            wf.close()

                            end_rtime = perf_counter()
                            print(f'This recording length is {end_rtime- start_rtime: 0.2f} second(s).')
                            
                            print("potential recording")
                            still_picked_up = False
                            
                            #play loud beep denoting end
                            message_end_beep = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/beep.wav")
                            message_end_beep2 = message_end_beep - 20
                            print('playing message end beep')
                            play(message_end_beep2)
                            
                        if(number == 2):#python code to play a random guest recording from the recording folder
                            #call(["amixer", "-D", "pulse", "sset", "Master", "100%+"])
                            random_recording1 = random.choice(os.listdir("/home/pi/Music/Guest Recordings/"))
                            random_recording2 = "/home/pi/Music/Guest Recordings/"+random_recording1
                            #random_recording3 = random_recording2 - 20
                            print("playing recorded " + random_recording1)
                            
                            call(["amixer", "-D", "pulse", "sset", "Master", "80%-"])
                            
                            wf = wave.open(random_recording2, 'rb') #your audio here
                            p = pyaudio.PyAudio() #instantiate PyAudio
                            def callback(in_data, frame_count, time_info, status): #define callback
                                data = wf.readframes(frame_count)
                                return (data, pyaudio.paContinue)
                            stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), #open stream using callback
                                channels=wf.getnchannels(),
                                rate=wf.getframerate(),
                                output=True,
                                stream_callback=callback)
                            stream.start_stream() #start the stream
                            while stream.is_active() and paused==True: #wait for stream to finish
                                #with on_turn as listener:
                                    #listener.join()
                                time.sleep(0.1)
                            stream.stop_stream() #stop the stream
                            stream.close()
                            wf.close()
                            p.terminate() #close pyaudio
                            call(["amixer", "-D", "pulse", "sset", "Master", "80%+"])
                            paused = True
                            
                            play_menu = True
                            sleep(1)
                            
                        if(number == 5):#this number plays a random song from the song library (McGrath choice = Matrix operator)
                            #songnumber = random.randint(2, 8)
                            #randomsong = "/home/pi/Music/Songs/"+str(songnumber)+".wav"
                            #randomsong2 = randomsong - 10
                            matrix = "/home/pi/Music/Rotary_Recordings/Matrix-mcgrath.wav"
                            print('playing Matrix using pydub')
                            call(["amixer", "-D", "pulse", "sset", "Master", "40%-"])
                            
                            wf = wave.open(matrix, 'rb') #your audio here
                            p = pyaudio.PyAudio() #instantiate PyAudio
                            def callback(in_data, frame_count, time_info, status): #define callback
                                data = wf.readframes(frame_count)
                                return (data, pyaudio.paContinue)
                            stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), #open stream using callback
                                channels=wf.getnchannels(),
                                rate=wf.getframerate(),
                                output=True,
                                stream_callback=callback)
                            stream.start_stream() #start the stream
                            while stream.is_active() and paused==True: #wait for stream to finish
                                #with on_turn as listener:
                                    #listener.join()
                                time.sleep(0.1)
                            stream.stop_stream() #stop the stream
                            stream.close()
                            wf.close()
                            p.terminate() #close pyaudio
                            call(["amixer", "-D", "pulse", "sset", "Master", "40%+"])
                            paused = True
                            
                            
                            play_menu = True
                            sleep(1)
                        
                        if(number == 4):#this number plays a Lincoln bark (McGrath choice)
                            #fartnumber = random.randint(2, 16)
                            #fartnoise = AudioSegment.from_wav("/home/pi/Music/Sound_Effects/farts/"+str(fartnumber)+".wav")
                            bark = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/bark-mcgrath.wav")
                            bark2 = bark - 40
                            print('playing bark using pydub')
                            play(bark2)
                            play_menu = True
                            sleep(0.5)

                        #if(number == 8):#phone exploding joke
                           # juke = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/juke.wav")
                           # juke2 = juke - 10
                           # print('playing juke')
                           # play(juke2)
                           # play_menu = True

                        if(number == 9):#community song
                            #community = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/community.wav")
                            #community2 = community - 10
                            #print('playing community')
                            #play(community2)
                            community = "/home/pi/Music/Rotary_Recordings/community.wav"
                            print('playing community using pydub')
                            call(["amixer", "-D", "pulse", "sset", "Master", "60%-"])
                            
                            wf = wave.open(community, 'rb') #your audio here
                            p = pyaudio.PyAudio() #instantiate PyAudio
                            def callback(in_data, frame_count, time_info, status): #define callback
                                data = wf.readframes(frame_count)
                                return (data, pyaudio.paContinue)
                            stream = p.open(format=p.get_format_from_width(wf.getsampwidth()), #open stream using callback
                                channels=wf.getnchannels(),
                                rate=wf.getframerate(),
                                output=True,
                                stream_callback=callback)
                            stream.start_stream() #start the stream
                            while stream.is_active() and paused==True: #wait for stream to finish
                                #with on_turn as listener:
                                    #listener.join()
                                time.sleep(0.1)
                            stream.stop_stream() #stop the stream
                            stream.close()
                            wf.close()
                            p.terminate() #close pyaudio
                            call(["amixer", "-D", "pulse", "sset", "Master", "60%+"])
                            paused = True
                            
                            play_menu = True
                            sleep(0.5)
                            
                        if(number == 3):#bird noises
                            bird = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/bird-mcgrath.wav")
                            bird2 = bird - 25
                            print('playing chirps')
                            play(bird2)
                            play_menu = True
                            sleep(0.5)

                        #if(number == 5):#play a polish greeting
                            #polish = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/polish_greeting.wav")
                            #print('playing polish greeting')
                            #play(polish)
                            #play_menu = True
                            
                        if(number == 10):#play menu again
                            print("returning to menu")
                            play_menu = True                        
                            
                        if(number == 6):#generate code to play foot fetish porn noises
                            play_menu = True
                            sexy_noise = True
                            still_picked_up = False
                            sleep(1)
                            
                        if(number == 0):#play menu again
                            print("returning to menu")
                            play_menu = True  

                    last = GPIO.input(27)
                    
        except KeyboardInterrupt:
            break


    if has_recorded:#play the recording options save and return to menu, delete and return to menu, or hang up
        
        if has_recorded_options:
            message_options = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/record_options-mcgrath.wav")
            message_options2 = message_options - 20
            print('playing record options')
            play(message_options2)
            has_recorded_options = False
            print("message options played")

        try:        
            if GPIO.event_detected(27):
                current = GPIO.input(27)
                if(last != current):
                    if(current == 0):
                        GPIO.add_event_detect(17, GPIO.BOTH, callback=count, bouncetime=10)
                    else:
                        GPIO.remove_event_detect(17)
                        number = int((c)/2)
                        print ("You dial", number)
                        c= 0
                        
                        if(number == 5):#code to save the message - hint: it's already saved
                            message_saved = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/saved.wav")
                            play(message_saved)
                            print("message saved")
                            has_recorded = False
                            still_picked_up = True                            
                            play_menu = True
                            sleep(1)
                        
                        if(number == 6):#code to delete the recently recorded message
                            newfile = open('count.txt','r')
                            g = int(newfile.read())
                            newfile.close()
                            print(g)
                            os.remove("/home/pi/Music/Guest Recordings/"+str(g)+".wav")

                            message_deleted = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/deleted.wav")
                            play(message_deleted)
                            print("message deleted")
                            has_recorded = False
                            still_picked_up = True
                            play_menu = True
                            sleep(1)
                            
                        if(number == 10):#return to menu 
                            print("returning to menu")
                            has_recorded = False
                            still_picked_up = True
                            play_menu = True 

                    last = GPIO.input(27)

        except KeyboardInterrupt:
            break

    if sexy_noise:#play the sexy noises, return to main menu
        try:        
            if GPIO.event_detected(27):
                current = GPIO.input(27)
                if(last != current):
                    if(current == 0):
                        GPIO.add_event_detect(17, GPIO.BOTH, callback=count, bouncetime=10)
                    else:
                        GPIO.remove_event_detect(17)
                        number = int((c)/2)
                        print ("You dial", number)
                        c= 0
                        
                        if(number == 9):#code to play sexy noise
                            female = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/female.wav")
                            play(female)
                            print("super hot")
                            sexy_noise = False
                            has_recorded = False
                            still_picked_up = True
                            sleep(1)
                        
                        if(number == 6):#code to proceed to phone shutdown
                            beast_number = True
                            sexy_noise = False
                            has_recorded = False
                            sleep(1)
                            
                        if(number == 10):#return to menu 
                            print("returning to menu")
                            sexy_noise = False
                            has_recorded = False
                            still_picked_up = True 

                    last = GPIO.input(27)

        except KeyboardInterrupt:
            break

    if beast_number:#shut down the pi, or return to main menu
        try:        
            if GPIO.event_detected(27):
                current = GPIO.input(27)
                if(last != current):
                    if(current == 0):
                        GPIO.add_event_detect(17, GPIO.BOTH, callback=count, bouncetime=10)
                    else:
                        GPIO.remove_event_detect(17)
                        number = int((c)/2)
                        print ("You dial", number)
                        c= 0
                        
                        if(number == 6):#shutdown the pi
                            shutdown = AudioSegment.from_wav("/home/pi/Music/Rotary_Recordings/shutdown.wav")
                            play(shutdown)
                            print("shutting down")
                            call("sudo poweroff", shell=True)
                            
                        if(number == 10):#return to menu 
                            print("returning to menu")
                            beast_number = False
                            has_recorded = False
                            still_picked_up = True

                    last = GPIO.input(27)

        except KeyboardInterrupt:
            break

我的编码经验极其有限,一直非常依赖 Chat GPT。

您遇到的错误表明变量

stream
没有在
on_turn
函数的范围内定义。似乎
stream
已在代码的
still_picked_up
部分中定义和使用,但在
on_turn
函数中无法访问它。

要解决此问题,您需要使

stream
变量可供
on_turn
函数访问。实现此目的的一种方法是在注册事件检测回调时将
stream
变量作为参数传递给
on_turn
函数。

这里是相关代码片段的更新版本:

import RPi.GPIO as GPIO
# ... (other imports)

# Define global variable 'stream'
stream = None

# ... (other code)

def on_turn(pin):
    global paused
    global stream

    if stream is not None and stream.is_active():
        print('Audio skipped')
        paused = False

# ... (other code)

GPIO.add_event_detect(27, GPIO.BOTH, callback=on_turn, bouncetime=200)

# ... (rest of the code)

在这段修改后的代码中,我们在

stream
函数之前将
on_turn
变量定义为全局变量。然后,我们修改
on_turn
函数以使用
stream
关键字访问
global
变量。

另外,请注意,我在调用

bouncetime
时添加了值为200的
GPIO.add_event_detect
参数。这有助于消除事件检测的抖动,以防止由于信号波动而导致的错误触发。

通过进行这些更改,

on_turn
函数现在应该能够访问
stream
变量,而无需抛出您遇到的
NameError

python-3.x raspberry-pi gpio pyaudio portaudio
© www.soinside.com 2019 - 2024. All rights reserved.