Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

14 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ohr-speaker πŸ”Š

On-device speech-to-text with speaker diarization, powered by Apple Intelligence & CAM++

δΈ­ζ–‡η‰ˆ | English

ohr-speaker is an enhanced fork of ohr that integrates three speaker diarization engines β€” including CAM++ (ι˜Ώι‡ŒθΎΎζ‘©ι™’) and FluidAudio β€” on top of the original Apple SpeechAnalyzer transcription engine.

100% on-device. No cloud. No API keys. Your data never leaves your machine.


Features

  • 🎀 Apple Intelligence Transcription β€” Powered by macOS SpeechAnalyzer, millisecond latency
  • πŸ—£οΈ Three Diarization Engines β€” CAM++, Offline VBx (WeSpeaker), or Sortformer (--engine flag)
  • πŸ‡¨πŸ‡³ Chinese-Optimized β€” CAM++ model trained on 200k Chinese speakers, ~15MB model
  • πŸ“ Multiple Output Formats β€” Plain text, JSON, SRT subtitles, VTT subtitles with speaker labels
  • πŸŽ™οΈ Live Microphone Transcription β€” Real-time --listen mode
  • πŸ–₯️ OpenAI-Compatible Server β€” --serve mode, compatible with OpenAI Whisper API
  • πŸ“¦ Multi-format Support β€” m4a, wav, mp3, mp4, caf, aiff, flac
  • πŸ”’ Privacy First β€” All processing is local, no data uploaded

Quick Start

Download a pre-built binary from Releases:

Binary Default Engine Model Size
ohr-cam CAM++ (default) ~15 MB
ohr-speaker Offline VBx (WeSpeaker) ~700 MB
# CAM++ engine (~15 MB model, auto-downloaded on first use)
ohr-cam --speakers meeting.wav

# Or offline VBx engine (legacy, ~700 MB model)
ohr-speaker --speakers meeting.wav

Build from Source

git clone https://github.com/yanhuicsdn/ohr-speaker.git
cd ohr-speaker

# Using Xcode-beta toolchain (macOS 27+)
DEVELOPER_DIR="/Applications/Xcode-beta.app/Contents/Developer" swift build -c release

# Using Xcode stable (macOS 26+)
swift build -c release

# Copy the binary to your PATH
cp .build/release/ohr /usr/local/bin/ohr-speaker

Prerequisites

  • macOS 26+ (Apple Silicon)
  • Xcode 26.6+ or Xcode-beta 27+

Usage

Basic Transcription

ohr-speaker audio.wav

With Speaker Diarization (CAM++ default)

ohr-speaker --speakers audio.wav

Sample output:

【S1】
There is usually a platform management layer with a user center...

【S2】
Give them the full version so they can use it...

【S1】
Yes, provincial business layers have isolation requirements for permissions...

Select a Different Diarization Engine

# CAM++ (default) β€” ι˜Ώι‡ŒθΎΎζ‘©ι™’, 200k Chinese speakers, ~15MB model
ohr-speaker --speakers --engine campplus audio.wav

# Offline VBx (WeSpeaker) β€” ~700MB model, PLDA scoring
ohr-speaker --speakers --engine offlineVbx audio.wav

# Sortformer β€” ~200MB model, ≀4 speakers, CoreML ANE accelerated
ohr-speaker --speakers --engine sortformer audio.wav

Output as SRT Subtitles

ohr-speaker --speakers -o srt audio.wav > subtitles.srt

Output as JSON

ohr-speaker --speakers -o json audio.wav

Live Microphone Transcription

ohr-speaker --listen --speakers

Start OpenAI-Compatible Server

ohr-speaker --serve --port 11434

Then call from any OpenAI Whisper client:

curl http://localhost:11434/v1/audio/transcriptions \
  -F "file=@audio.wav" \
  -F "model=whisper-1" \
  -F "diarize=true"

Complete Options

USAGE:
  ohr <file>                   Transcribe an audio file
  ohr -o srt <file>            Transcribe to SRT subtitles
  ohr -o vtt <file>            Transcribe to VTT subtitles
  ohr -o json <file>           Transcribe to JSON with segments
  ohr --listen                 Live microphone transcription
  ohr --serve                  Start OpenAI-compatible HTTP server
  cat audio.wav | ohr          Transcribe from stdin

