Zoom Video SDK Linux
OpenAIOfficialCreated by ZoomDistributed by OpenAI
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Zoom Video SDK for Linux provides a C++ library for building custom video applications, including headless bots and UI-integrated clients. Unlike other platforms, the Linux SDK does not provide a Canvas API, requiring developers to use a raw data pipe for all audio and video processing. This skill covers the architectural patterns, environment setup, and critical implementation requirements for Linux-based Zoom integrations.
What it does
- Provides guidance for building headless bots and custom UI applications using Qt or GTK.
- Explains the mandatory raw data pipe architecture for video and audio handling.
- Details the integration of virtual audio and video devices for headless environments.
- Outlines the singleton-based SDK architecture and event delegate patterns.
- Offers troubleshooting steps for PulseAudio, Qt dependencies, and build configurations.
- Supports advanced features like cloud recording, live streaming, and transcription.
When to use it
- When building custom video conferencing applications on Linux.
- When developing headless bots for automated session participation.
- When integrating Zoom video capabilities into existing C++ applications.
- When implementing custom media processing or injection pipelines.
Advantages
- Enables full control over raw audio and video streams.
- Supports headless operation via Docker and virtual device injection.
- Provides a consistent singleton-based API for session management.
- Includes comprehensive documentation for Linux-specific environment setup.
Usage examples
- “How do I join a session using the Zoom Video SDK on Linux?”
- The agent provides the session join pattern, including initializing the SDK, setting up delegates, and configuring the session context with necessary credentials and virtual device parameters.
- “Why is my video not rendering in my Linux Zoom application?”
- The agent explains that Linux lacks a Canvas API and guides the user to implement a raw data pipe to process and render YUV420 frames manually.
- “How do I configure audio for a headless bot on Linux?”
- The agent provides instructions for installing PulseAudio, configuring the zoomus.conf file, and initializing virtual audio speakers and microphones in the session context.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/openai/zoom-video-sdk-linux/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip zoom-video-sdk-linux.zip -d .agents/skills
Documentation by Zoom
Zoom Video SDK - Linux Development
Expert guidance for developing with the Zoom Video SDK on Linux. Build headless bots, raw media capture/injection applications, and custom UI integrations with Qt/GTK.
Official Documentation: https://developers.zoom.us/docs/video-sdk/linux/ API Reference: https://marketplacefront.zoom.us/sdk/custom/linux/ Sample Repository: https://github.com/zoom/videosdk-linux-raw-recording-sample
Quick Links
New to Video SDK? Follow this path:
SDK Architecture Pattern - Universal 3-step pattern for ANY feature
Session Join Pattern - Complete working code to join a session
Raw Data vs Canvas - CRITICAL: Linux has NO Canvas API - raw data ONLY
Raw Video Capture - Capture and process YUV420 frames
Reference:
Singleton Hierarchy - 5-level SDK navigation map
API Reference - Complete API documentation
Qt/GTK Integration - UI framework patterns
Troubleshooting - Quick diagnostics
SKILL.md - Complete documentation navigation
Having issues?
PulseAudio setup → PulseAudio Guide
Qt dependencies → Qt Dependencies
Build errors → Build Errors Guide
Key Differences from Windows/macOS
| Feature | Linux | Windows/Mac |
|---|---|---|
| Canvas API | ❌ Not available | ✅ Available |
| Raw Data Pipe | ✅ ONLY option | ✅ Available |
| UI Integration | Qt, GTK, SDL2, OpenGL | Win32/WinForms/WPF, Cocoa |
| Headless Support | ✅ Excellent (Docker) | Limited |
| Audio | PulseAudio required | Native |
| Virtual Devices | ✅ Required for headless | Optional |
SDK Overview
The Zoom Video SDK for Linux is a C++ library optimized for:
Headless Bots: Docker/WSL support, no display required
Raw Data Access: Capture YUV420 video, PCM audio
Raw Data Injection: Virtual camera/mic for custom media
Screen Sharing: Capture or inject share data
Cloud Recording: Record sessions to Zoom cloud
Live Streaming: Stream to RTMP endpoints
Live Transcription: Real-time speech-to-text
Qt/GTK Integration: Full UI framework support
Prerequisites
System Requirements
OS: Ubuntu 20.04+, Debian 11+, or compatible
Architecture: x64 (recommended), ARM64
Compiler: GCC 9+, Clang 10+
CMake: 3.14 or later
Qt5: Bundled with SDK (do NOT install system Qt5)
Dependencies
sudo apt update
sudo apt install -y build-essential gcc cmake libglib2.0-dev liblzma-dev \
libxcb-image0 libxcb-keysyms1 libxcb-xfixes0 libxcb-xkb1 libxcb-shape0 \
libxcb-shm0 libxcb-randr0 libxcb-xtest0 libgbm1 libxtst6 libgl1 libnss3 \
libasound2 libpulse0
# For headless Linux
sudo apt install -y pulseaudio
# PulseAudio configuration (CRITICAL for audio)
mkdir -p ~/.config
echo "[General]" > ~/.config/zoomus.conf
echo "system.audio.type=default" >> ~/.config/zoomus.conf
# Log directory
mkdir -p ~/.zoom/logsQuick Start
#include "zoom_video_sdk_api.h"
#include "zoom_video_sdk_interface.h"
#include "zoom_video_sdk_delegate_interface.h"
USING_ZOOM_VIDEO_SDK_NAMESPACE
// 1. Create SDK
IZoomVideoSDK* sdk = CreateZoomVideoSDKObj();
// 2. Initialize
ZoomVideoSDKInitParams init_params;
init_params.domain = "https://zoom.us";
init_params.enableLog = true;
init_params.logFilePrefix = "bot";
init_params.videoRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.shareRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.audioRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
sdk->initialize(init_params);
// 3. Add delegate
sdk->addListener(myDelegate);
// 4. Join session
ZoomVideoSDKSessionContext ctx;
ctx.sessionName = "my-session";
ctx.userName = "Linux Bot";
ctx.token = "jwt-token";
ctx.audioOption.connect = true;
ctx.audioOption.mute = false;
ctx.videoOption.localVideoOn = false;
// For headless: Virtual audio speaker
ctx.virtualAudioSpeaker = new VirtualSpeaker();
IZoomVideoSDKSession* session = sdk->joinSession(ctx);See Session Join Pattern for complete code.
Key Features
| Feature | Linux Support | Guide |
|---|---|---|
| Session Management | ✅ Full | Session Join |
| Raw Video (YUV420) | ✅ ONLY rendering option | Raw Video |
| Raw Audio (PCM) | ✅ Full | Raw Audio |
| Virtual Camera/Mic | ✅ Full | Virtual Devices |
| Cloud Recording | ✅ Full | Recording |
| Live Streaming | ✅ Full | Live Stream |
| Live Transcription | ✅ Full | Transcription |
| Command Channel | ✅ Full | Commands |
| Chat | ✅ Full | Chat |
| Qt Integration | ✅ Recommended | Qt/GTK |
| GTK Integration | ✅ Supported | Qt/GTK |
| Docker/Headless | ✅ Excellent | Virtual Devices |
Critical Gotchas
⚠️ CRITICAL #1: No Canvas API on Linux
Problem: Linux SDK does NOT have Canvas API like Windows/Mac.
Solution: You MUST use Raw Data Pipe and implement your own rendering.
See: Raw Data vs Canvas
⚠️ CRITICAL #2: PulseAudio Required for Audio
Problem: SDK requires PulseAudio for raw audio functions.
Solution:
sudo apt install -y pulseaudio
mkdir -p ~/.config
echo "[General]" > ~/.config/zoomus.conf
echo "system.audio.type=default" >> ~/.config/zoomus.confSee: PulseAudio Setup
⚠️ CRITICAL #3: Qt5 Dependencies
Problem: SDK requires Qt5 libraries (bundled, NOT system Qt5).
Solution:
# Copy from SDK package
cp -r samples/qt_libs/Qt/lib/* lib/zoom_video_sdk/
# Create symlinks
cd lib/zoom_video_sdk
for lib in libQt5*.so.5; do ln -sf $lib ${lib%.5}; doneSee: Qt Dependencies
⚠️ CRITICAL #4: Heap Memory Mode
Always use heap mode for raw data:
init_params.videoRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.shareRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.audioRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;⚠️ CRITICAL #5: Virtual Audio for Headless
Problem: Docker/headless environments have no audio devices.
Solution: Use virtual audio speaker and mic.
session_context.virtualAudioSpeaker = new VirtualSpeaker();
session_context.virtualAudioMic = new VirtualMic();See: Virtual Audio/Video
Sample Repositories
Official Samples
| Repository | Description |
|---|---|
| raw-recording-sample | Raw audio/video capture |
| qt-quickstart | Qt6 UI integration |
| gtk-quickstart | GTK3 UI integration |
Sample Architecture
Headless Bot (Docker):
┌──────────────────────────────────┐
│ Virtual Audio Speaker/Mic │
├──────────────────────────────────┤
│ Raw Data Processing │
│ - YUV420 → File/Stream
## Merged from video-sdk/linux/SKILL.md
# Zoom Video SDK Linux - Complete Documentation Index
## Quick Start Path
**If you're new to the SDK, follow this order:**
1. **Read the architecture pattern** → [concepts/sdk-architecture-pattern.md](concepts/sdk-architecture-pattern.md)
- Universal formula: Singleton → Delegate → Subscribe
- Once you understand this, you can implement any feature
2. **Understand Linux specifics** → [concepts/raw-data-vs-canvas.md](concepts/raw-data-vs-canvas.md)
- **CRITICAL**: Linux has NO Canvas API - raw data ONLY
3. **Implement session join** → [examples/session-join-pattern.md](examples/session-join-pattern.md)
- Complete working JWT + session join code
4. **Setup environment** → [troubleshooting/pulseaudio-setup.md](troubleshooting/pulseaudio-setup.md)
- PulseAudio configuration (required for audio)
- [troubleshooting/qt-dependencies.md](troubleshooting/qt-dependencies.md)
- Qt5 library setup (bundled with SDK)
5. **Implement features** → Choose from examples below
---
## Documentation Structure
video-sdk/linux/ ├── SKILL.md # Main skill overview ├── SKILL.md # This file - navigation guide ├── linux.md # Platform summary │ ├── concepts/ # Core architectural patterns │ ├── sdk-architecture-pattern.md # Universal formula for ANY feature │ ├── singleton-hierarchy.md # 5-level navigation guide │ └── raw-data-vs-canvas.md # Linux-specific: raw data ONLY │ ├── examples/ # Complete working code │ ├── session-join-pattern.md # JWT auth + session join │ └── command-channel.md # Command channel with threading │ ├── troubleshooting/ # Problem solving guides │ ├── pulseaudio-setup.md # Audio configuration │ ├── qt-dependencies.md # Qt5 library setup │ ├── build-errors.md # Common build issues │ └── common-issues.md # Quick diagnostic workflow │ └── references/ # Reference documentation └── linux-reference.md # API hierarchy, methods, error codes
---
## By Use Case
### I want to build a headless bot
1. [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md) - Understand the pattern
2. [Session Join Pattern](examples/session-join-pattern.md) - Join sessions
3. [PulseAudio Setup](troubleshooting/pulseaudio-setup.md) - Configure audio
4. [Raw Data vs Canvas](concepts/raw-data-vs-canvas.md) - Understand Linux differences
### I'm getting build errors
1. [Build Errors Guide](troubleshooting/build-errors.md) - SDK build issues
2. [Qt Dependencies](troubleshooting/qt-dependencies.md) - Qt5 setup
3. [Common Issues](troubleshooting/common-issues.md) - Quick diagnostics
### I'm getting runtime errors
1. [PulseAudio Setup](troubleshooting/pulseaudio-setup.md) - Audio not working
2. [Qt Dependencies](troubleshooting/qt-dependencies.md) - Library not found
3. [Common Issues](troubleshooting/common-issues.md) - Error code tables
### I want to use command channel
1. [Command Channel](examples/command-channel.md) - Send/receive commands
2. [Common Issues](troubleshooting/common-issues.md) - Threading requirements
### I want to implement a specific feature
1. [SDK Architecture Pattern](concepts/sdk-architecture-pattern.md) - **START HERE!**
2. [Singleton Hierarchy](concepts/singleton-hierarchy.md) - Navigate to the feature
3. [API Reference](references/linux-reference.md) - Method signatures
---
## Most Critical Documents
### 1. SDK Architecture Pattern (MASTER DOCUMENT)
**[concepts/sdk-architecture-pattern.md](concepts/sdk-architecture-pattern.md)**
The universal 3-step pattern:
1. Get singleton (SDK, helpers, session, users)
2. Implement delegate (event callbacks)
3. Subscribe and use
### 2. Raw Data vs Canvas (LINUX-SPECIFIC)
**[concepts/raw-data-vs-canvas.md](concepts/raw-data-vs-canvas.md)**
**CRITICAL**: Unlike Windows/Mac, Linux SDK has NO Canvas API. You MUST use raw data pipe.
### 3. PulseAudio Setup (MOST COMMON ISSUE)
**[troubleshooting/pulseaudio-setup.md](troubleshooting/pulseaudio-setup.md)**
Audio requires PulseAudio configuration.
### 4. Qt Dependencies
**[troubleshooting/qt-dependencies.md](troubleshooting/qt-dependencies.md)**
SDK requires bundled Qt5 libraries, NOT system Qt5.
---
## Key Learnings
### Critical Discoveries:
1. **Linux has NO Canvas API**
- Windows/Mac have Canvas API for SDK-rendered video
- Linux MUST use Raw Data Pipe
- See: [Raw Data vs Canvas](concepts/raw-data-vs-canvas.md)
2. **PulseAudio is MANDATORY**
- SDK requires PulseAudio for raw audio
- Must configure ~/.config/zoomus.conf
- See: [PulseAudio Setup](troubleshooting/pulseaudio-setup.md)
3. **Use Bundled Qt5, NOT System Qt5**
- SDK includes specific Qt5 versions
- Copy from samples/qt_libs/
- See: [Qt Dependencies](troubleshooting/qt-dependencies.md)
4. **Helpers Control YOUR Streams Only**
- `videoHelper->startVideo()` starts YOUR camera
- To see others, subscribe to their VideoPipe
- See: [Singleton Hierarchy](concepts/singleton-hierarchy.md)
5. **Virtual Devices for Headless**
- Docker/headless needs virtual audio speaker/mic
- Set before joining session
- See: [Session Join Pattern](examples/session-join-pattern.md)
6. **Always Use Heap Memory Mode**
```cpp
init_params.videoRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;GLib Main Loop Required
while/sleep loops don't dispatch SDK events
Must use g_main_loop_run()
See: Common Issues
All SDK Calls Must Be on Main Thread
Background thread SDK calls return error 2 (Internal_Error)
Use g_idle_add() to schedule on GLib main thread
See: Command Channel
Command Channel is Session-Scoped
Does NOT span across different sessions
Both sender and receiver must be in the same session
See: Command Channel
Sample Repositories
raw-recording-sample - Official raw data sample
qt-quickstart - Qt6 UI integration
gtk-quickstart - GTK3 UI integration
Quick Reference
"My code won't compile"
"Audio not working"
"Library not found"
"How do I implement [feature]?"
"What error code means what?"
Document Version
Based on Zoom Video SDK for Linux v2.x
Happy coding!
Remember: The SDK Architecture Pattern is your key to unlocking the entire SDK. Read it first!
Operations
RUNBOOK.md - 5-minute preflight and debugging checklist.
Files
- ATTRIBUTION.mdAdded by AutoGineer882 B
- LICENSELicence file added by AutoGineer1.1 KiB
- RUNBOOK.md2.2 KiB
- SKILL.md15.3 KiB
- agents/openai.yaml246 B
- concepts/raw-data-vs-canvas.md16.4 KiB
- concepts/sdk-architecture-pattern.md14.7 KiB
- concepts/singleton-hierarchy.md15.0 KiB
- examples/chat.md215 B
- examples/cloud-recording.md395 B
- examples/command-channel.md9.7 KiB
- examples/live-streaming.md234 B
- examples/qt-gtk-integration.md261 B
- examples/raw-audio-capture.md215 B
- examples/raw-video-capture.md251 B
- examples/session-join-pattern.md21.2 KiB
- examples/transcription.md255 B
- examples/virtual-audio-video.md279 B
- linux.md25.7 KiB
- references/linux-reference.md26.7 KiB
- troubleshooting/build-errors.md2.0 KiB
- troubleshooting/common-issues.md5.3 KiB
- troubleshooting/pulseaudio-setup.md1.7 KiB
- troubleshooting/qt-dependencies.md1.9 KiB
linux.md
name: video-sdk/linux description: "Zoom Video SDK for Linux - C++ integration for video sessions, raw audio/video capture, screen sharing, recording, and real-time communication"
Zoom Video SDK - Linux Development
Expert guidance for developing with the Zoom Video SDK on Linux. This SDK enables headless video conferencing bots, raw media capture/injection, cloud recording, live streaming, and real-time transcription.
Official Documentation: https://developers.zoom.us/docs/video-sdk/linux/ API Reference: https://marketplacefront.zoom.us/sdk/custom/linux/ Sample Repository: https://github.com/zoom/videosdk-linux-raw-recording-sample
SDK Overview
The Zoom Video SDK for Linux is a C++ library that provides:
Session Management: Join/leave video SDK sessions
Raw Data Access: Capture raw audio/video frames (YUV420, PCM)
Raw Data Injection: Send custom audio/video into sessions
Screen Sharing: Share screens or inject custom share sources
Cloud Recording: Record sessions to Zoom cloud
Live Streaming: Stream to RTMP endpoints (YouTube, etc.)
Chat & Commands: In-session messaging and command channels
Live Transcription: Real-time speech-to-text
Subsessions: Breakout room support
Whiteboard: Collaborative whiteboard features
Annotations: Screen share annotations
Project Structure
project/
├── CMakeLists.txt
├── config.json # Session credentials
├── src/
│ ├── main.cpp
├── include/
│ └── zoom_video_sdk/ # SDK headers
│ ├── zoom_video_sdk_api.h
│ ├── zoom_video_sdk_interface.h
│ ├── zoom_video_sdk_delegate_interface.h
│ ├── zoom_video_sdk_def.h
│ └── helpers/ # Feature-specific interfaces
│ ├── zoom_video_sdk_audio_helper_interface.h
│ ├── zoom_video_sdk_audio_send_rawdata_interface.h # Virtual audio
│ ├── zoom_video_sdk_video_helper_interface.h
│ ├── zoom_video_sdk_video_source_helper_interface.h # Video injection
│ └── zoom_video_sdk_user_helper_interface.h
├── lib/
│ └── zoom_video_sdk/ # SDK + Qt5 libraries
│ ├── libvideosdk.so # Main SDK (from SDK tarball)
│ ├── libcml.so # Required
│ ├── libmpg123.so # Audio codec
│ ├── cpthost # Host binary
│ ├── libQt5Core.so.5 # Qt5 dependencies (from sdk samples/qt_libs)
│ ├── libQt5Gui.so.5
│ ├── libQt5Network.so.5
│ ├── libQt5Qml.so.5
│ └── libQt5Quick.so.5
└── bin/ # Build outputCRITICAL: SDK requires Qt5 libraries. Copy from SDK samples (qt_libs/Qt/lib/) and create symlinks:
cd lib/zoom_video_sdk
ln -sf libQt5Core.so.5 libQt5Core.so
ln -sf libQt5Gui.so.5 libQt5Gui.so
# ... repeat for all Qt5 libsPrerequisites
# System dependencies
sudo apt update
sudo apt install -y build-essential gcc cmake
sudo apt install -y libglib2.0-dev liblzma-dev libxcb-image0 libxcb-keysyms1 \
libxcb-xfixes0 libxcb-xkb1 libxcb-shape0 libxcb-shm0 libxcb-randr0 \
libxcb-xtest0 libgbm1 libxtst6 libgl1 libnss3 libasound2 libpulse0
# Qt5 is bundled with SDK - do NOT install system Qt5
# Copy Qt5 libs from SDK samples/qt_libs/Qt/lib/ to your lib directory
# For headless Linux (no soundcard)
sudo apt install -y pulseaudio
# OR use virtual audio speaker/mic in code (recommended)
# Create log directory
mkdir -p ~/.zoom/logsCMakeLists.txt Template
cmake_minimum_required(VERSION 3.14)
project(ZoomVideoSDKBot VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB REQUIRED glib-2.0)
# CRITICAL: Include both paths for nested SDK headers
include_directories(
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/include/zoom_video_sdk # For helpers/ relative includes
${GLIB_INCLUDE_DIRS}
)
link_directories(${CMAKE_SOURCE_DIR}/lib/zoom_video_sdk)
set(SOURCES src/main.cpp src/ZoomDelegate.cpp)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME}
videosdk
${GLIB_LIBRARIES}
pthread
Qt5Core Qt5Gui Qt5Network Qt5Qml Qt5Quick
)
set_target_properties(${PROJECT_NAME} PROPERTIES
BUILD_RPATH "${CMAKE_SOURCE_DIR}/lib/zoom_video_sdk"
INSTALL_RPATH "${CMAKE_SOURCE_DIR}/lib/zoom_video_sdk"
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin
)Configuration
config.json (place in bin/ directory):
{
"session_name": "your-session-name",
"token": "your.jwt.token",
"session_psw": "optional-password"
}JWT Generation: Use Zoom Video SDK credentials from marketplace.zoom.us
Core Implementation Pattern
1. SDK Initialization
#include "zoom_video_sdk_api.h"
#include "zoom_video_sdk_interface.h"
#include "zoom_video_sdk_delegate_interface.h"
USING_ZOOM_VIDEO_SDK_NAMESPACE
IZoomVideoSDK* video_sdk_obj = CreateZoomVideoSDKObj();
ZoomVideoSDKInitParams init_params;
init_params.domain = "https://zoom.us";
init_params.enableLog = true;
init_params.logFilePrefix = "my_bot";
init_params.videoRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.shareRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.audioRawDataMemoryMode = ZoomVideoSDKRawDataMemoryModeHeap;
init_params.enableIndirectRawdata = false;
ZoomVideoSDKErrors err = video_sdk_obj->initialize(init_params);2. Session Join
ZoomVideoSDKSessionContext session_context;
session_context.sessionName = "session-name";
session_context.sessionPassword = "password";
session_context.userName = "Linux Bot";
session_context.token = "jwt-token";
session_context.sessionIdleTimeoutMins = 40; // 0 = never timeout
session_context.autoLoadMutliStream = true;
session_context.videoOption.localVideoOn = true;
session_context.audioOption.connect = true;
session_context.audioOption.mute = false;
// For headless Linux - use virtual audio
ZoomVideoSDKVirtualAudioSpeaker* vSpeaker = new ZoomVideoSDKVirtualAudioSpeaker();
session_context.virtualAudioSpeaker = vSpeaker;
IZoomVideoSDKSession* session = video_sdk_obj->joinSession(session_context);3. Event Delegate
class MyDelegate : public IZoomVideoSDKDelegate {
public:
virtual void onSessionJoin() override {
printf("Joined session!\n");
// Start audio subscription
IZoomVideoSDKAudioHelper* audioHelper = video_sdk_obj->getAudioHelper();
if (audioHelper) {
audioHelper->startAudio();
audioHelper->subscribe();
}
}
virtual void onSessionLeave() override {
printf("Left session\n");
}
virtual void onError(ZoomVideoSDKErrors errorCode, int detailErrorCode) override {
printf("Error: %d, Detail: %d\n", errorCode, detailErrorCode);
}
virtual void onUserJoin(IZoomVideoSDKUserHelper* pUserHelper,
IVideoSDKVector<IZoomVideoSDKUser*>* userList) override {
int count = userList->GetCount();
for (int i = 0; i < count; i++) {
IZoomVideoSDKUser* user = userList->GetItem(i);
// Subscribe to user's video
user->GetVideoPipe()->subscribe(ZoomVideoSDKResolution_720P, videoDelegate);
}
}
virtual void onMixedAudioRawDataReceived(AudioRawData* data_) override {
// Handle mixed audio (all participants)
char* buffer = data_->GetBuffer();
unsigned int len = data_->GetBufferLen();
unsigned int sampleRate = data_->GetSampleRate();
// Process PCM audio
}
virtual void onOneWayAudioRawDataReceived(AudioRawData* data_,
IZoomVideoSDKUser* pUser) override {
// Handle individual user audio
}
};
video_sdk_obj->addListener(new MyDelegate());IZoomVideoSDKDelegate - CRITICAL Notes
WARNING: IZoomVideoSDKDelegate has many pure virtual methods. ALL must be implemented.
VERSION SENSITIVITY: The delegate interface changes between SDK versions:
New callbacks are added, old ones may be removed
Method signatures may change
ALWAYS check
zoom_video_sdk_delegate_interface.hwhen upgrading SDK versions
Required Includes for Full Class Definitions
VERSION SENSITIVITY: Forward declarations in zoom_video_sdk_def.h may change. Always verify which helper headers contain full class definitions.
// zoom_video_sdk_def.h only forward-declares classes!
// Include helper headers for actual implementations:
#include "zoom_video_sdk/helpers/zoom_video_sdk_user_helper_interface.h" // IZoomVideoSDKUser full definition
#include "zoom_video_sdk/helpers/zoom_video_sdk_audio_send_rawdata_interface.h" // Virtual audio classes
#include "zoom_video_sdk/helpers/zoom_video_sdk_video_source_helper_interface.h" // Video source/sender
#include "zoom_video_sdk/zoom_video_sdk_chat_message_interface.h" // IZoomVideoSDKChatMessageSDK 2.4.12 Method Signature Examples
VERSION SENSITIVITY: Method signatures change between SDK versions. These are examples from 2.4.12 - always verify against current SDK headers.
| Example Change | SDK 2.4.12 Signature |
|---|---|
onSessionLeave() | onSessionLeave(ZoomVideoSDKSessionLeaveReason reason) (both exist) |
onUserShareStatusChanged(...) | Takes IZoomVideoSDKShareAction* instead of ZoomVideoSDKShareStatus, ZoomVideoSDKShareType |
message->getSenderUser() | Now message->getSendUser() |
info->getSpeaker() | Now info->getSpeakerName() (returns const zchar_t* directly) |
sender->send() | Now sender->Send() (capital S) |
user->getVideoStatus() | Now user->GetVideoPipe()->getVideoStatus() |
Required Empty Stub Callbacks
VERSION SENSITIVITY: Callbacks are added/removed between SDK versions. Check zoom_video_sdk_delegate_interface.h for the complete current list.
Must implement ALL these (use empty {} for unused ones):
virtual void onUserShareStatusChanged(IZoomVideoSDKShareHelper*, IZoomVideoSDKUser*, IZoomVideoSDKShareAction*) override {}
virtual void onShareContentChanged(IZoomVideoSDKShareHelper*, IZoomVideoSDKUser*, IZoomVideoSDKShareAction*) override {}
virtual void onFailedToStartShare(IZoomVideoSDKShareHelper*, IZoomVideoSDKUser*) override {}
virtual void onShareSettingChanged(ZoomVideoSDKShareSetting) override {}
virtual void onUserManagerChanged(IZoomVideoSDKUser*) override {}
virtual void onAudioLevelChanged(unsigned int, bool, IZoomVideoSDKUser*) override {}
virtual void onSpokenLanguageChanged(ILiveTranscriptionLanguage*) override {}
virtual void onChatPrivilegeChanged(IZoomVideoSDKChatHelper*, ZoomVideoSDKChatPrivilegeType) override {}
virtual void onSendFileStatus(IZoomVideoSDKSendFile*, const FileTransferStatus&) override {}
virtual void onReceiveFileStatus(IZoomVideoSDKReceiveFile*, const FileTransferStatus&) override {}
virtual void onShareNetworkStatusChanged(ZoomVideoSDKNetworkStatus, bool) override {}
virtual void onUserNetworkStatusChanged(ZoomVideoSDKDataType, ZoomVideoSDKNetworkStatus, IZoomVideoSDKUser*) override {}
virtual void onUserOverallNetworkStatusChanged(ZoomVideoSDKNetworkStatus, IZoomVideoSDKUser*) override {}
virtual void onAnnotationHelperCleanUp(IZoomVideoSDKAnnotationHelper*) override {}
virtual void onAnnotationPrivilegeChange(IZoomVideoSDKUser*, IZoomVideoSDKShareAction*) override {}
virtual void onAnnotationHelperActived(void*) override {}
virtual void onAnnotationToolTypeChanged(IZoomVideoSDKAnnotationHelper*, void*, ZoomVideoSDKAnnotationToolType) override {}
virtual void onVideoAlphaChannelStatusChanged(bool) override {}
virtual void onSpotlightVideoChanged(IZoomVideoSDKVideoHelper*, IVideoSDKVector<IZoomVideoSDKUser*>*) override {}
// ... and many more for live stream, subsession, broadcast, etc.See zoom_video_sdk_delegate_interface.h for complete list (~90 methods).
IZoomVideoSDKRawDataPipeDelegate Requirements
VERSION SENSITIVITY: Interface methods may be added/removed between SDK versions.
class VideoDelegate : public IZoomVideoSDKRawDataPipeDelegate {
virtual void onRawDataFrameReceived(YUVRawDataI420* data) override { /* handle */ }
virtual void onRawDataStatusChanged(RawDataStatus status) override { /* handle */ }
virtual void onShareCursorDataReceived(ZoomVideoSDKShareCursorData info) override {} // REQUIRED in 2.4.12
};Raw Data Capture
Video Raw Data (YUV I420)
class VideoEncoder : public IZoomVideoSDKRawDataPipeDelegate {
public:
virtual void onRawDataFrameReceived(YUVRawDataI420* data) override {
int width = data->GetStreamWidth();
int height = data->GetStreamHeight();
char* yBuffer = data->GetYBuffer();
char* uBuffer = data->GetUBuffer();
char* vBuffer = data->GetVBuffer();
char* alphaBuffer = data->GetAlphaBuffer(); // Optional
unsigned long long timestamp = data->GetTimeStamp();
int rotation = data->GetRotation(); // 0, 90, 180, 270
bool isLimited = data->IsLimitedI420();
// Reference counting for async processing
if (data->CanAddRef()) {
data->AddRef();
// Process in background thread
data->Release();
}
}
virtual void onRawDataStatusChanged(RawDataStatus status) override {
// RawData_On or RawData_Off
}
};
// Subscribe to user's video
user->GetVideoPipe()->subscribe(ZoomVideoSDKResolution_720P, new VideoEncoder());Audio Raw Data (PCM)
// Subscribe to audio in onSessionJoin or onUserAudioStatusChanged
IZoomVideoSDKAudioHelper* audioHelper = video_sdk_obj->getAudioHelper();
audioHelper->subscribe();
// Receive in callbacks:
virtual void onMixedAudioRawDataReceived(AudioRawData* data_) override {
char* buffer = data_->GetBuffer(); // PCM 16-bit
unsigned int len = data_->GetBufferLen();
unsigned int sampleRate = data_->GetSampleRate();
unsigned int channels = data_->GetChannelNum();
unsigned long long timestamp = data_->GetTimeStamp();
}
// Convert PCM to MP3:
// ffmpeg -f s16le -ar 32000 -i output.pcm output.mp3Raw Data Injection
Virtual Audio Mic
class MyAudioMic : public IZoomVideoSDKVirtualAudioMic {
public:
virtual void onMicInitialize(IZoomVideoSDKAudioSender* sender) override {
audio_sender_ = sender;
}
virtual void onMicStartSend() override {
// Start sending audio frames
}
virtual void onMicStopSend() override {}
virtual void onMicUninitialized() override { audio_sender_ = nullptr; }
void SendAudio(char* data, unsigned int len, int sampleRate) {
if (audio_sender_) {
audio_sender_->Send(data, len, sampleRate);
}
}
private:
IZoomVideoSDKAudioSender* audio_sender_ = nullptr;
};
// Set before joining
session_context.virtualAudioMic = new MyAudioMic();
session_context.audioOption.connect = true;
session_context.audioOption.mute = false;Virtual Video Source
class MyVideoSource : public IZoomVideoSDKVideoSource {
public:
virtual void onInitialize(IZoomVideoSDKVideoSender* sender,
IVideoSDKVector<VideoSourceCapability>* caps,
VideoSourceCapability& suggest) override {
video_sender_ = sender;
}
virtual void onStartSend() override {
// Start sending video frames
}
virtual void onStopSend() override {}
virtual void onPropertyChange(...) override {}
void SendFrame(char* y, char* u, char* v, int w, int h, int rotation) {
if (video_sender_) {
video_sender_->sendVideoFrame(y, u, v, w, h, 0, rotation);
}
}
private:
IZoomVideoSDKVideoSender* video_sender_ = nullptr;
};
// Set before joining
session_context.externalVideoSource = new MyVideoSource();Helper Interfaces
Audio Helper
IZoomVideoSDKAudioHelper* audio = video_sdk_obj->getAudioHelper();
audio->startAudio();
audio->stopAudio();
audio->muteAudio(true);
audio->subscribe(); // For raw data callbacks
audio->unSubscribe();Video Helper
IZoomVideoSDKVideoHelper* video = video_sdk_obj->getVideoHelper();
video->startVideo();
video->stopVideo();
video->rotateMyVideo(90);
IVideoSDKVector<IZoomVideoSDKCameraDevice*>* cameras = video->getCameraList();Share Helper
IZoomVideoSDKShareHelper* share = video_sdk_obj->getShareHelper();
share->startShare();
share->startSharingExternalSource(shareSource);
share->stopShare();
bool isSharing = share->isSharingOut();Chat Helper
IZoomVideoSDKChatHelper* chat = video_sdk_obj->getChatHelper();
chat->sendChatToAll("Hello!");
chat->sendChatToUser(user, "Private message");Recording Helper
IZoomVideoSDKRecordingHelper* rec = video_sdk_obj->getRecordingHelper();
if (rec->canStartRecording() == ZoomVideoSDKErrors_Success) {
rec->startCloudRecording();
}Live Stream Helper
IZoomVideoSDKLiveStreamHelper* ls = video_sdk_obj->getLiveStreamHelper();
if (ls->canStartLiveStream() == ZoomVideoSDKErrors_Success) {
ls->startLiveStream("rtmp://...", "stream-key", "broadcast-url");
}Live Transcription Helper
Note: The session host can start/stop live transcription via the SDK object. Participants receive transcription messages via callbacks.
IZoomVideoSDKLiveTranscriptionHelper* ltt = video_sdk_obj->getLiveTranscriptionHelper();
// Check if transcription can be started (host privilege required)
if (ltt->canStartLiveTranscription()) {
ltt->startLiveTranscription();
}
// Set spoken language (optional)
IVideoSDKVector<ILiveTranscriptionLanguage*>* languages = ltt->getAvailableSpokenLanguages();
if (languages && languages->GetCount() > 0) {
ltt->setSpokenLanguage(languages->GetItem(0)->getLTTLanguageID());
}
// Receive transcription in callback:
virtual void onLiveTranscriptionMsgInfoReceived(ILiveTranscriptionMessageInfo* info) override {
const char* speaker = info->getSpeakerName();
const char* content = info->getMessageContent();
printf("[%s]: %s\n", speaker, content);
}
// Monitor transcription status changes:
virtual void onLiveTranscriptionStatus(ZoomVideoSDKLiveTranscriptionStatus status) override {
// ZoomVideoSDKLiveTranscription_Status_Start or _Stop
}CMakeLists.txt Template
cmake_minimum_required(VERSION 3.10)
project(ZoomVideoSDKBot)
set(CMAKE_CXX_STANDARD 14)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GLIB REQUIRED glib-2.0)
include_directories(
${CMAKE_SOURCE_DIR}/src/include
${GLIB_INCLUDE_DIRS}
)
link_directories(${CMAKE_SOURCE_DIR}/src/lib/zoom_video_sdk)
add_executable(${PROJECT_NAME}
src/main.cpp
src/ZoomVideoSDKRawDataPipeDelegate.cpp
src/ZoomVideoSDKVirtualAudioMic.cpp
src/ZoomVideoSDKVirtualAudioSpeaker.cpp
)
target_link_libraries(${PROJECT_NAME}
videosdk
${GLIB_LIBRARIES}
pthread
z
lzma
)Build & Run
cmake -B build
cd build && make
# Run from bin directory
cd bin
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../src/lib/zoom_video_sdk
./ZoomVideoSDKBotHeadless Linux (Docker/WSL)
# Install PulseAudio
sudo apt install -y pulseaudio
pulseaudio --start
# Create virtual devices
pactl load-module module-null-sink sink_name=virtual_speaker
pactl load-module module-null-source source_name=virtual_mic
# Configure
mkdir -p ~/.config
cat > ~/.config/zoomus.conf << EOF
[General]
system.audio.type=default
EOFOr use IZoomVideoSDKVirtualAudioSpeaker and IZoomVideoSDKVirtualAudioMic interfaces.
Thread Safety
SDK callbacks are on SDK's internal threads
Don't perform heavy operations in callbacks
Use message queues for async processing
Don't call
cleanup()inside callbacks
// Reference counting for async use
if (data->CanAddRef()) {
data->AddRef();
// Queue for processing
data->Release(); // When done
}Custom UI Frameworks
For applications requiring a graphical user interface, use these quickstart templates:
Qt Framework (Recommended)
Repository: https://github.com/tanchunsiong/videosdk-linux-qt-quickstart
# Prerequisites
sudo apt install -y qt6-base-dev qt6-tools-dev libasound2-dev cmake
# Build
cd videosdk-linux-qt-quickstart/src
mkdir build && cd build
export Qt6_DIR=/usr/lib/x86_64-linux-gnu/cmake/Qt6
cmake .. && make -j$(nproc)
# Run
./run_qt_demo.shFeatures:
Qt6/Qt5 cross-platform GUI
Video rendering with QPainter + QImage
YUV-to-RGB conversion (ITU-R BT.601)
ALSA audio playback
Device selection (camera, mic, speaker)
Session management UI
Key Components:
QtMainWindow- Main window with controlsQtVideoWidget- Video display widgetQtVideoRenderer- Video rendering logicQtPreviewVideoHandler- Self video previewQtRemoteVideoHandler- Remote video streams
Qt Platform Options:
# Desktop
./run_qt_demo.sh
# Headless/Server
QT_QPA_PLATFORM=offscreen ./run_qt_demo.sh
# Wayland
QT_QPA_PLATFORM=wayland ./run_qt_demo.sh
# X11 with SSH forwarding
ssh -X user@host
export DISPLAY=:10.0
./run_qt_demo.shGTK Framework
Repository: https://github.com/tanchunsiong/videosdk-linux-gtk-quickstart
# Prerequisites
sudo apt install -y libgtkmm-3.0-dev libsdl2-dev libasound2-dev libcurl4-openssl-dev cmake
# Build
cd videosdk-linux-gtk-quickstart/src
mkdir build && cd build
cmake .. && make
# Run
cd ../bin && ./SkeletonDemoFeatures:
GTKmm 3.0 native Linux GUI
SDL2 + Cairo video rendering
ALSA audio integration
Device hot-swapping
Separate self/remote video panels
Chat system
Key Components:
VideoRenderer- SDL2-based rendering engineVideoDisplayBridge- SDK to renderer connectionPreviewVideoHandler- Camera previewRemoteVideoRawDataHandler- Remote participant video
Architecture:
┌─────────────────────────────────────────────────────────┐
│ GTK User Interface │
├─────────────────────────────────────────────────────────┤
│ Session Controls │ Device Selection │ Video Controls │
├─────────────────────────────────────────────────────────┤
│ Self Video │ Status Area │ Remote Video │
│ (Left Panel) │ │ (Right Panel) │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Video Processing Layer │
│ VideoRenderer ←→ VideoDisplayBridge ←→ Device Manager │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Zoom Video SDK │
└─────────────────────────────────────────────────────────┘Comparison
| Feature | Qt | GTK |
|---|---|---|
| Cross-platform | Yes (Windows, Mac, Linux) | Linux-focused |
| Video Rendering | QPainter + QImage | SDL2 + Cairo |
| Threading | Qt signals/slots | Glib main loop |
| Modern C++ | Better support | Good support |
| Performance | Slightly better | Good |
| Learning Curve | Moderate | Moderate |
Choose Qt for: Cross-platform apps, modern C++ features, better tooling Choose GTK for: Native Linux look, lightweight, GNOME integration
Runtime Setup
Required Symlinks
cd lib/zoom_video_sdk
# SDK library versioned symlink
ln -sf libvideosdk.so libvideosdk.so.1
# Qt5 library symlinks (if using bundled Qt)
ln -sf libQt5Core.so.5 libQt5Core.so
ln -sf libQt5Gui.so.5 libQt5Gui.so
ln -sf libQt5Network.so.5 libQt5Network.so
ln -sf libQt5Qml.so.5 libQt5Qml.so
ln -sf libQt5Quick.so.5 libQt5Quick.soOutput Directories
Create directories for raw data capture (relative to binary location):
mkdir -p bin/output/audio bin/output/videoRaw File Playback
# Audio (PCM 16-bit, 32kHz, Mono)
ffplay -f s16le -ar 32000 -ac 1 output/audio/mixed_audio.pcm
# Video (YUV420P) - adjust resolution as needed
ffplay -f rawvideo -pixel_format yuv420p -video_size 640x360 output/video/video.yuv
# Convert audio to MP3
ffmpeg -f s16le -ar 32000 -ac 1 -i audio.pcm output.mp3
# Convert video to MP4
ffmpeg -f rawvideo -pixel_format yuv420p -video_size 640x360 -framerate 30 -i video.yuv -c:v libx264 output.mp4Error Codes
| Code | Name | Description |
|---|---|---|
| 0 | Success | Operation succeeded |
| 1001 | Auth_Error | Authentication failed |
| 1002 | Auth_Empty_Token | No token provided |
| 1003 | Auth_Wrong_Token | Invalid token |
| 1004 | Auth_Expired_Token | Token expired |
| 3001 | Session_Join_Failed | Failed to join |
| 3008 | Session_Need_Password | Password required |
| 3009 | Session_Password_Wrong | Wrong password |
Reference Files
See linux-reference.md for complete API documentation.
Requirements and compatibility
Written for: OpenAI Codex
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Zoom
- Publisher
- OpenAI (Official)
- Distributed by
- OpenAI
- Source
- openai/plugins · plugins/zoom/skills/video-sdk/linux · commit d420d13
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from plugins/zoom/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Zoom or OpenAI.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download zoom-video-sdk-linux.zip