Files
transui/AGENTS.md
2026-08-29 23:11:50 +02:00

2.2 KiB

Transui design

  • Linux is a GTK3 desktop recorder. It supports hosted transcription with an optional local fallback and can type at the cursor or copy to the clipboard.
  • macOS is a SwiftUI menu bar recorder targeting macOS 15. It supports the same hosted-first, local-fallback behavior as Linux, a global recording hotkey, launch at login, cursor typing, and clipboard output. When hosted-first is off, use local only. Its compact floating recorder uses teal level bars for recording feedback.
  • Android is remote-only. It provides an Android RecognitionService, a voice-only input method, and a floating recognition activity. Do not add a local llama.cpp path to Android.
  • All clients upload 16 kHz mono, 32 kbps MP3 to OpenAI-compatible /v1/audio/transcriptions endpoints and clean only the Qwen3-ASR language …<astext> or language …<asr_text> prefix.
  • MP3 encoding uses the third_party/shine submodule pinned to ab5e3526b64af1a2eaa43aa6f441a7312e013519 (3.1.1-59-gab5e352).
  • Generate the macOS Xcode project from macos/project.yml with XcodeGen. Treat the spec as the source of truth and leave macos/Transui.xcodeproj untracked.
  • The Android voice UI is an opaque, compact system surface. Teal is the recording signal. PushToTalkButton draws the Apps and Stop Circle glyphs with Canvas because the target device drops ImageButton image layers. Keep the glyphs drawn above the button background.

llama.cpp local endpoint

The Linux and macOS local fallback uses this multipart request. response_format=json is required; prompt is optional and may request transcription or translation.

curl -s -X POST -F response_format=json http://localhost:8080/v1/audio/transcriptions \
  -F file="@test.mp3" \
  -F 'prompt=Transcribe the following speech segment in English, and translate them into chinese.'

llama.cpp may return an event envelope instead of a bare OpenAI response:

{"type":"transcript.text.done","text":"这是个测试。你能听到什么?我希望这很好。","usage":{"type":"tokens","input_tokens":241,"output_tokens":516,"total_tokens":757,"input_tokens_details":{"cached_tokens":0}}}

Use text as the transcript. Accept transcript.text.done; do not require a bare { "text": "…" } response.