feat(voicemail): add silence file generation for missing recordings and improve logging for voicemail saving
Some checks failed
CI / lint (push) Failing after 5m1s
CI / test-backend (push) Successful in 4s
Benchmarks / benchmark (push) Successful in 12m31s
CI / build-frontend (push) Successful in 9m43s
Build Test / Build and Test (push) Successful in 14m45s
CI / test-backend (pull_request) Successful in 5s
CI / lint (pull_request) Failing after 5m3s
Build and Publish Docker Image / build (pull_request) Has been skipped
CI / test-lang (push) Successful in 9m37s
OSV-Scanner PR Scan / scan-pr (pull_request) Successful in 11s
Benchmarks / benchmark (pull_request) Successful in 12m20s
Build Test / Build and Test (pull_request) Successful in 13m32s
CI / build-frontend (pull_request) Successful in 9m43s
CI / test-lang (pull_request) Successful in 9m34s
Tests / test (pull_request) Failing after 7m23s
Build and Publish Docker Image / build-dev (pull_request) Successful in 12m54s
Tests / test (push) Failing after 20m7s

This commit is contained in:
2026-01-04 16:02:32 -06:00
parent c4674992e0
commit ad928d1279

View File

@@ -454,20 +454,30 @@ class VoicemailManager:
filepath = os.path.join(self.recordings_dir, self.recording_filename)
self._fix_recording(filepath)
# If recording is missing or empty (no frames), synthesize a small silence file
if (not os.path.exists(filepath)) or os.path.getsize(filepath) == 0:
self._write_silence_file(filepath, max(duration, 1))
remote_name = self.get_name_for_identity_hash(
self.recording_remote_identity.hash.hex(),
)
self.db.voicemails.add_voicemail(
remote_identity_hash=self.recording_remote_identity.hash.hex(),
remote_identity_name=remote_name,
filename=self.recording_filename,
duration_seconds=duration,
timestamp=self.recording_start_time,
)
RNS.log(
f"Saved voicemail from {RNS.prettyhexrep(self.recording_remote_identity.hash)} ({duration}s)",
RNS.LOG_DEBUG,
)
if os.path.exists(filepath) and os.path.getsize(filepath) > 0:
self.db.voicemails.add_voicemail(
remote_identity_hash=self.recording_remote_identity.hash.hex(),
remote_identity_name=remote_name,
filename=self.recording_filename,
duration_seconds=duration,
timestamp=self.recording_start_time,
)
RNS.log(
f"Saved voicemail from {RNS.prettyhexrep(self.recording_remote_identity.hash)} ({duration}s)",
RNS.LOG_DEBUG,
)
else:
RNS.log(
f"Voicemail: Recording missing for {self.recording_filename}, skipping DB insert",
RNS.LOG_ERROR,
)
if self.on_new_voicemail_callback:
self.on_new_voicemail_callback(
@@ -535,6 +545,38 @@ class VoicemailManager:
if os.path.exists(temp_path):
os.remove(temp_path)
def _write_silence_file(self, filepath, seconds=1):
"""Creates a minimal OGG/Opus file with silence if recording is missing."""
if not self.has_ffmpeg:
return False
try:
cmd = [
self.ffmpeg_path,
"-y",
"-f",
"lavfi",
"-i",
f"anullsrc=r=48000:cl=mono",
"-t",
str(max(1, seconds)),
"-c:a",
"libopus",
"-b:a",
"16k",
filepath,
]
result = subprocess.run(cmd, capture_output=True, text=True, check=False) # noqa: S603
if result.returncode == 0 and os.path.exists(filepath):
return True
RNS.log(
f"Voicemail: Failed to create silence file for {filepath}: {result.stderr}",
RNS.LOG_ERROR,
)
except Exception as e:
RNS.log(f"Voicemail: Error creating silence file for {filepath}: {e}", RNS.LOG_ERROR)
return False
def start_greeting_recording(self):
telephone = self.telephone_manager.telephone
if not telephone: