Skip to content

feat: add microphone input selector with device enumeration#9

Merged
msitarzewski merged 4 commits into
msitarzewski:mainfrom
agentpip:mic-selector
May 25, 2026
Merged

feat: add microphone input selector with device enumeration#9
msitarzewski merged 4 commits into
msitarzewski:mainfrom
agentpip:mic-selector

Conversation

@agentpip
Copy link
Copy Markdown
Contributor

Changes

  • Mic select dropdown in the Input deck panel — lets users pick from available audio input devices
  • Device enumeration on app init (non-blocking) — populates the dropdown with all available microphones
  • In-place track replacement on device change — no permission dialog, uses removeTrack/addTrack pattern to keep stream ID stable
  • RTCManager.getLocalStream(deviceId) — now accepts optional deviceId parameter to target a specific input
  • /api/export/zip endpoint wiring for zip archive export

Why

Gives multi-host podcasters the ability to pick their mic without reloading or restarting. The in-place track swap avoids renegotiation and permission prompts on device change.

agentpip added 4 commits May 14, 2026 16:14
…Raw export UI

- whisper.cpp: built binary, medium model downloaded
- server/lib/whisper-transcriber.js: local transcription service
- server/lib/audio-cleaner.js: 6-step ffmpeg pipeline
- server/lib/filler-detector.js: word-boundary filler detection
- server/lib/audio-converter.js: ffmpeg audio conversion
- server/server.js: POST /api/export/transcribe + /api/export/clean endpoints
- web/index.html: Clean/Raw export panel in recording deck
- web/css/studio.css: Export panel styles
- web/js/main.js: Export UI wiring
- web/js/recording-manager.js: exportTrack() method

API:
- POST /api/export/transcribe - local Whisper.cpp transcription
- POST /api/export/clean - audio cleaning pipeline
The import('fs') returned a Promise that was never awaited, causing
the concat manifest file to be written asynchronously after ffmpeg
tried to read it. This would result in an empty concat file and
ffmpeg failure.

Signed-off-by: Pip <pip@zerologic.com>
The parseMultipart function was trying to .split() a Buffer as if
it were a string, causing 'body.split is not a function' errors on
the transcribe endpoint.

Also fix the boundary detection to properly handle binary audio data
using Buffer.indexOf() instead of string split.

Signed-off-by: Pip <pip@zerologic.com>
- server/lib/show-notes-generator.js: LLM-powered title/summary via LM Studio
- POST /api/export/show-notes: accepts transcript segments, returns {title, summary, segments}
- Post-Production UI panel: transcribe → auto-generate show notes with segment markers + copy/download
- Server extracts outputFormat from multipart form field for MP3/transcode (libmp3lame -qscale:a 2)
- archiver installed for zip bundle download (Task 3 in progress)
@msitarzewski msitarzewski merged commit dc39b00 into msitarzewski:main May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants