# Start Meeting inside linux bot

**URL:** <https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916>\
**Category:** Meeting SDK\
**Created:** [January 20, 2025, 7:11am UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916 "2025-01-20T07:11:04Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [January 20, 2025, 7:11am UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/1 "2025-01-20T07:11:04Z")

</div>

@chunsiong.zoom @amanda-recallai  
I created bot based on [GitHub - zoom/meetingsdk-linux-raw-recording-sample](https://github.com/zoom/meetingsdk-linux-raw-recording-sample)  
So, in documentation I find how I can start meeting using my bot [Meetings | MSDK | Linux - Zoom Developers](https://developers.zoom.us/docs/meeting-sdk/linux/get-started/meetings/#start-a-meeting)  
But, I don’t understand what is `vanityID` and `customer_key`  
I tried to send as `vanityID` user PMI and ZAK token as `customer_key`, but I think I make something wrong, cause I get `Segmentation fault (core dumped) ./meetingSDKDemo`  
I change StartMeeting function like this

```auto
void StartMeeting()
{
	std::cout<<"START MEETING FUNCTION"<<std::endl;
	ZOOM_SDK_NAMESPACE::StartParam startParam;
	startParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_NORMALUSER;
	startParam.param.normaluserStart.vanityID = " **********".c_str();
	startParam.param.normaluserStart.customer_key = token.c_str();
	startParam.param.normaluserStart.isVideoOff = false;
	startParam.param.normaluserStart.isAudioOff = false;
	std::cout<<"START MEETING FUNCTION params added succsessfully"<<std::endl;

	ZOOM_SDK_NAMESPACE::SDKError err = m_pMeetingService->Start(startParam);
	std::cout<<"START MEETING FUNCTION Start"<<std::endl;
	if (SDKError::SDKERR_SUCCESS == err)
	{
		std::cerr << "StartMeeting:success " << std::endl;
	}
	else
	{
		std::cerr << "StartMeeting:error " << std::endl;
	}
}

```

and call it like this

```auto
int main(int argc, char *argv[])
{

	ReadTEXTSettings();
	
	InitMeetingSDK();
	AuthMeetingSDK();
	initAppSettings();
	StartMeeting();
	loop = g_main_loop_new(NULL, FALSE);
	// add source to default context
	g_timeout_add(1000, timeout_callback, loop);
	g_main_loop_run(loop);
	return 0;
}

```

---

<div class="post-metadata">

**Author:** ![amanda-recallai](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/amanda-recallai/32/44747_2.png) [@amanda-recallai](https://devforum.zoom.us/u/amanda-recallai)\
**Post date:** [January 21, 2025, 3:26am UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/2 "2025-01-21T03:26:26Z")

</div>

Hi @emotioniq, thanks for the ping!

It looks like you’re using the [zoom/meetingsdk-linux-raw-recording-sample](https://github.com/zoom/meetingsdk-linux-raw-recording-sample) template repo.

To quickly answer your questions, the `vanityID` is an id associated with your Zoom organization ([docs](https://marketplacefront.zoom.us/sdk/meeting/android/us/zoom/sdk/StartMeetingParams.html#vanityID)) and the `customer_key` should be the participant id ([docs](https://marketplacefront.zoom.us/sdk/meeting/android/us/zoom/sdk/MeetingOptions.html#customer_key))

That being said, you don’t actually need the `vanityID` and `customer_key` to start using the Zoom meeting bot because both of these fields are nullable

Another option is [Recall.ai](https://www.recall.ai/). It’s a simple 3rd party API that lets you use meeting bots to get raw audio/video from meetings without you needing to spend months to build, scale and maintain these bots. You can deploy a bot to a zoom meeting in under 5 minutes with using a simple API

Let me know if you have any questions!

---

<div class="post-metadata">

**Author:** ![noah.duncan](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/noah.duncan/32/51124_2.png) [@noah.duncan](https://devforum.zoom.us/u/noah.duncan)\
**Post date:** [January 22, 2025, 9:51pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/3 "2025-01-22T21:51:09Z")

</div>

Hi @emotioniq

I’m building an open source API for meeting bots called Attendee, that provides similar functionality to Recall.

Check out the github here: [GitHub - noah-duncan/attendee: Meeting Bots made easy](https://github.com/noah-duncan/attendee).  
And the hosted instance here: [https://app.attendee.dev/](https://app.attendee.dev/)

It’s another option if you’re looking for a way to avoid the complexity of working directly with the [Meeting SDK](https://developers.zoom.us/docs/meeting-sdk) and running the bots.

Attendee uses the Linux SDK under the hood to power its Zoom bots, so the source code can provide a good example of how to use the Meeting SDK.

---

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [January 23, 2025, 8:05pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/4 "2025-01-23T20:05:05Z")

</div>

@amanda-recallai @chunsiong.zoom Thanks! So, I have another question. Where I need to call `StartMeeting()` function inside `meeting_sdk_demo.cpp`

I tried to call it like this

```auto
void OnAuthenticationComplete()
{
	
	std::cout << "OnAuthenticationComplete" << std::endl;
	// 
	StartMeeting();
	JoinMeeting();
}

```

but it stuck here.  
Now, my `StartMeeting()` function looks like this

```auto
void StartMeeting()
{
	std::cout<<"START MEETING FUNCTION"<<std::endl;
	ZOOM_SDK_NAMESPACE::StartParam startParam;
	startParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_NORMALUSER;
	startParam.param.normaluserStart.vanityID = NULL;
	startParam.param.normaluserStart.customer_key = NULL;
	startParam.param.normaluserStart.isVideoOff = false;
	startParam.param.normaluserStart.isAudioOff = false;
	std::cout<<"START MEETING FUNCTION params added succsessfully"<<std::endl;

	ZOOM_SDK_NAMESPACE::SDKError err = m_pMeetingService->Start(startParam);
	std::cout<<"START MEETING FUNCTION Start"<<std::endl;
	if (SDKError::SDKERR_SUCCESS == err)
	{
		std::cerr << "StartMeeting:success " << std::endl;
	}
	else
	{
		std::cerr << "StartMeeting:error " << std::endl;
	}
}

```

in config.txt

```auto
meeting_number: " ***********"
token: #here I send ZAK token#
meeting_password: " *******"
recording_token: " ***********"
GetVideoRawData: "true"
GetAudioRawData: "true"
SendVideoRawData: "false"
SendAudioRawData: "false"

```

Logs looks like

```auto
-- Using the single-header code from /app/demo/build/_deps/json-src/single_include/
ln: failed to create symbolic link 'libmeetingsdk.so.1': File exists
-- Configuring done
-- Generating done
-- Build files have been written to: /app/demo/build
Consolidate compiler generated dependencies of target meetingSDKDemo
[100%] Built target meetingSDKDemo
unix:path=/run/dbus/system_bus_socket,guid=959dd410e40a3cb27bf4814b6792a072
Adding user `root' to group `pulse-access' ...
Adding user root to group pulse-access
Done.
Adding user `root' to group `audio' ...
Adding user root to group audio
Done.
cp: target '/root/.config/pulse/' is not a directory
W: [pulseaudio] main.c: This program is not intended to be run as root (unless --system is specified).
19
mkdir: cannot create directory '/root/.config': File exists
getpath
self path: /app/demo/bin
Readfile success.
Reading..meeting_number: " **********"
Reading.. token: " **************"
Reading.. meeting_password: " **********"
Reading.. recording_token: " ************"
Reading.. GetVideoRawData: "true"
Reading.. GetAudioRawData: "true"
Reading.. SendVideoRawData: "false"
Reading.. SendAudioRawData: "false" HostUser: " ***********"
Reading.. authToken: " ************"
Meeting Number: ************
authToken: ***********
Token: **********
meeting_password: *********
recording_token: ********
GetVideoRawData before parsing is : true
GetVideoRawData: 1
GetAudioRawData before parsing is : true
GetAudioRawData: 1
SendVideoRawData before parsing is : false
SendVideoRawData: 0
SendAudioRawData before parsing is : false HostUser: ***********
SendAudioRawData: 0
directory of config file: /app/demo/bin/config.txt
Init meetingSdk:success
AuthServiceEventListener added.
AuthService created.
AuthSDK:token extracted from config file *******************

```

---

<div class="post-metadata">

**Author:** ![amanda-recallai](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/amanda-recallai/32/44747_2.png) [@amanda-recallai](https://devforum.zoom.us/u/amanda-recallai)\
**Post date:** [January 25, 2025, 12:26am UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/5 "2025-01-25T00:26:26Z")

</div>

Hey @emotioniq I noticed that you’re calling both `StartMeeting` and `JoinMeeting` in `OnAuthenticationComplete`. Only one of these functions should be called, depending on whether you want to start a new meeting or join an existing one. Is there a reason that you’re calling them both in the same function right now?

---

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [January 25, 2025, 1:32pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/6 "2025-01-25T13:32:30Z")

</div>

@amanda-recallai Yeah, I’m creating scheduled meeting and want for bot will start meeting and after this connect to the meeting and start raw recording

---

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [January 25, 2025, 1:41pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/7 "2025-01-25T13:41:16Z")

</div>

@amanda-recallai First I try to start meeting and doing like this

```c++
void StartMeeting()
{
	std::cerr << "!!!!!!Start Meeting" << std::endl;
	SDKError err2(SDKError::SDKERR_SUCCESS);

	// // try to create the meetingservice object,
	// // this object will be used to join the meeting
	if ((err2 = CreateMeetingService(&m_pMeetingService)) != SDKError::SDKERR_SUCCESS)
	{
	};

	std::cout<<"START MEETING FUNCTION"<<std::endl;
	ZOOM_SDK_NAMESPACE::StartParam startParam;
	startParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_NORMALUSER;
	startParam.param.normaluserStart.vanityID = NULL;
	startParam.param.normaluserStart.customer_key = NULL;
	startParam.param.normaluserStart.isVideoOff = false;
	startParam.param.normaluserStart.isAudioOff = false;
	std::cout<<"START MEETING FUNCTION params added succsessfully"<<std::endl;

	if (!m_pMeetingService) {
		std::cerr << "m_pMeetingService is null!" << std::endl;
		return;
	}
	ZOOM_SDK_NAMESPACE::SDKError err = m_pMeetingService->Start(startParam);
	std::cout << "StartMeeting result: " << err << std::endl;
	std::cout<<"START MEETING FUNCTION Start"<<std::endl;
	if (SDKError::SDKERR_SUCCESS == err)
	{
		std::cerr << "StartMeeting:success " << std::endl;
	}
	else
	{
		std::cerr << "StartMeeting:error " << std::endl;
	}

}

```

but in logs i get this

```auto
backend-1 | ISTART MEETING FUNCTION
backend-1 | START MEETING FUNCTION params added succsessfully
backend-1 | 4StartMeeting result: 2
backend-1 | START MEETING FUNCTION Start
backend-1 | StartMeeting:error

```

result `2` is equal to `SDKERR_WRONG_USAGE,///<Incorrect usage of the feature. `

---

<div class="post-metadata">

**Author:** ![amanda-recallai](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/amanda-recallai/32/44747_2.png) [@amanda-recallai](https://devforum.zoom.us/u/amanda-recallai)\
**Post date:** [January 30, 2025, 12:30am UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/8 "2025-01-30T00:30:34Z")

</div>

Hi @emotioniq, it looks like the main cause of the `SDKERR_WRONG_USAGE` error is [when you call a method at the wrong time](https://arc.net/l/quote/lbiqljxj)

Because of this, it makes me think that the error is being thrown because the SDK function is being called at the wrong time. You can try logging to see which function is being thrown here and also try following [zoom/meetingsdk-linux-raw-recording-sample](https://github.com/zoom/meetingsdk-linux-raw-recording-sample) to guide you along the way and see how to initialize and run the start function

---

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [January 30, 2025, 7:45pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/9 "2025-01-30T19:45:31Z")

</div>

@chunsiong.zoom Maybe you know how to solve this problem?

---

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [February 9, 2025, 4:09pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/10 "2025-02-09T16:09:19Z")

</div>

@amanda-recallai @chunsiong.zoom Okay, I solve part of the problem, now meeting is started, and I did it like this

```c++
void OnAuthenticationComplete()
{
    std::cout << "OnAuthenticationComplete" << std::endl;
    
    // Create MeetingService and setup event listeners as in JoinMeeting
    SDKError err2(SDKError::SDKERR_SUCCESS);
    if ((err2 = CreateMeetingService(&m_pMeetingService)) != SDKError::SDKERR_SUCCESS)
    {
        // Handle error
    };
    std::cerr << "MeetingService created." << std::endl;

    CreateSettingService(&m_pSettingService);

    m_pMeetingService->SetEvent(new MeetingServiceEventListener(&onMeetingJoined, &onMeetingEndsQuitApp, &onInMeeting));
    m_pParticipantsController = m_pMeetingService->GetMeetingParticipantsController();
    m_pParticipantsController->SetEvent(new MeetingParticipantsCtrlEventListener(&onIsHost, &onIsCoHost));
    m_pRecordController = m_pMeetingService->GetMeetingRecordingController();
    m_pRecordController->SetEvent(new MeetingRecordingCtrlEventListener(&onIsGivenRecordingPermission));

    IMeetingReminderController *meetingremindercontroller = m_pMeetingService->GetMeetingReminderController();
    MeetingReminderEventListener *meetingremindereventlistener = new MeetingReminderEventListener();
    meetingremindercontroller->SetEvent(meetingremindereventlistener);

    // Now start the meeting
    StartMeeting();
}

```

My `StartMeeting()` function

```c++
void StartMeeting()
{
    ZOOM_SDK_NAMESPACE::StartParam startParam;
    startParam.userType = ZOOM_SDK_NAMESPACE::SDK_UT_WITHOUT_LOGIN;

    ZOOM_SDK_NAMESPACE::StartParam4WithoutLogin& normalUserStart = startParam.param.withoutloginStart;

    normalUserStart.userName = "EmotionIQ Bot";
	normalUserStart.userZAK = userZAK.c_str();
	normalUserStart.zoomuserType = ZOOM_SDK_NAMESPACE::ZoomUserType_APIUSER;
    normalUserStart.meetingNumber = std::stoull(meeting_number); // 0 for instant meeting
    normalUserStart.vanityID = NULL;
    normalUserStart.customer_key = NULL;
    normalUserStart.isVideoOff = false;
    normalUserStart.isAudioOff = false;

    ZOOM_SDK_NAMESPACE::SDKError err = m_pMeetingService->Start(startParam);
    if (err == ZOOM_SDK_NAMESPACE::SDKERR_SUCCESS)
    {
        std::cerr << "StartMeeting: Success" << std::endl;
    }
    else
    {
        std::cerr << "StartMeeting: Error " << err << std::endl;
    }
}

```

And after this I get this

```auto
backend-1 | 0MeetingService created.
backend-1 | Settingservice created.
backend-1 | .Auth succeeded: JWT.
backend-1 | OnAuthenticationComplete
backend-1 | StartMeeting: Success
backend-1 | AonLoginReturnWithReason: 0
backend-1 | onMeetingStatusChanged: 1, iResult: 0
backend-1 | EConnect to the meeting server status.
backend-1 | onMeetingParameterNotification
backend-1 | sJoining Meeting...
backend-1 | !!!!!!!!!!!!!! USER JOINED !!!!!!!!!!!!!!
backend-1 | !!!!!!!!!!!!!! LIST OF USERS !!!!!!!!!!!!!!!
backend-1 | 16778240
backend-1 | W/app/demo/run.sh: line 4: 151 Segmentation fault (core dumped) ./meetingSDKDemo

```

This `!!!!!!!!!!!!!! USER JOINED !!!!!!!!!!!!!!` I getting from

```auto
void MeetingParticipantsCtrlEventListener::onUserJoin(IList<unsigned int >* lstUserID, const zchar_t* strUserList ){
    std::cout<<"!!!!!!!!!!!!!! USER JOINED !!!!!!!!!!!!!!"<<std::endl;
    std::cout<<"!!!!!!!!!!!!!! LIST OF USERS !!!!!!!!!!!!!!!"<<std::endl;
    for(int i=0; i<lstUserID->GetCount(); i++) {
        std::cout<<lstUserID->GetItem(i)<<std::endl;
    }
    CheckAndStartRawRecordingOnUserJoin(true, true);

}

```

The main problem is `/app/demo/run.sh: line 4: 151 Segmentation fault (core dumped) ./meetingSDKDemo`

---

<div class="post-metadata">

**Author:** ![emotioniq](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/emotioniq/32/62111_2.png) [@emotioniq](https://devforum.zoom.us/u/emotioniq)\
**Post date:** [February 9, 2025, 4:15pm UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/11 "2025-02-09T16:15:31Z")

</div>

@amanda-recallai @chunsiong.zoom

### Problem 1

And also I have another problem. Usually I create scheduled meeting like

 ![Screenshot 2025-02-09 at 19.10.34](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/a/8/a8488e73c1e64ac372ba258d25e0aefeb64d775e.png)

However, when I start the bot, it doesn’t wait for start\_time and tries to start the conference immediately.

### Problem 2

In addition, after the bot starts the conference and connects to it, I want it to wait for the user(not the host) and only then start recording audio and video. I would like to know if this is possible?

I already have one bot that does all the necessary steps to process raw data. However, it only knows how to connect to an already created conference.

---

<div class="post-metadata">

**Author:** ![amanda-recallai](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/amanda-recallai/32/44747_2.png) [@amanda-recallai](https://devforum.zoom.us/u/amanda-recallai)\
**Post date:** [February 11, 2025, 12:59am UTC](https://devforum.zoom.us/t/start-meeting-inside-linux-bot/124916/12 "2025-02-11T00:59:00Z")

</div>

> However, when I start the bot, it doesn’t wait for start\_time and tries to start the conference immediately.

If you want your bot to join a call at a scheduled time, this will be something you need to implement on your end. You’ll want to utilize your own logic (e.g. a cron job) to launch a bot at the correct time.

> In addition, after the bot starts the conference and connects to it, I want it to wait for the user(not the host) and only then start recording audio and video. I would like to know if this is possible?

Before your bot is able to record a meeting, they’ll need to get permission from the host of the meeting. Non-host participants can’t grant recording permission to the bot.

However, if you’re able to provision the bot with a join token for local recording, then the bot will be able to join the call and start recording automatically without needing to ask for permission.
