Python interface to macOS AI capabilities
Project description
macbook-ai
Python interface to macOS AI capabilities — speech recognition, text-to-speech, and LLM via Apple Foundation Models.
All processing is on-device. No API keys, no network calls.
Requirements
- macOS 10.15 or later
- Python 3.10 or later
- The first time you use Speech-to-Text, macOS will prompt for access. You may need to enable it manually: System Settings > Privacy & Security > Speech Recognition > Terminal
Installation
pip install macbook-ai
With uv:
uv add macbook-ai
Note: Foundation Models require macOS 15.6+ and pyobjc-framework-FoundationModels (install separately when available on PyPI).
Features
Speech-to-Text (STT)
Powered by the macOS SFSpeechRecognizer framework.
Grant Permission
The first time you use recognition, macOS will prompt for access. You can trigger it explicitly:
from macbook_ai.stt import SpeechRecognizer
status = SpeechRecognizer.request_authorization()
# Returns: 'authorized' | 'denied' | 'restricted' | 'not_determined'
If running from Terminal, you may need to enable it manually: System Settings > Privacy & Security > Speech Recognition > Terminal
Transcribe Audio Files
from macbook_ai.stt import SpeechRecognizer
recognizer = SpeechRecognizer() # defaults to en-US
text = recognizer.recognize_file("recording.m4a")
print(text)
Async Support
import asyncio
from macbook_ai.stt import SpeechRecognizer
async def main():
recognizer = SpeechRecognizer()
text = await recognizer.recognize_file_async("recording.m4a")
print(text)
asyncio.run(main())
Multiple Languages
recognizer = SpeechRecognizer(locale="fr-FR")
recognizer = SpeechRecognizer(locale="es-ES")
recognizer = SpeechRecognizer(locale="ja-JP")
Supported Audio Formats
Any format supported by AVFoundation: WAV, M4A, MP3, AIFF, CAF, FLAC, and more.
Error Handling
from macbook_ai.stt import SpeechRecognizer
from macbook_ai._exceptions import AuthorizationError, RecognitionError
recognizer = SpeechRecognizer()
try:
text = recognizer.recognize_file("recording.m4a")
except AuthorizationError:
print("Grant Speech Recognition access in System Settings first.")
except RecognitionError as e:
print(f"Recognition failed: {e}")
except TimeoutError:
print("Recognition timed out — try a shorter clip or increase timeout.")
Text-to-Speech (TTS)
Powered by the macOS AVSpeechSynthesizer framework.
Basic Usage
from macbook_ai.tts import SpeechSynthesizer
synth = SpeechSynthesizer()
synth.speak("Hello from macbook-ai")
Async Support
import asyncio
from macbook_ai.tts import SpeechSynthesizer
async def main():
synth = SpeechSynthesizer()
await synth.speak_async("Hello from macbook-ai")
asyncio.run(main())
Custom Voices and Settings
# List available voices
voices = SpeechSynthesizer.available_voices(language="en")
for voice in voices:
print(f"{voice['name']} ({voice['identifier']})")
# Use a specific voice
synth = SpeechSynthesizer(
voice="com.apple.voice.compact.en-US.Samantha",
rate=0.5, # 0.0 (slowest) to 1.0 (fastest)
volume=1.0 # 0.0 to 1.0
)
synth.speak("Hello in Samantha's voice")
Save to Audio File
synth = SpeechSynthesizer()
synth.save_to_file("Hello world", "output.caf")
Apple Foundation Models (macOS 15.6+)
On-device language model — no API keys, no network calls.
Note: Requires macOS 15.6+ and pyobjc-framework-FoundationModels (not yet on PyPI).
Basic Usage
import asyncio
from macbook_ai.foundation import LanguageModel
async def main():
model = LanguageModel()
# Get complete response
response = await model.respond("What is the capital of France?")
print(response)
asyncio.run(main())
Streaming Responses
import asyncio
from macbook_ai.foundation import LanguageModel
async def main():
model = LanguageModel()
async for chunk in model.stream("Write a haiku about Python"):
print(chunk, end="", flush=True)
asyncio.run(main())
With System Instructions
model = LanguageModel(instructions="You are a helpful coding assistant.")
response = await model.respond("Explain list comprehensions")
print(response)
Development
Running Tests
uv run pytest tests/ -v
Publishing to PyPI
This project uses GitHub Actions for secure, tag-based publishing.
To publish a new version:
-
Update version in
pyproject.toml:# Edit pyproject.toml, bump version to 0.1.7 git add pyproject.toml git commit -m "Bump version to 0.1.7" git push origin main
-
Create and push a release tag:
git tag v0.1.7 git push origin v0.1.7
The pipeline will automatically:
- Run tests on Python 3.10, 3.11, and 3.12
- Verify the tag matches the version in
pyproject.toml - Build the package
- Publish to PyPI if all checks pass
Security: Only tagged releases are published. This prevents accidental or malicious publishes from regular commits.
See PUBLISHING.md for detailed setup and SECURITY.md for security best practices.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file macbook_ai-0.1.8.tar.gz.
File metadata
- Download URL: macbook_ai-0.1.8.tar.gz
- Upload date:
- Size: 28.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8204d3db74f7fd1acc2ee1e074b35906c351f6fc223775ad518f8cf26f4f0f20
|
|
| MD5 |
66eb459fa9b0ae92c8a2d199e046793b
|
|
| BLAKE2b-256 |
06251f9fa86c56375c76924c3b4bfa5eb00bc516b187355fde71811f58df0d05
|
Provenance
The following attestation bundles were made for macbook_ai-0.1.8.tar.gz:
Publisher:
publish.yml on sagrd/macbook-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
macbook_ai-0.1.8.tar.gz -
Subject digest:
8204d3db74f7fd1acc2ee1e074b35906c351f6fc223775ad518f8cf26f4f0f20 - Sigstore transparency entry: 1825006850
- Sigstore integration time:
-
Permalink:
sagrd/macbook-ai@c202e0c7589fa9c37e97e4b6994357cf1aba588b -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/sagrd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c202e0c7589fa9c37e97e4b6994357cf1aba588b -
Trigger Event:
push
-
Statement type:
File details
Details for the file macbook_ai-0.1.8-py3-none-any.whl.
File metadata
- Download URL: macbook_ai-0.1.8-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f21a3daa89631a23513e9287f887562dbc6a948f3376eac4d899bb7454f2df4b
|
|
| MD5 |
044382b764b4f664fdf13a61ca204b3f
|
|
| BLAKE2b-256 |
4774c9cc5737e726fe37fafd0f47920b88e9e808c0233667935c59a51bd16d96
|
Provenance
The following attestation bundles were made for macbook_ai-0.1.8-py3-none-any.whl:
Publisher:
publish.yml on sagrd/macbook-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
macbook_ai-0.1.8-py3-none-any.whl -
Subject digest:
f21a3daa89631a23513e9287f887562dbc6a948f3376eac4d899bb7454f2df4b - Sigstore transparency entry: 1825006859
- Sigstore integration time:
-
Permalink:
sagrd/macbook-ai@c202e0c7589fa9c37e97e4b6994357cf1aba588b -
Branch / Tag:
refs/tags/v0.1.8 - Owner: https://github.com/sagrd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c202e0c7589fa9c37e97e4b6994357cf1aba588b -
Trigger Event:
push
-
Statement type: