MC System Guide
MC (Master of Ceremonies) System
The spoken host layer of AI DJ — OpenAI line generation, Mem0 memory, ElevenLabs voice, prompting, customization, and stopping unwanted repetition.
1. End-to-end pipeline
The AI MC generates short lines for welcomes, track intros, interval check-ins, and goodbyes, converts them to speech, and plays them over the mix while ducking music volume.
Overall architecture, sessions, library, and mixing flow.
How AI DJ Works — main guideMC Settings UI → mc_context / mc_advanced / keys → Server builds prompt
→ Mem0 search (optional) → OpenAI chat completion (6–22 words)
→ Dedupe + forbidden validation → Eleven v3 audio tags (optional)
→ ElevenLabs TTS (or pyttsx3 fallback) → temp audio file
→ Client: { type: mc, wav_path, duck_* } → duck music, play audioMC → mc_donePrimary implementation: aidj_server.py (prompts, TTS, Mem0, send_mc()). Legacy helper: mc_brain.py (template buckets — largely superseded by inline MC_TEMPLATES in the server).
2. MC settings UI
Open MC Settings from the app (MC modal in electron_mock/index.html).
| Section | What it controls |
|---|---|
| Basic | Enable MC, event type, Event Prompt, venue, MC name, track naming frequency, interval minutes |
| Integrations | Mem0, ElevenLabs, OpenAI API keys |
| Advanced | Premix/postmix timing, duck level, language, Use Script Templates, template set, crowd response sim |
Click Apply Settings (mcApply) to send mc_context + mc_advanced to the server. API keys are saved separately via each integration's Save button.
- Server: %APPDATA%\AI_DJ_Demo_Pro\aidj_config.json (and env vars)
- Client: some MC UI state in localStorage via mcApply handlers
3. When the MC speaks (triggers)
| Trigger | When | Typical content |
|---|---|---|
| Welcome / session open | On Start (first time per session) | DJ + venue intro |
| premix | Before a track starts (if premix_sec > 0) | Hype the upcoming drop |
| intro / postmix | After track starts (postmix_sec, default ~3s) | Track title, energy, dedication |
| interval | Every N minutes (Speak Every N Minutes) | Crowd check-in, QR invite |
| goodbye | On End session | Thank-you line |
| manual | MC Test button or manual deck intro | Custom / test line |
Timing guards
- Skip in progress or rapid Next Track presses → MC may be skipped
- mc_busy — next line waits until current TTS finishes (mc_done from client)
- min_mc_interval_sec (~5s) between announcements when skipping rapidly
- Skip button rate limit — 3+ presses in 2s disables skip briefly (MC timing stays stable)
Track title mentions & dedications
Name Track Every N Songs (trackname_every_n, default 2) controls how often intros include the song title. 1 = every track; 2 = every other track, etc.
- One-time next dedication — queue text in MC settings before a track
- Per-track dedication — set from library (×/dedicate flow) → spoken once on that track's intro, then cleared
4. Two line sources: AI vs templates
Controlled by Use Script Templates (mc_use_templates).
Live AI (default when templates off)
Requires OpenAI API key and AIDJ_LIVE_AI_MC=1 (default on). Prompts built in _mk_intro_prompt, _mk_welcome_prompt, _mk_goodbye_prompt, interval prompts. Augmented with Mem0 memories when enabled. Validated against FORBIDDEN phrases from Event Prompt. Retried once if output contains a banned substring.
Script templates
When Use Script Templates is checked, lines are picked from MC_TEMPLATES in aidj_server.py. Template sets: default, hype, smooth, wedding. Placeholders: {venue}, {track}, {genre}, {dj}, etc. No OpenAI call for that line (TTS still needs ElevenLabs or pyttsx3).
| Use templates | Use live AI |
|---|---|
| Predictable, repeatable phrasing | Natural variation, event-specific wording |
| No OpenAI cost for lines | Rich context from Event Prompt + Mem0 |
| Offline-ish line generation | Crowd QR invites, dedications, genre teases |
You can switch per session via Apply Settings without restarting the server.
5. How prompting works (OpenAI)
System message (fixed personality)
- Sound like a real club MC — natural, varied, not radio-cliché
- 6–22 words, contractions, no emojis
- FORBIDDEN section is absolute — never use those phrases or obvious rewrites
- Vary openings; avoid starting with Let's, Keep, We're keeping
- Prefer strong verbs (Drop, Ride, Build, …) unless forbidden
- Event details occasionally (every 3–5 lines), not every line
- Crowd QR: invite scans sometimes, never read raw URLs aloud
Temperature 0.9, presence penalty 0.3, frequency penalty 0.8 — encourages variety.
User message (per announcement)
- _mc_user_settings_block(event_ctx) — full Event Prompt + parsed FORBIDDEN list
- Event type context — gym, wedding, club, etc.
- Venue, MC name, energy note, delivery style (hype vs restrained TTS hints)
- Track context — title, artist, genre tease, dedication
- Recent lines — Avoid repeating these recent lines from state.mc_history
- Crowd QR block — if crowd server is running
- Mem0 suffix — retrieved memories
Delivery style hints
| Condition | MC text style |
|---|---|
| Wedding / corporate / classy tone | Restrained — standard spelling, max one ! |
| Hype tone + medium/high energy | May use one stretched vowel (gooo) or one ALL CAPS word |
| Default | Upbeat but clean |
Post-generation checks & translation
- _line_violates_forbidden() — substring match → regenerate once with explicit fix prompt
- _too_similar() — exact match vs mc_history → line discarded
- state.mc_history — deque of last ~24 lines fed into next prompt
If Language ≠ English, prompts are passed through _translate_mc_prompt() before the LLM call; TTS uses the selected language code.
6. Event Prompt — your main customization surface
The Event Prompt textarea (mcPrompt) maps to state.event_ctx on the server via mc_context. Everything you put here is injected into every live-AI MC prompt (welcome, intro, interval, goodbye) via _mc_user_settings_block().
What to include
Wedding for Sam and Alex at Riverside Barn. Family-friendly — grandparents and kids present. Shout out the caterer Green Plate once early in the night. Keep energy warm until first dance, then open up.
The model treats this as always-on DJ instructions, not a script to read verbatim.
Event Type, Venue, and MC name
- Event Type dropdown — selects a preset tone pack (gym, club, wedding, …). Use Custom if you only want the Event Prompt text.
- Venue Name — spoken occasionally (~every 4–6 lines), not every line. Blank venue falls back to config default or Venue.
- MC Name — DJ/host name; welcome may require both DJ + venue when configured.
7. Stopping repetition and banned phrases
AI DJ uses four layers to stop unwanted repetition:
Layer 1 — Event Prompt FORBIDDEN parsing (strongest)
Write bans directly in Event Prompt. The server parses them in _extract_forbidden_phrases(). Supported patterns (case-insensitive):
Do not say "Feel that energy" Don't say 'last call' Never say hands up for the DJ Avoid saying let's go crazy Remember: Do not say "old venue name"
- Use quotes for multi-word phrases
- Keep bans specific ("Feel that energy") rather than vague ("be boring")
- Max ~20 parsed phrases per prompt
Layers 2–4
- Mem0 avoidance memories — durable never say X rules promoted to CRITICAL blocks (see Mem0 section)
- Recent line history — Avoid repeating these recent lines in each prompt; exact duplicates rejected
- Prompt-level opening bans — hard-coded: never start with Let's, Keep, We're keeping; throttle event theme and MC name mentions
Practical example — full Event Prompt
Corporate holiday party for NovaTech. No profanity. Upbeat but professional. Do not say "hands up" Do not say "make some noise" Do not say "let's get lit" Avoid saying anything about drinking contests Remember: Never mention the competitor brand SyncWare. Remember: Do not say "last call" — bar closes quietly at midnight. Mention NovaTech once in the welcome only. Thank the AV team if doing a mic check.
After Apply Settings, bans are active immediately for the next MC line.
8. Mem0 memory
Mem0 is an optional long-term memory layer. The server calls Mem0's REST API — keys stay in AppData, never in the Electron UI logs.
| Phase | Behavior |
|---|---|
| Before LLM | Search venue + global memories → append short suffix to prompt |
| After Apply Settings | Lines starting Remember: / Memory: / Mem0: → saved to venue-scoped memory |
| Auto-save (optional) | Selected spoken MC lines saved back to Mem0 for learning |
Enabling Mem0
- MC Settings → Integrations → Mem0 Memory
- Check Enable Mem0
- Paste API key → Save Mem0 → Test Mem0
- Optionally check Auto-save MC lines
| Key | Meaning |
|---|---|
| MEM0_ENABLED | 1 / 0 |
| MEM0_AUTOSAVE | 1 / 0 |
| MEM0_API_KEY | Your Mem0 API token |
| MEM0_USER_ID | Auto-generated stable user id |
Mem0 is off by default on boot unless you enable it in UI — the server explicitly avoids auto-enabling.
Memory scopes & explicit remember lines
| Scope | User ID format | Used for |
|---|---|---|
| Global | MEM0_USER_ID | Cross-venue preferences |
| Venue | {MEM0_USER_ID}:venue:{venue_slug} | Overrides per venue name |
Remember: Do not say "feel the energy" or "hands in the air" Remember: Sponsor is Blue Peak Water — mention at most once per hour Memory: Bride's name is Alex — groom is Sam — use first names only Mem0: Keep wedding lines classy — no club slang
Auto-save policy & retrieval
- Auto-save triggers: intro, interval, goodbye only (not every premix)
- Rate limit: ≥ 90 seconds between saves; dedupes identical consecutive lines
- Retrieval: search venue (top 4) + global (top 4); split into avoidance rules (CRITICAL) and general prefs
- Filter out memories that contain Event Prompt forbidden phrases
| Event Prompt | Mem0 |
|---|---|
| Always included in full | Retrieved by relevance |
| Best for tonight's brief + FORBIDDEN | Best for durable rules across sessions |
| Instant on Apply | Requires API + search latency |
| Parsed Do not say automatically | Use Remember: lines or natural-language avoid rules |
Best practice: Put hard bans in Event Prompt and Remember: the same bans into Mem0 once so they persist across app restarts.
9. ElevenLabs voice (TTS)
ElevenLabs converts MC text into speech. Without a key, the server falls back to pyttsx3 (local system TTS).
Setup
- API key — from ElevenLabs API keys page
- Voice ID — default pre-filled; swap for any voice in your library
- TTS model — Multilingual v2 (default), Eleven v3 (expressive + audio tags), Turbo v2.5 / Flash v2.5
- Save Settings → Test Key
Voice / tone selection
| Tone | Character |
|---|---|
| Hype | More dynamic, higher style, lower stability |
| Smooth | Calmer, consistent delivery |
| Classy | Restrained — weddings/corporate |
Eleven v3 + OpenAI audio tags
When TTS model = eleven_v3 and OpenAI is available: MC line is generated normally, then _enhance_mc_text_eleven_v3_blocking() asks OpenAI to insert [audio tags] without changing words. Example: [excited] Riverside, here comes the drop! Disable tag enhancement: AIDJ_ELEVEN_MC_ENHANCE_TAGS=0.
TTS fallback chain
1. ElevenLabs (if key + voice ID)
2. pyttsx3 local TTS
3. If both fail → log text only; goodbye may still trigger fade_out
Temp audio files: %TEMP%\aidj_mc_{uuid}.mp310. Volume ducking and client playback
Server sends an mc message with text, wav_path, duck_enabled, and duck_level (~0.3 = 30% music volume).
{
"type": "mc",
"text": "The spoken line",
"wav_path": "C:\\Users\\...\\aidj_mc_abc123.mp3",
"duck_enabled": true,
"duck_level": 0.3
}- Client ramps gainMusicDuck down to duck_level
- Plays audioMC from wav_path
- On end → ramps music back to 100%
- Sends mc_done so server clears mc_busy
11. Configuration reference
Environment / aidj_config.json
| Key | Default | Purpose |
|---|---|---|
| AIDJ_MC_ENABLED | 1 | MC on by default |
| AIDJ_LIVE_AI_MC | 1 | Use OpenAI for lines |
| AIDJ_LLM_MODEL | gpt-4o-mini | OpenAI model |
| OPENAI_API_KEY | — | Required for live AI + v3 tags |
| ELEVEN_API_KEY | — | ElevenLabs TTS |
| ELEVEN_VOICE_ID | app default | Override voice |
| AIDJ_ELEVEN_TTS_MODEL | multilingual_v2 | TTS model id |
| AIDJ_MC_PREMIX_SEC | 0 | Seconds before track |
| AIDJ_MC_POSTMIX_SEC | 3 | Seconds after track start |
| AIDJ_MC_DUCK | 1 | Ducking enabled |
| AIDJ_MC_DUCK_LEVEL | 0.3 | Duck target gain |
| AIDJ_MC_LANGUAGE | en | TTS language |
| AIDJ_MC_USE_TEMPLATES | 0 | Script templates vs AI |
| MEM0_ENABLED | 0 | Mem0 off until user enables |
WebSocket messages (MC-related)
| Client → server | Purpose |
|---|---|
| mc_context | Event prompt, venue, MC name, enable, interval, dedication |
| mc_advanced | Premix/postmix, duck, language, templates, template set |
| mc_voice / mc_tone | Voice gender + delivery tone |
| mc_dedication_set | Per-track dedication |
| mc_test / mc_manual | Test spoken line |
| openai_config_set / eleven_config_set / mem0_config_set | API keys |
| mc_done | Client finished playing TTS |
| Server → client | Purpose |
|---|---|
| mc | Play TTS file + duck |
| log | MC status / errors |
| dedication_indicator | Library UI badge |
12. Troubleshooting
| Problem | Things to check |
|---|---|
| No MC voice | ElevenLabs key + voice ID; try Test Key. Fallback: pyttsx3 installed on system |
| MC text in log only | TTS failed — check server log; OpenAI may still work for text |
| Same line every time | Templates mode ON → limited pool; switch to live AI or change template set |
| Repeats a phrase you hate | Add Do not say "…" to Event Prompt + Apply; add Remember: to Mem0 |
| MC ignores bans | Check quotes in Do not say; avoid overly broad bans; verify Apply Settings ran |
| Mem0 not affecting lines | Enable Mem0 + key + Test; use Remember lines; wait for search |
| Mem0 makes it worse | Disable Auto-save; delete bad memories in Mem0 dashboard |
| MC during skip chaos | Expected — rapid skip suppresses MC; wait for stable playback |
| OpenAI errors | Test Key in MC settings; AIDJ_LIVE_AI_MC=1; billing/quota |
| Eleven quota exhausted | Refresh quota display; upgrade plan or use local TTS temporarily |
| Wrong language | MC Advanced → Language; some models handle multilingual better |
Quick diagnostic order
- Is MC Enabled checked and Apply Settings clicked?
- Is Use Script Templates unintentionally on?
- Are OpenAI + ElevenLabs keys saved and tested?
- Does Event Prompt contain clear Do not say "…" lines?
- Check aidj-server.log for [MC] and TTS errors.
Appendix: Prompt function map
| Function | Used for |
|---|---|
| _mk_welcome_prompt() | Session start welcome |
| _mk_intro_prompt() | Track intros / postmix / premix AI text |
| _mk_goodbye_prompt() | Session end |
| _mk_interval_* / inline interval prompt | Periodic check-ins |
| _mc_user_settings_block() | Injects Event Prompt + FORBIDDEN |
| _mem0_prompt_blocking() | Mem0 retrieval suffix |
| _llm_call_with_mem0_blocking() | Mem0 + OpenAI combined call |
| _get_template_line() | Template mode line pick |
| send_mc() | TTS + WebSocket delivery |
Still need help?
Contact our support team for licensing, setup, or technical questions.
