我正在通过此链接重新创建项目: 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
。