Convert briefing audio to MP3 before upload #2
Loading…
Reference in a new issue
No description provided.
Delete branch "mp3-audio-upload"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
pocket-ttsproduces to MP3 withffmpeg + libmp3lamebefore uploading to ntfy, mirroring theforgejo-daily-reportpipelineContent-Type: audio/mpegon the audio upload (it was previously sent as an unlabelled binary)FFMPEG_BINandMP3_BITRATEenv-var overrides (defaultsffmpegand96k)ffmpegto the Nix runtime and dev shellContext
The TTS step already produced a WAV, but WAV attachments to ntfy are large and the upload was going out with no
Content-Type. Theforgejo-daily-reportrepo solved this with affmpegstep, so this PR ports that pattern over.The conversion is wrapped in a
convert_to_mp3()helper with a 120 s timeout. If ffmpeg is missing, the script falls back to uploading the WAV rather than failing the run, so the text notification still goes out.Notes
python3 -m py_compile daily-briefing.py, which still passes.Automated code review
Reviewed commit:
a472dc2c4d3155c358cff9c07b15d9930f4ad0edVerdict: Ready to merge
No blocking or important findings were retained, and deterministic checks passed. Suggestions remain advisory.
Overall assessment
The pull request implements WAV-to-MP3 conversion via ffmpeg with a graceful fallback to WAV, adds explicit Content-Type headers for ntfy raw uploads, and applies defensive stderr decoding (errors='replace') across subprocess calls. Module-level environment variable capture for FFMPEG_BIN and MP3_BITRATE has been corrected to read at call time, preventing race conditions with load_env(). Silent OSError suppression during temp file cleanup is now logged. The diff aligns with the provided human context and addresses previously flagged concerns.
Blocking findings
None.
Important findings
None.
Suggestions
None.
Tests and validation
Questions
Review limitations
Diff coverage
README.md: reviewed — included in a context-limited batchdaily-briefing.py: reviewed — included in a context-limited batchflake.nix: reviewed — included in a context-limited batchReview metadata
One of the suggestions from the previous automated review was a false positive, worth flagging for the next pass:
This pattern (raw body with explicit
Content-Type) is correct and is whatforgejo-daily-reportuses in production against the same ntfy instance — seeforgejo-daily-report/forgejo-daily-report.pyaround line 1192-1198, which postsaudio/mpegaudio withdata=audio. The previous code onmainwas already doing this for the WAV (it just omitted the Content-Type header), and the dedicated audio branch inntfy()predates this PR. The PR only adds the missing Content-Type and the fallback; it does not change the upload mechanism.The other suggestion (silent
OSErrorsuppression in cleanup) was valid and has been addressed in commitb1e00fa: thepath.exists()guard still handles the race against the file being already gone, and any remainingOSErroris now logged with the path and the exception.Following the previous review's high-confidence finding on
subprocesstext=Truedecoding (convert_to_mp3), I applied the sameerrors='replace'fix to the siblinggenerate_tts()function in commit024a3a3.Same root cause, same fix, same reasoning:
text=Trueuses the default UTF-8 codec witherrors='strict'pocket-tts's stderr would raiseUnicodeDecodeErrorexcept Exceptioningenerate_ttswould log it as a misleading "TTS generation failed to start" — even if the WAV was actually writtenFolding it in rather than opening a separate issue: the change is a one-line mirror of the existing fix, the same defensive pattern, and would otherwise just get flagged again on the next pass. Two call sites of the same decode idiom, same fix applied to both.
High-confidence finding on lines 28–29:
FFMPEG_BINandMP3_BITRATEare read at module scope, beforeload_env()runs inmain(). Any value set inbriefing.envis silently ignored — the user gets the shell environment or the hardcoded default, not what they put in the env file.This is a real bug, not a false positive. The rest of the file (e.g.
generate_ttsreadingPOCKET_TTS_FALLBACK_VOICE,POCKET_TTS_TIMEOUT_SECS) reads env vars inside the function body, which is the correct pattern. The new constants broke that pattern.Fix landing in a follow-up commit: drop the module-level capture, read inside
convert_to_mp3()at call time, matching the existing style.MP3_CONVERT_TIMEOUT_SECShas no env-var read so it stays as a constant.flake.nixdoesn't need to change — ffmpeg is still a runtime input. README's documented env-var overrides are correct in spirit; the bug was in how the values were captured, not in the documentation.