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
|
# Play the sound with volume control
|
||||||
data = wf.readframes(CHUNK)
|
data = wf.readframes(CHUNK)
|
||||||
while data:
|
while data:
|
||||||
# For greeting sounds, stop if handset is hung up
|
# For greeting sounds, stop immediately if handset is hung up
|
||||||
if check_hook_status and self.phone_status != "off_hook":
|
if check_hook_status and GPIO.input(HOOK_PIN) != HOOK_PRESSED:
|
||||||
|
print("Handset hung up, stopping playback immediately")
|
||||||
break
|
break
|
||||||
|
|
||||||
# Apply volume by converting to numpy array and scaling
|
# Apply volume by converting to numpy array and scaling
|
||||||
@@ -259,6 +260,8 @@ class RotaryPhone:
|
|||||||
|
|
||||||
print(f"Recording to {filename}")
|
print(f"Recording to {filename}")
|
||||||
|
|
||||||
|
MIN_RECORDING_DURATION = 1.0 # Minimum 1 second to save recording
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Use configured audio device
|
# Use configured audio device
|
||||||
stream = self.audio.open(
|
stream = self.audio.open(
|
||||||
@@ -276,9 +279,9 @@ class RotaryPhone:
|
|||||||
# Record until handset is hung up or max time reached
|
# Record until handset is hung up or max time reached
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while self.recording and (time.time() - start_time) < RECORD_SECONDS:
|
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:
|
if GPIO.input(HOOK_PIN) != HOOK_PRESSED:
|
||||||
print("Handset hung up, stopping recording")
|
print("Handset hung up, stopping recording immediately")
|
||||||
break
|
break
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -291,21 +294,33 @@ class RotaryPhone:
|
|||||||
stream.stop_stream()
|
stream.stop_stream()
|
||||||
stream.close()
|
stream.close()
|
||||||
|
|
||||||
# Save the recording
|
# Calculate recording duration
|
||||||
if frames:
|
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 = wave.open(filename, 'wb')
|
||||||
wf.setnchannels(CHANNELS)
|
wf.setnchannels(CHANNELS)
|
||||||
wf.setsampwidth(self.audio.get_sample_size(FORMAT))
|
wf.setsampwidth(self.audio.get_sample_size(FORMAT))
|
||||||
wf.setframerate(RATE)
|
wf.setframerate(RATE)
|
||||||
wf.writeframes(b''.join(frames))
|
wf.writeframes(b''.join(frames))
|
||||||
wf.close()
|
wf.close()
|
||||||
duration = len(frames) * CHUNK / RATE
|
|
||||||
print(f"Recording saved: {filename} ({duration:.1f}s)")
|
print(f"Recording saved: {filename} ({duration:.1f}s)")
|
||||||
else:
|
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:
|
except Exception as e:
|
||||||
print(f"Recording error: {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.recording = False
|
||||||
self.current_recording = None
|
self.current_recording = None
|
||||||
|
|||||||
Reference in New Issue
Block a user