partner-built/zoom-plugin/skills/meeting-sdk/linux/SKILL.md
Zoom Meeting SDK for Linux - C++ headless meeting bots with raw audio/video access, transcription, recording, and AI integration for server-side automation
npx skillsauth add anthropics/knowledge-work-plugins meeting-sdk/linuxInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Expert guidance for building headless meeting bots with the Zoom Meeting SDK on Linux. This SDK enables server-side meeting participation, raw media capture, transcription, and AI-powered meeting automation.
Use this skill when the requirement is:
Skill chain:
meeting-sdk/linuxzoom-rest-api for OBF/ZAK lookup, scheduling, or cloud-recording settingszoom-webhooks when post-meeting cloud recording retrieval is requiredMinimal raw-recording flow:
JoinParam join_param;
join_param.userType = SDK_UT_WITHOUT_LOGIN;
auto& params = join_param.param.withoutloginuserJoin;
params.meetingNumber = meeting_number;
params.userName = "Recording Bot";
params.psw = meeting_password.c_str();
params.app_privilege_token = obf_token.c_str();
SDKError join_err = meeting_service->Join(join_param);
if (join_err != SDKERR_SUCCESS) {
throw std::runtime_error("join_failed");
}
// In MEETING_STATUS_INMEETING callback:
auto* record_ctrl = meeting_service->GetMeetingRecordingController();
if (!record_ctrl) {
throw std::runtime_error("recording_controller_unavailable");
}
if (record_ctrl->CanStartRawRecording() != SDKERR_SUCCESS) {
throw std::runtime_error("raw_recording_not_permitted");
}
SDKError record_err = record_ctrl->StartRawRecording();
if (record_err != SDKERR_SUCCESS) {
throw std::runtime_error("start_raw_recording_failed");
}
GetAudioRawdataHelper()->subscribe(new MyAudioDelegate());
Use raw recording when the bot must own PCM/YUV media or feed an AI pipeline directly.
Use cloud recording + webhooks when the requirement is Zoom-managed MP4/M4A/transcript assets after the meeting.
Official Documentation: https://developers.zoom.us/docs/meeting-sdk/linux/
API Reference: https://marketplacefront.zoom.us/sdk/meeting/linux/
Sample Repository (Raw Recording): https://github.com/zoom/meetingsdk-linux-raw-recording-sample
Sample Repository (Headless): https://github.com/zoom/meetingsdk-headless-linux-sample
New to Meeting SDK Linux? Follow this path:
Common Use Cases:
Having issues?
If the user asks to build a bot that automatically joins a Zoom meeting and records it, start with meeting-sdk-bot.md.
The Zoom Meeting SDK for Linux is a C++ library optimized for headless server environments:
| Feature | Meeting SDK (Linux) | Video SDK |
|---------|-------------------|-----------|
| Primary Use | Join existing meetings as bot | Host custom video sessions |
| Visibility | Visible participant | Session participant |
| UI | Headless (no UI) | Optional custom UI |
| Authentication | JWT + OBF/ZAK for external meetings | JWT only |
| Recording Control | StartRawRecording() required | Direct raw data access |
| Platform | Linux only | Windows, macOS, iOS, Android |
# Ubuntu
apt-get install -y build-essential cmake \
libx11-xcb1 libxcb-xfixes0 libxcb-shape0 libxcb-shm0 \
libxcb-randr0 libxcb-image0 libxcb-keysyms1 libxcb-xtest0 \
libglib2.0-dev libcurl4-openssl-dev pulseaudio
# CentOS
yum install -y cmake gcc gcc-c++ \
libxcb-devel xcb-util-image xcb-util-keysyms \
glib2-devel libcurl-devel pulseaudio
# Download from https://marketplace.zoom.us/
tar xzf zoom-meeting-sdk-linux_x86_64-{version}.tar
# Organize files
mkdir -p demo/include/h demo/lib/zoom_meeting_sdk
cp -r h/* demo/include/h/
cp lib*.so demo/lib/zoom_meeting_sdk/
cp -r qt_libs demo/lib/zoom_meeting_sdk/
cp translation.json demo/lib/zoom_meeting_sdk/json/
# Create required symlink
cd demo/lib/zoom_meeting_sdk && ln -s libmeetingsdk.so libmeetingsdk.so.1
#include "zoom_sdk.h"
USING_ZOOM_SDK_NAMESPACE
// Initialize SDK
InitParam init_params;
init_params.strWebDomain = "https://zoom.us";
init_params.enableLogByDefault = true;
init_params.rawdataOpts.audioRawDataMemoryMode = ZoomSDKRawDataMemoryModeHeap;
InitSDK(init_params);
// Authenticate with JWT
AuthContext auth_ctx;
auth_ctx.jwt_token = your_jwt_token;
CreateAuthService(&auth_service);
auth_service->SDKAuth(auth_ctx);
// In onAuthenticationReturn callback
void onAuthenticationReturn(AuthResult ret) {
if (ret == AUTHRET_SUCCESS) {
JoinParam join_param;
join_param.userType = SDK_UT_WITHOUT_LOGIN;
auto& params = join_param.param.withoutloginuserJoin;
params.meetingNumber = 1234567890;
params.userName = "Bot";
params.psw = "password";
params.isVideoOff = true;
params.isAudioOff = false;
meeting_service->Join(join_param);
}
}
// In onMeetingStatusChanged callback
void onMeetingStatusChanged(MeetingStatus status, int iResult) {
if (status == MEETING_STATUS_INMEETING) {
auto* record_ctrl = meeting_service->GetMeetingRecordingController();
// Start raw recording (enables raw data access)
if (record_ctrl->CanStartRawRecording() == SDKERR_SUCCESS) {
record_ctrl->StartRawRecording();
// Subscribe to audio
auto* audio_helper = GetAudioRawdataHelper();
audio_helper->subscribe(new MyAudioDelegate());
// Subscribe to video
IZoomSDKRenderer* video_renderer;
createRenderer(&video_renderer, new MyVideoDelegate());
video_renderer->setRawDataResolution(ZoomSDKResolution_720P);
video_renderer->subscribe(user_id, RAW_DATA_TYPE_VIDEO);
}
}
}
| Feature | Description | |---------|-------------| | Headless Operation | No GUI, perfect for Docker/server deployments | | Raw Audio (PCM) | Capture mixed or per-user audio at 32kHz | | Raw Video (YUV420) | Capture video frames in contiguous planar format | | GLib Event Loop | Async callback handling | | Docker Support | Pre-built Dockerfiles for CentOS/Ubuntu | | PulseAudio Virtual Devices | Audio in headless environments | | Breakout Rooms | Programmatic breakout room management | | Chat | Send/receive in-meeting chat | | Recording Control | Local, cloud, and raw recording |
The #1 issue for raw audio in Docker:
Raw audio requires PulseAudio and a config file, even in headless environments.
Solution:
# Install PulseAudio
apt-get install -y pulseaudio pulseaudio-utils
# Create config file
mkdir -p ~/.config
cat > ~/.config/zoomus.conf << EOF
[General]
system.audio.type=default
EOF
# Start PulseAudio with virtual devices
pulseaudio --start --exit-idle-time=-1
pactl load-module module-null-sink sink_name=virtual_speaker
pactl load-module module-null-sink sink_name=virtual_mic
See: references/linux-reference.md#pulseaudio-setup
Unlike Video SDK, Meeting SDK requires explicit permission to access raw data:
// MUST call StartRawRecording() first
auto* record_ctrl = meeting_service->GetMeetingRecordingController();
SDKError can_record = record_ctrl->CanStartRawRecording();
if (can_record == SDKERR_SUCCESS) {
record_ctrl->StartRawRecording();
// NOW you can subscribe to audio/video
} else {
// Need: host/co-host status OR recording token
}
Ways to get permission:
recording_token parameter (get via REST API)app_privilege_token (OBF) when joiningSDK callbacks execute via GLib event loop:
#include <glib.h>
// Setup main loop
GMainLoop* loop = g_main_loop_new(NULL, FALSE);
// Add timeout for periodic tasks
g_timeout_add_seconds(10, check_meeting_status, NULL);
// Run loop (blocks until quit)
g_main_loop_run(loop);
Without GLib loop: Callbacks never fire, join hangs indefinitely.
Always use heap mode for raw data to avoid stack overflow with large frames:
init_params.rawdataOpts.videoRawDataMemoryMode = ZoomSDKRawDataMemoryModeHeap;
init_params.rawdataOpts.shareRawDataMemoryMode = ZoomSDKRawDataMemoryModeHeap;
init_params.rawdataOpts.audioRawDataMemoryMode = ZoomSDKRawDataMemoryModeHeap;
SDK callbacks execute on SDK threads:
CleanUPSDK() from within callbacksSee: concepts/high-level-scenarios.md#scenario-1
Join Meeting → StartRawRecording → Subscribe Audio →
Stream to AssemblyAI/Whisper → Generate Real-time Transcript
See: concepts/high-level-scenarios.md#scenario-2
Join Meeting → StartRawRecording → Subscribe Audio+Video →
Write YUV+PCM → FFmpeg Merge → Upload to Storage
See: concepts/high-level-scenarios.md#scenario-3
Join Meeting → Real-time Transcription → AI Analysis →
Extract Action Items → Generate Summary
Official Repositories:
| Sample | Description | Link | |--------|-------------|------| | Raw Recording Sample | Traditional C++ approach with config.txt | GitHub | | Headless Sample | Modern TOML-based with CLI, Docker Compose | GitHub |
What Each Demonstrates:
| Issue | Cause | Solution |
|-------|-------|----------|
| No audio in Docker | Missing PulseAudio config | Create ~/.config/zoomus.conf |
| Raw recording denied | No permission | Use host/co-host OR recording token |
| Callbacks not firing | Missing GLib main loop | Add g_main_loop_run() |
| Build errors (XCB) | Missing X11 libraries | Install libxcb packages |
| Segfault on auth | OpenSSL version mismatch | Install libssl1.1 |
Complete troubleshooting: references/linux-reference.md#troubleshooting
Need help? Start with linux.md for quick start, then explore high-level-scenarios.md for production patterns.
testing
Reads a forwarded customer email or ticket, pulls order/refund status from PayPal and account history from HubSpot, drafts a tone-matched reply in the owner's writing voice, and can issue a PayPal refund with explicit owner approval. Use when the user says "draft a response," "answer this customer," "where's my order," or "I want a refund."
development
Prepares tax-season materials for small business owners — framed as deliverables for their accountant, not tax advice. Two modes: (1) quarterly estimated tax calculation — pulls YTD net income from QuickBooks and calculates the federal income tax + self-employment tax liability and quarterly payment due; (2) year-end 1099 prep — scans QuickBooks, PayPal, and Stripe for contractors paid over $600, builds a 1099-NEC candidate list with missing W-9 flags, and produces a plain-English summary a CPA can work from directly. Trigger this skill whenever the user mentions: quarterly taxes, estimated tax payment, how much to set aside for taxes, 1099s, 1099-NEC, year-end tax prep, contractor payments, W-9s, or any phrase suggesting they are preparing for a tax deadline or handing materials to an accountant. Also trigger proactively when a user asks about net profit or YTD income in a context that suggests they are worried about their tax bill.
tools
Prepares tax-season materials — quarterly estimated tax calculation or year-end 1099 prep — and produces an accountant handoff packet. Accepts optional mode and year arguments.
tools
The front door to the Small Business plugin. Listens to what the owner needs right now — vague or specific — and routes them to the best skill or slash command for the moment. Also serves as a guide: explains what's available, suggests what to try next, and adapts recommendations based on stored business context. Trigger whenever the owner asks "what can you do," "help me with my business," "what should I focus on," "I don't know where to start," or any open-ended business request that doesn't clearly match a single skill.