One-command migration from Recall.ai to MeetStream.ai — scans your codebase, maps APIs, transforms code.
Project description
meetstream-migrate
One-command migration from Recall.ai to MeetStream.ai. Scans your codebase, maps every API call, shows the diff, and migrates.
Why migrate?
- ~40% cheaper — significantly lower per-hour bot and transcription costs
- Agent-first architecture — built for AI agents joining meetings, not just recording
- Context layers — real-time info fetching during calls
- Migration CLI — scan, preview, migrate, test in minutes
Quick Start
pip install meetstream-migrate
meetstream-migrate scan ./your-recall-project
Or run without installing:
pipx run meetstream-migrate scan ./your-recall-project
Commands
Scan (read-only)
Finds every Recall.ai reference in your codebase. No files are modified.
meetstream-migrate scan ./your-project
Dry Run (preview changes)
Shows exactly what would change — still no writes.
meetstream-migrate migrate ./your-project --dry-run
Migrate
Applies all transformations. Prompts for confirmation before writing.
meetstream-migrate migrate ./your-project --yes
Test APIs
Verifies your MeetStream API key works and endpoints are reachable.
meetstream-migrate test --api-key YOUR_MEETSTREAM_API_KEY
What It Detects
The scanner finds:
- Base URLs —
us-east-1.recall.ai,api.recall.ai - API endpoints — all 14 Recall endpoints mapped to MeetStream equivalents
- Field names —
meeting_url,recording_mode,metadata,transcription_options, etc. - Webhook handlers —
joining_call,in_call_recording,done,fatal, etc. - SDK imports —
import recall,from recall import - Environment variables —
RECALL_API_KEY
Supported file types: .js, .ts, .jsx, .tsx, .py, .go, .rb, .java, .env, .yaml, .json
Endpoint Mapping
| Recall.ai | MeetStream.ai | Notes |
|---|---|---|
POST /api/v1/bot/ |
POST /api/v1/bots/create_bot |
Field names differ |
GET /api/v1/bot/{id}/ |
GET /api/v1/bots/{id}/detail |
|
POST /api/v1/bot/{id}/leave_call/ |
GET /api/v1/bots/{id}/remove_bot |
Method change |
DELETE /api/v1/bot/{id}/ |
DELETE /api/v1/bots/{id}/delete |
|
GET /api/v1/bot/ |
GET /api/v1/bots |
List all |
GET /bot/{id}/audio/ |
GET /bots/{id}/get_audio |
|
GET /bot/{id}/video/ |
GET /bots/{id}/get_video |
|
GET /bot/{id}/transcript/ |
GET /transcript/{transcript_id}/get_transcript |
Uses transcript_id |
GET /bot/{id}/participants/ |
GET /bots/{id}/get_participants |
|
GET /bot/{id}/chat_messages/ |
GET /bots/{id}/get_chats |
|
POST /bot/{id}/send_chat_message/ |
bot_message field on create_bot |
Manual review |
GET /bot/{id}/screenshots/ |
GET /bots/{id}/get_screenshots |
|
GET /bot/{id}/speaker_timeline/ |
GET /bots/{id}/get_speaker_timeline |
|
POST /api/v1/webhook/ |
callback_url on create_bot |
Per-bot webhooks |
Field Mapping
| Recall.ai | MeetStream.ai |
|---|---|
meeting_url |
meeting_link |
recording_mode (string) |
video_required (boolean) |
metadata |
custom_attributes |
transcription_options |
recording_config.transcript |
noone_joined_timeout |
voice_inactivity_timeout |
destination_url |
webhook_url |
output_media.websocket.url |
socket_connection_url.websocket_url |
Webhook Event Mapping
IMPORTANT: MeetStream uses a two-layer event model, not a flat event list like Recall. You must check event first, then bot_status for detail — especially for bot.stopped where bot_status tells you why the bot stopped (normal exit, denied, lobby timeout, or error).
The webhook payload format is:
{ "event": "bot.inmeeting", "bot_id": "...", "bot_status": "InMeeting", "message": "...", "status_code": 200, "timestamp": "...", "custom_attributes": {} }
Bot Lifecycle Events
| Recall.ai Event | MeetStream event |
bot_status |
Description |
|---|---|---|---|
bot.joining_call |
bot.joining |
Joining |
Bot connecting to meeting |
bot.in_waiting_room |
bot.joining |
Joining |
Bot in waiting room |
bot.in_call_not_recording |
bot.inmeeting |
InMeeting |
Joined, not yet recording |
bot.recording_permission_allowed |
bot.inmeeting |
InMeeting |
Recording allowed |
bot.recording_permission_denied |
bot.stopped |
Denied |
Recording denied by host |
bot.in_call_recording |
bot.inmeeting |
InMeeting |
In-call, recording |
bot.call_ended |
bot.stopped |
Stopped |
Meeting ended / bot left |
bot.call_ended (lobby_timeout) |
bot.stopped |
NotAllowed |
Bot could not join (lobby timeout) |
bot.done |
bot.stopped |
Stopped |
Bot lifecycle ended |
bot.fatal |
bot.stopped |
Error |
Unexpected error |
Post-Call Processing Events (MeetStream)
| Recall.ai | MeetStream event |
Description |
|---|---|---|
bot.done (then fetch) |
audio.processed |
Audio ready to fetch |
bot.done (then fetch) |
transcription.processed |
Transcript ready to fetch |
bot.done (then fetch) |
video.processed |
Video ready to fetch |
| (no equivalent) | data_deletion |
Bot data deleted |
Real-Time Events
| Recall.ai Event | MeetStream | Description |
|---|---|---|
transcript.data |
live_transcription_required webhook |
Transcript utterance |
transcript.partial_data |
live_transcription_required webhook |
Partial transcript |
transcript.done |
transcription.processed |
Full transcript ready |
participant_events.join |
Realtime endpoint | Participant joined |
participant_events.leave |
Realtime endpoint | Participant left |
bot_status Reference
bot_status |
event |
Meaning |
|---|---|---|
Joining |
bot.joining |
Bot is connecting |
InMeeting |
bot.inmeeting |
Bot is in the meeting and recording |
Stopped |
bot.stopped |
Bot exited normally (meeting ended, removed via API, everyone left, voice timeout, etc.) |
NotAllowed |
bot.stopped |
Bot could not join (commonly waiting room / lobby timeout) |
Denied |
bot.stopped |
Host explicitly denied join or recording permission |
Error |
bot.stopped |
Unexpected error during lifecycle |
Breaking Changes to Watch
These are flagged during migration and require manual review:
- Transcript retrieval — MeetStream uses
transcript_id(returned in create_bot response), notbot_id - Recording mode — Recall uses strings (
speaker_view,gallery_view,audio_only), MeetStream uses a booleanvideo_required - Chat messages — Recall has a separate
POST /send_chat_message/endpoint, MeetStream uses thebot_messagefield oncreate_bot - Webhooks — Recall registers webhooks globally via
POST /webhook/, MeetStream usescallback_urlper bot on creation - Webhook events — Recall uses granular string events (
bot.joining_call,bot.in_call_recording), MeetStream uses 3 lifecycle events (bot.joining,bot.inmeeting,bot.stopped) withbot_statusfor detail - Post-call processing — Recall signals readiness via
bot.done, MeetStream sends separateaudio.processed,transcription.processed, andvideo.processedwebhooks - Live transcription — Recall uses
real_time_transcription.destination_url, MeetStream useslive_transcription_required.webhook_urlon create_bot
Post-Migration Checklist
After running the migration:
- Set
MEETSTREAM_API_KEYin your.envfile (get one at app.meetstream.ai) - Review all warnings from the migration output
- Update webhook handlers to use
event+bot_statusinstead of Recall event names - Store
transcript_idfrom create_bot responses for transcript retrieval - Add handlers for
audio.processed,transcription.processed,video.processedwebhooks - Verify
recording_mode→video_requiredboolean logic - Run
meetstream-migrate test --api-key YOUR_KEYto verify
CLI Options
meetstream-migrate [command] [path] [options]
Commands:
scan [path] Scan only — show what would change
migrate [path] Scan & migrate a project (default)
test Run API tests against MeetStream.ai
Options:
--yes, -y Skip confirmation prompt
--dry-run Show changes without writing files
--api-key KEY MeetStream API key (for test command)
Also available as an npm package
npx @meetstream/migrate scan ./your-project
See @meetstream/migrate on npm.
Requirements
- Python >= 3.8
License
MIT
Need help migrating? Reach out at meetstream.ai — we'll walk you through it.
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 meetstream_migrate-1.0.0.tar.gz.
File metadata
- Download URL: meetstream_migrate-1.0.0.tar.gz
- Upload date:
- Size: 16.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3debe0005b68984ea64fa6dbb862ee98c9c887ff51b0218145d89e0820a9c0bb
|
|
| MD5 |
808358bf9f7901df33151490066c65f0
|
|
| BLAKE2b-256 |
f5f5e71e600b9cbe65836667e50d91b95b5950cbe9b3ec54ac47d99c2abb5c39
|
File details
Details for the file meetstream_migrate-1.0.0-py3-none-any.whl.
File metadata
- Download URL: meetstream_migrate-1.0.0-py3-none-any.whl
- Upload date:
- Size: 15.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
369a1ade7e50a384bcfb596fd05b5063a4f9fc9a6514c101d353aa5a8227a138
|
|
| MD5 |
16653562eadf4e20d99bc753427739fa
|
|
| BLAKE2b-256 |
a486b835f08e2283740bbf22d673e01dd73d51172fa1a180803ce1f7353b2f2c
|