feat: add audio input and audio output widgets (#47)#48
feat: add audio input and audio output widgets (#47)#48claude[bot] wants to merge 8 commits intomainfrom
Conversation
Add `AudioInputWidget` and `AudioOutputWidget` components for the audio in/out resource types. Each widget displays GetProperties (supported codecs, sample rate, channels) with polling support. Register both components in the client map and builtin resource map so they appear in the control view. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 838215d The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Alphabetically "Audio" (Au) sorts after "Arm" (Ar). The PR inserted the audio exports before the Arm block; move them to their correct position between ArmQuickMoveWidget and BaseWidget.
…viamrobotics/test-widgets into claude/add-audio-in-out-widgets
|
@claude review the changes |
|
Claude finished @DTCurrie's task in 3m 36s —— View job Review
Overall the PR is well-structured and follows existing widget conventions. The BugBlob URL memory leak ( $effect(() => {
return () => {
if (captureDownloadUrl) URL.revokeObjectURL(captureDownloadUrl)
}
})Design issuesUnrecognized file extension → silent invalid codec ( No cancellation for
Test gapsMain widget logic is untested ( Positives
|
|
Claude finished @DTCurrie's task in 3m 4s —— View job Review
Prior inline comment retractedMy earlier inline comment on Verified against Viam proto/SDKI fetched the proto definitions and TypeScript SDK source to validate the implementation:
Client map keys — Remaining issuesBug — Blob URL memory leak on component destroy
$effect(() => {
return () => {
if (captureDownloadUrl) URL.revokeObjectURL(captureDownloadUrl)
}
})Design — Unrecognized file extension sends invalid codec to SDKWhen Suggestion: fall through to const detected = mimeToCodec[file.type] ?? mimeToCodec[`audio/${file.name.split('.').pop()?.toLowerCase()}`] ?? ''
playCodec = detectedDesign — No abort path for
|
|
Claude finished @DTCurrie's task in 1m 20s —— View job Review update
Corrections acknowledged@DTCurrie is right on both counts — I apologize for the incorrect observations:
Both widgets implement the full primary interface for their respective clients. The "only surfaces getProperties" observation should be disregarded entirely. Remaining issues (still valid)The five issues from the earlier review that don't touch those two incorrect observations are still accurate: Bug — Blob URL memory leak ( $effect(() => {
return () => { if (captureDownloadUrl) URL.revokeObjectURL(captureDownloadUrl) }
})Design — Unrecognized extension silently passes invalid codec ( Design — No abort for Design — Design — Test coverage — capture/play state machines (abort vs. error paths, blob URL creation, byte counter) remain untested. Glad to see it working in the playground. The core implementation is solid — the remaining items are improvements rather than blockers. |
|
Claude finished @DTCurrie's task in 1m 16s —— View job Clarifying the blob URL cleanup fix
The previous suggestion block at line 114 was malformed — it echoed the existing The fix: add a new $effect(() => {
return () => {
if (captureDownloadUrl) URL.revokeObjectURL(captureDownloadUrl)
}
})Because the |
|
@claude everything should be resolved except: "Design — No abort for play (audio-output.svelte:81–111)" We cannot stop the unary RPC, even with an abort controller. Once the server begins playing the audio, it continues to play it. |
|
Claude finished @DTCurrie's task in 1m 4s —— View job Review update
All remaining issues resolved@DTCurrie confirmed — the "no abort for Everything else from the prior review has been addressed:
The Implementation looks solid. LGTM. |
…nto claude/add-audio-in-out-widgets


Adds
AudioInputWidgetandAudioOutputWidgetcomponents for the new audio in/out resource types, enabling users to view audio device properties directly from the control interface.Closes #47
Frontend
audio-input/audio-input.svelte— main widget for the audio input component. UsesAudioInClientto querygetPropertieswith polling support viaRefetchController.audio-input/properties.svelte— displays supported codecs, sample rate, and channel count.audio-output/audio-output.svelte— main widget for the audio output component. UsesAudioOutClientto querygetPropertieswith polling support.audio-output/properties.svelte— displays supported codecs, sample rate, and channel count.client-map.ts— registersAudioInClientandAudioOutClientunderrdk:component:audio_inputandrdk:component:audio_output.builtin.ts— maps both audio resource APIs to their widgets so they appear in the control view.components/index.ts— exportsAudioInputWidgetandAudioOutputWidget.Testing
audio-input/properties.svelteandaudio-output/properties.sveltecovering codec display, empty codec list, sample rate, and channel count rendering.pnpm lintandpnpm check(both pass clean).pnpm testfails due to a pre-existing Playwright browser installation issue in the environment, unrelated to this change.DRI
@DTCurrie