Add immediate stop on hook and abort incomplete recordings
**Immediate Hook Detection:** - Playback now checks GPIO pin directly instead of status variable - Recording checks GPIO pin in every loop iteration - Both stop immediately when handset is placed back on hook - No delays or waiting for status updates **Abort Incomplete Recordings:** - Added minimum recording duration (1 second) - Recordings shorter than 1 second are automatically deleted - Aborted recordings (hook hung up during recording) are not saved - Failed recordings are cleaned up automatically - Prevents saving empty or accidental recordings **Behavior:** - Pick up handset → Greeting plays - Hang up during greeting → Greeting stops immediately, no recording - Hang up during recording < 1s → Recording aborted, file deleted - Hang up during recording > 1s → Recording saved normally - Clean state after each hang up, ready for next call 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -228,8 +228,9 @@ class RotaryPhone:
|
||||
# Play the sound with volume control
|
||||
data = wf.readframes(CHUNK)
|
||||
while data:
|
||||
# For greeting sounds, stop if handset is hung up
|
||||
if check_hook_status and self.phone_status != "off_hook":
|
||||
# For greeting sounds, stop immediately if handset is hung up
|
||||
if check_hook_status and GPIO.input(HOOK_PIN) != HOOK_PRESSED:
|
||||
print("Handset hung up, stopping playback immediately")
|
||||
break
|
||||
|
||||
# Apply volume by converting to numpy array and scaling
|
||||
@@ -256,9 +257,11 @@ class RotaryPhone:
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
filename = os.path.join(OUTPUT_DIR, f"recording_{timestamp}.wav")
|
||||
self.current_recording = filename
|
||||
|
||||
|
||||
print(f"Recording to {filename}")
|
||||
|
||||
|
||||
MIN_RECORDING_DURATION = 1.0 # Minimum 1 second to save recording
|
||||
|
||||
try:
|
||||
# Use configured audio device
|
||||
stream = self.audio.open(
|
||||
@@ -269,44 +272,56 @@ class RotaryPhone:
|
||||
input_device_index=AUDIO_DEVICE_INDEX,
|
||||
frames_per_buffer=CHUNK
|
||||
)
|
||||
|
||||
|
||||
frames = []
|
||||
self.recording = True
|
||||
|
||||
|
||||
# Record until handset is hung up or max time reached
|
||||
start_time = time.time()
|
||||
while self.recording and (time.time() - start_time) < RECORD_SECONDS:
|
||||
# Check if handset is still off hook
|
||||
# Check if handset is still off hook - immediate detection
|
||||
if GPIO.input(HOOK_PIN) != HOOK_PRESSED:
|
||||
print("Handset hung up, stopping recording")
|
||||
print("Handset hung up, stopping recording immediately")
|
||||
break
|
||||
|
||||
|
||||
try:
|
||||
data = stream.read(CHUNK, exception_on_overflow=False)
|
||||
frames.append(data)
|
||||
except Exception as e:
|
||||
print(f"Error reading audio: {e}")
|
||||
break
|
||||
|
||||
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
|
||||
# Save the recording
|
||||
if frames:
|
||||
|
||||
# Calculate recording duration
|
||||
duration = len(frames) * CHUNK / RATE if frames else 0
|
||||
|
||||
# Only save if recording is long enough
|
||||
if frames and duration >= MIN_RECORDING_DURATION:
|
||||
wf = wave.open(filename, 'wb')
|
||||
wf.setnchannels(CHANNELS)
|
||||
wf.setsampwidth(self.audio.get_sample_size(FORMAT))
|
||||
wf.setframerate(RATE)
|
||||
wf.writeframes(b''.join(frames))
|
||||
wf.close()
|
||||
duration = len(frames) * CHUNK / RATE
|
||||
print(f"Recording saved: {filename} ({duration:.1f}s)")
|
||||
else:
|
||||
print("No audio recorded")
|
||||
|
||||
# Delete aborted/too short recording
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
print(f"Recording aborted or too short ({duration:.1f}s), not saved")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Recording error: {e}")
|
||||
|
||||
# Clean up failed recording file
|
||||
if os.path.exists(filename):
|
||||
try:
|
||||
os.remove(filename)
|
||||
print(f"Cleaned up failed recording: {filename}")
|
||||
except:
|
||||
pass
|
||||
|
||||
self.recording = False
|
||||
self.current_recording = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user