OPTIONS:
  -o, --output <format>        Output: plain (default), json, srt, vtt
  --json                       Shorthand for -o json
  --srt                        Shorthand for -o srt
  --vtt                        Shorthand for -o vtt
  --timestamps                 Show timestamps in plain text output
  --speakers                   Enable speaker diarization
  --engine <name>              Diarization engine: campplus, offlineVbx, sortformer
  -l, --language <code>        Language code (e.g. en-US, de-DE)
  -q, --quiet                  Suppress headers and chrome
  --no-color                   Disable ANSI colors

SERVER OPTIONS:
  --serve                      Start HTTP server
  --port <n>                   Server port (default: 11434, env: OHR_PORT)
  --host <addr>                Bind address (default: 127.0.0.1, env: OHR_HOST)
  --cors                       Enable CORS headers
  --allowed-origins <list>     Comma-separated allowed origins
  --no-origin-check            Disable origin validation
  --token <secret>             Require Bearer token (env: OHR_TOKEN)
  --token-auto                 Generate random token on startup
  --public-health              /health without auth on non-loopback
  --footgun                    Disable all protections (DANGEROUS)
  --max-concurrent <n>         Max concurrent requests (default: 5)
  --debug                      Enable /v1/logs endpoints

INFO:
  -h, --help                   Show this help
  -v, --version                Show version
  --release                    Show detailed build info
  --model-info                 Show model capabilities

Diarization Engine Comparison

Engine Model Parameters Size Speakers M4 Accel. Language Bias
CAM++ ⭐ ι˜Ώι‡ŒθΎΎζ‘©ι™’ CAM++ 7.2M ~15 MB unlimited GPU Chinese βœ…
Offline VBx WeSpeaker + PLDA ~25M ~700 MB unlimited ANE βœ… Multi
Sortformer FluidAudio Sortformer β€” ~200 MB ≀4 ANE βœ… Multi
LS‑EEND ❌ dihard3 EEND β€” ~44 MB unlimited CoreML English only

Benchmark (2-speaker Chinese podcast, 17 min):

Engine Segments S1 S2 First-run download
CAM++ ⭐ 22 11 11 ~5 sec
Offline VBx 26 13 13 ~2 min
Sortformer 26 13 13 ~1 min

CAM++ is the recommended engine for Chinese audio β€” smallest model, fastest download, specifically trained on 200k Chinese speakers by Alibaba DAMO Academy.

Performance

Audio Duration Transcription Only Additional Diarization
1 min ~1s ~1s
10 min ~3s ~2s
31 min ~10s ~5s
1 hour ~20s ~10s

How It Works

  1. Transcription: Uses Apple's SpeechAnalyzer + SpeechTranscriber framework to convert audio into timestamped text segments
  2. Diarization: One of three engines:
    • CAM++: FluidAudio segmentation β†’ independent CAM++ embedding extractor (192-d) β†’ cosine agglomerative clustering
    • Offline VBx: FluidAudio's full pipeline (Seg-3 + WeSpeaker + PLDA + VBx)
    • Sortformer: FluidAudio's end-to-end Sortformer (≀4 speakers, CoreML ANE)
  3. Alignment: Uses a time-overlap-maximization algorithm to align transcription segments with speaker segments

Environment Variables

Variable Description
OHR_PORT Server port (default: 11434)
OHR_HOST Server bind address (default: 127.0.0.1)
OHR_TOKEN Bearer token for server auth
OHR_LANGUAGE Default language code
REGISTRY_URL Model download mirror (e.g. https://hf-mirror.com)
NO_COLOR Disable ANSI colors

Differences from Upstream ohr

Feature ohr ohr-speaker
Speaker Diarization ❌ βœ… --speakers
Transcription Engine Apple SpeechAnalyzer Apple SpeechAnalyzer
Diarization Engine β€” CAM++ (default) / Offline VBx / Sortformer
Model Download 0 MB ~15 MB (CAM++) or ~700 MB (VBx)
Engine Selection β€” --engine flag
Output Formats plain/json/srt/vtt plain/json/srt/vtt + speaker labels
Server Mode βœ… βœ… (supports diarize parameter)

Model Cache Locations

Engine Cache Path Size
CAM++ ~/Library/Application Support/ohr-campplus/ ~15 MB
FluidAudio ~/Library/Application Support/FluidAudio/Models/ ~700 MB

Credits

License

MIT

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages