Skip to content

fix: make native audio messages playable inline - #278

Open
coletebou wants to merge 1 commit into
openclaw:mainfrom
coletebou:fix/native-audio-caf-opus
Open

fix: make native audio messages playable inline#278
coletebou wants to merge 1 commit into
openclaw:mainfrom
coletebou:fix/native-audio-caf-opus

Conversation

@coletebou

@coletebou coletebou commented Sep 7, 2026

Copy link
Copy Markdown

Sending a valid MP3 with send-attachment --audio can produce a 00:00 voice bubble that will not play inline, even though opening the attachment externally plays the audio. The bridge sets isAudioMessage, but currently stages and sends the original bytes unchanged.

This prepares native voice attachments as CAF containing Opus before bridge dispatch, for both CLI and RPC. Ordinary file attachments keep their existing behavior.

What changes

  • One shared AudioMessagePreparer in IMsgCore, selected by CLI --audio and RPC audio / is_audio / as_voice.
  • Convert a securely staged snapshot with macOS's built-in afconvert: mono, 24 kHz, 32 kbit/s Opus in CAF. No runtime dependency on ffmpeg or a TTS provider.
  • Verify the output codec, sample rate, channels and positive duration with AudioToolbox. Invalid input, conversion failure or invalid output stops the send before bridge dispatch; the existing bounded process wait and no-AppleScript-fallback policy are preserved.
  • Keep the caller's original unchanged, remove failed staging/intermediate files, and retain the final private CAF for Messages' asynchronous transfer.

The container and codec both matter; renaming an MP3 to .caf is insufficient. Preparation belongs before the bridge call, so every CLI/RPC caller benefits without spawning a converter inside Messages.app. Reply metadata and ordinary attachment sends are unchanged.

Reproduce / verify

On a Mac with a working injected bridge, use an existing iMessage chat and a valid MP3 containing a few seconds of audio:

imsg send-attachment --chat "$CHAT" --file /path/to/speech.mp3 --audio --transport dylib

Before: the native bubble can show 00:00 and refuse inline playback; opening the file externally works.

After: imsg sends the prepared CAF/Opus file. Verify a real duration and audible playback using the play button inside Messages. Omitting --audio still sends the original MP3 as a regular attachment.

End-to-end verification used this PR's release build directly on macOS 26.6.2,
bypassing the existing transport wrapper. A fresh synthetic 4.95-second MP3
arrived as a native four-second voice bubble; clicking the normal play button
started inline playback and advanced its remaining-time state. The database
recorded is_audio_message=1, a CAF UTI and a nonempty 28,235-byte attachment.
The earlier transport-side reproduction also produced a fresh 16-second TTS
reply whose recipient confirmed audible inline playback.

Validation

  • make lint: passed; 15 existing size warnings, no serious violations.
  • make test: 754 Swift tests passed, plus documentation and native helper tests. On this Mac with a live bridge, the three test-only injections from fix: make RPC send tests independent of host bridge availability #277 were temporarily applied for the full run and then removed; they are not included in this PR. The Command Line Tools-only installation also needed explicit Testing framework search/runtime paths.
  • make build ARCHES=arm64: passed, including the native helper build.
  • Synthetic MP3 tests inspect actual CAF/Opus metadata and duration, preserve original bytes, cover CAF inputs and misleading extensions, reject empty/invalid audio and unsafe source paths, and check failed-output cleanup. The text-encoded fixture contains no speech or private data; tests need neither ffmpeg nor Messages access. Fixture decoding was rechecked after making the asset text-reviewable: all five core audio tests passed.
  • CLI/RPC tests cover all audio aliases, both RPC initializers, reply metadata, ordinary attachments, conversion failure before dispatch, and the existing audio no-fallback policy.
  • Extensive multi-model review completed with no blockers reported.

Linux read-core compatibility is preserved with macOS guards; Linux CI remains the validation for that platform.

@coletebou
coletebou requested a review from a team as a code owner September 7, 2026 07:28
@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-07T07:31:48.743286Z 210785b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coletebou coletebou changed the title fix: prepare native audio messages as CAF/Opus fix: make native audio messages playable inline Sep 7, 2026
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Sep 7, 2026
@clawsweeper

clawsweeper Bot commented Sep 7, 2026

Copy link
Copy Markdown

Codex review: needs real behavior proof before merge. Reviewed September 7, 2026, 3:36 AM ET / 07:36 UTC.

ClawSweeper review

What this changes

The PR converts CLI and RPC native voice attachments to validated CAF/Opus audio before sending, with regression tests and documentation.

Merge readiness

Blocked before merge - 2 items remain

This remains a useful, focused fix absent from the supplied main revision and v0.15.1. No blocking code defect was found, but the reported successful playback needs inspectable supporting evidence before merge.

Priority: P2
Reviewed head: 210785ba7e94eee8d0b94a06fef3226d48aa4f42

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The focused implementation and regression coverage are solid; inspectable evidence of the reported native playback result remains the merge gate.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: The body specifically reports successful Messages inline playback through this branch's CLI and shared preparer on macOS 26.6.2, but supplies only a narrative account rather than inspectable playback evidence or captured runtime output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🐚 platinum hermit (4/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: The body specifically reports successful Messages inline playback through this branch's CLI and shared preparer on macOS 26.6.2, but supplies only a narrative account rather than inspectable playback evidence or captured runtime output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 8 items Repository policy and identity: The origin identifies openclaw/imsg. The complete root AGENTS.md was read; no nested AGENTS.md or maintainer-notes directory was found. Fixture-based regression coverage and CLI verification guidance informed this review.
Main still sends original audio bytes: At the supplied main SHA, CLI and RPC attachment handlers stage the original file and set isAudioMessage without conversion. Local tags identify that same SHA as v0.15.1; this release therefore does not contain the proposed preparation.
Release identity: The local v0.15.1 tag points at the supplied main revision, matching the captured release context.
Findings None None.
Security None None.

How this fits together

imsg accepts attachment paths through its CLI and JSON-RPC server, then stages files for the bridge inside Messages.app. Native voice preparation changes the audio representation that Messages receives for inline playback.

flowchart TD
  A[CLI or RPC attachment request] --> B{Native voice requested?}
  B -->|Yes| C[Secure snapshot and CAF Opus conversion]
  C --> D[Validate audio format and duration]
  D --> E[Messages bridge]
  B -->|No| F[Ordinary attachment staging]
  F --> E
  E --> G[Messages attachment or voice bubble]
Loading

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: The body specifically reports successful Messages inline playback through this branch's CLI and shared preparer on macOS 26.6.2, but supplies only a narrative account rather than inspectable playback evidence or captured runtime output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Complete next step (P2) - Add inspectable evidence of the reported after-fix inline playback; a short recording is preferred, and captured runtime output or logs also count when they show the result. Redact phone numbers, chat details, endpoints, and other private information. Updating the PR body should trigger re-review; otherwise ask a maintainer to comment @clawsweeper re-review.
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production and regression coverage Production +106/-3 lines; test code +359/-3; fixtures and fixture documentation +53 Production growth implements the shared audio conversion boundary, with substantial focused regression coverage.

Technical review

Best possible solution:

Keep one shared native-voice preparer before bridge dispatch, preserving original files, ordinary attachments, reply metadata, and existing delivery safeguards.

Do we have a high-confidence way to reproduce the issue?

Unclear independently: source confirms that current main passes MP3 bytes unchanged with the native-audio flag, and the contributor supplies a concrete Mac reproduction, but inline playback was not exercised in this read-only review.

Is this the best way to solve the issue?

Yes at the code level: shared preparation before bridge dispatch addresses both entrypoints without adding a runtime dependency or duplicating the unrelated receive-side attachment conversion.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 646ea7af9616.

Labels

Label changes:

  • add P2: This repairs inline playback for explicitly requested native voice attachments without changing ordinary message workflows.
  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The body specifically reports successful Messages inline playback through this branch's CLI and shared preparer on macOS 26.6.2, but supplies only a narrative account rather than inspectable playback evidence or captured runtime output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This repairs inline playback for explicitly requested native voice attachments without changing ordinary message workflows.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The body specifically reports successful Messages inline playback through this branch's CLI and shared preparer on macOS 26.6.2, but supplies only a narrative account rather than inspectable playback evidence or captured runtime output. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

  • Repository policy and identity: The origin identifies openclaw/imsg. The complete root AGENTS.md was read; no nested AGENTS.md or maintainer-notes directory was found. Fixture-based regression coverage and CLI verification guidance informed this review. (AGENTS.md:1, 210785ba7e94)
  • Main still sends original audio bytes: At the supplied main SHA, CLI and RPC attachment handlers stage the original file and set isAudioMessage without conversion. Local tags identify that same SHA as v0.15.1; this release therefore does not contain the proposed preparation. (Sources/imsg/Commands/BridgeAttachmentCommand.swift:66, 646ea7af9616)
  • Release identity: The local v0.15.1 tag points at the supplied main revision, matching the captured release context. (646ea7af9616)
  • Conversion and safety boundary: The preparer reuses secure regular-file staging, invokes the fixed system afconvert executable with argument-array paths and a bounded wait, validates CAF/Opus metadata and positive duration, and removes failed conversion output. It does not change recipient authorization, bridge credentials, dependencies, or workflow permissions. (Sources/IMsgCore/AudioMessagePreparer.swift:19, 210785ba7e94)
  • Regression coverage: Core tests exercise actual conversion and metadata validation, original-byte preservation, unsafe sources, and cleanup. CLI/RPC tests cover ordinary attachments, audio aliases, both server initializers, reply metadata, and failure before dispatch. Tests were inspected but not executed during this read-only review. (Tests/imsgTests/AudioAttachmentRoutingTests.swift:129, 210785ba7e94)
  • Captured playback report: The complete supplied body, under context sourceRevision dfd4d66002029581b6a03b056efa4c347f35c19c443fa5fca3f2da457eea9f82, reports running this PR's release build on macOS 26.6.2: a 4.95-second MP3 became a playable voice bubble, with a CAF attachment of 28,235 bytes. This is specific and relevant, but the captured body and discussion contain no attached playback recording, screenshot, runtime transcript, or underlying database output to inspect. The earlier wrapper-based TTS result is supplementary rather than direct evidence for this branch. (210785ba7e94)

Likely related people:

  • Peter Steinberger: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)
  • Omar Shahine: Suggested for follow-up; no historical authorship or introduction is verified. (role: unverified routing candidate; confidence: low)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Attach a redacted recording of the reported inline playback, or a runtime transcript that ties the branch build and send to the observed playback result.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@steipete

steipete commented Sep 7, 2026

Copy link
Copy Markdown
Collaborator

Maintainer verification of 210785ba7e94eee8d0b94a06fef3226d48aa4f42:

  • Approved the reviewed fork workflow. Full macOS/Linux CI passed: https://github.com/openclaw/imsg/actions/runs/34095651974.
  • Independent branch autoreview against origin/main is clean at P0–P2. make lint passes with 15 existing warnings and no serious violations.
  • All 11 focused audio conversion/routing tests pass, including the aliases, both RPC initializers, original-file preservation, unsafe inputs, cleanup, reply metadata, and no-fallback behavior.
  • A separately compiled, Developer-ID-signed consumer called the built library's public AudioMessagePreparer.prepare(at:) on the synthetic MP3 fixture. AudioToolbox inspected the real result: CAF, Opus, 24,000 Hz, mono, duration 0.548583 seconds, 6,049 bytes; the original MP3 was unchanged. Temporary prepared media was removed afterward.
  • The built, matching-Developer-ID-signed CLI runs and exposes the attachment command successfully.

This proves the shared preparation path. It does not independently prove the recipient's inline Messages player. This Mac has SIP enabled and no live injected bridge, so no message was sent. The remaining landing gate is inspectable inline-playback evidence from an authorized bridge-enabled Mac and test conversation, tied to this head. The implementation is otherwise a LAND candidate; it stays outside the current patch-release notes until that gate is satisfied.

steipete added a commit that referenced this pull request Sep 7, 2026
Prepare the authorized 0.15.2 patch release with safer bridge startup and reliable local tests. Preserve the Highlights line and contributor credits, date the release notes for 2026-09-07, and synchronize version.env, the generated Swift constant, and bundle versions.

The combined fixes passed 753 Swift tests and signed CLI verification. Version metadata validation and independent autoreviews pass. Native audio playback work in #278 remains excluded.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants