Hi there. I’m running into a continual issue and I’m unsure how to resolve.
SDKError err_can_start = m_pRecordController->CanStartRawRecording();
if (err_can_start == SDKERR_SUCCESS) {
std::cout << "[REC_CTRL] Permission granted. Attempting to StartRawRecording()..." << std::endl;
SDKError err_start = m_pRecordController->StartRawRecording();
if (err_start == SDKERR_SUCCESS) {
std::cout << "[REC_CTRL] StartRawRecording() call SUCCEEDED." << std::endl;
g_rawRecordingGloballyActive = true; // <<< SET THE FLAG HERE
if (isVideo) {
std::cout << "[REC_CTRL] Initializing renderers for all *current* participants..." << std::endl;
m_pParticipantsController = m_pMeetingService->GetMeetingParticipantsController();
if (m_pParticipantsController) {
IList<unsigned int>* participants = m_pParticipantsController->GetParticipantsList();
if (participants) {
printf("[REC_CTRL] Found %d current participants. Creating renderers...\n", participants->GetCount());
for (int i = 0; i < participants->GetCount(); ++i) {
uint32_t participantId = participants->GetItem(i);
std::cout << "[REC_CTRL] Attempting to create/subscribe renderer for UserID: " << participantId << std::endl;
createAndSubscribeUserRenderer(participantId);
On startup I’m looping participants (shown above) and trying to subscribe to their raw data feed, using the function below:
void createAndSubscribeUserRenderer(uint32_t userIdToSubscribe) { // Renamed param for clarity
std::lock_guard<std::mutex> lock(g_rendererMapMutex);
if (g_userVideoRenderHelpers.count(userIdToSubscribe) || g_userVideoDelegates.count(userIdToSubscribe)) {
std::cout << "[RENDER_MGR] Renderer already exists for UserID: " << userIdToSubscribe << ". Skipping creation." << std::endl;
return;
}
if (g_zoom_unique_meeting_id.empty()) { return; }
if (!m_pMeetingService) { return; }
std::cout << "[RENDER_MGR] Creating renderer for UserID: " << userIdToSubscribe << std::endl;
ZoomSDKRenderer* userDelegate = nullptr;
IZoomSDKRenderer* sdkRendererHelper = nullptr; // SDK's helper object
// 1. Create your custom delegate, informing it which UserID it's logically for.
// Pass nullptr for the helper initially, as it's not created yet.
try {
userDelegate = new ZoomSDKRenderer(
m_pMeetingService,
g_zoom_unique_meeting_id,
userIdToSubscribe, // The UserID this delegate is responsible for
nullptr // Helper will be set later
);
} catch (const std::bad_alloc& e) {
std::cerr << "[RENDER_MGR] FATAL: new ZoomSDKRenderer failed for UserID " << userIdToSubscribe << ": " << e.what() << std::endl;
return;
} catch (const std::exception& e) {
std::cerr << "[RENDER_MGR] FATAL: new ZoomSDKRenderer exception for UserID " << userIdToSubscribe << ": " << e.what() << std::endl;
return;
}
if (!userDelegate) { return; }
// 2. Create the SDK's renderer helper object, associating your delegate with it.
// The SDK will call methods on 'userDelegate' via this helper.
SDKError err_create_helper = createRenderer(&sdkRendererHelper, userDelegate);
if (err_create_helper != SDKERR_SUCCESS || !sdkRendererHelper) {
std::cerr << "[RENDER_MGR] Failed to create IZoomSDKRenderer helper for UserID: " << userIdToSubscribe << ". Error: " << err_create_helper << std::endl;
delete userDelegate; // Clean up the delegate we allocated
return;
}
// 3. Now that the SDK helper is created, provide it to your delegate for reference.
userDelegate->SetRendererHelper(sdkRendererHelper);
// 4. Configure the SDK helper (e.g., resolution)
SDKError resolution_err = sdkRendererHelper->setRawDataResolution(ZoomSDKResolution_1080P); // Or your desired resolution
if (resolution_err != SDKERR_SUCCESS) {
std::cerr << "[RENDER_MGR] Warn: Failed to set resolution for UserID " << userIdToSubscribe << ", error: " << resolution_err << std::endl;
}
// 5. Subscribe the SDK helper to the specified user's video.
SDKError subErr = sdkRendererHelper->subscribe(userIdToSubscribe, RAW_DATA_TYPE_VIDEO);
if (subErr != SDKERR_SUCCESS) {
std::cerr << "[RENDER_MGR] Video subscription FAILED for UserID " << userIdToSubscribe << " with error: " << subErr << std::endl;
destroyRenderer(sdkRendererHelper); // Clean up the SDK-side helper
delete userDelegate; // Clean up our delegate
} else {
std::cout << "[RENDER_MGR] Video subscription SUCCEEDED for UserID " << userIdToSubscribe << "." << std::endl;
g_userVideoRenderHelpers[userIdToSubscribe] = sdkRendererHelper;
g_userVideoDelegates[userIdToSubscribe] = userDelegate;
}
}
It’ll subscribe to the first user, but always fails on the next user. This is what it logs:
[ZoomSDKRenderer] Renderer helper set for logical UserID: xxxxxxxx
[RENDER_MGR] Video subscription FAILED for UserID xxxxxxxx with error: 2
[ZoomSDKRenderer] onRendererBeDestroyed for UserID xxxxxxxx.
[ZoomSDKRenderer_DTOR] Destructor called for UserID: xxxxxxxx
[REC_CTRL] Subscription for xxxxxxxx likely failed based on map check.
Which gives an error of:
SDKERR_WRONG_USAGE (2)
Can anyone tell me what I might be doing wrong? Also, just for a sanity check, I am allowed to subscribe to multiple users raw data simultaneously via my headless zoom bot, correct?