# How to use Raw Data function: startRawRecording macOS?

**URL:** <https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827>\
**Category:** macOS\
**Created:** [July 14, 2023, 11:16am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827 "2023-07-14T11:16:24Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [July 14, 2023, 11:16am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/1 "2023-07-14T11:16:24Z")

</div>

**Description**  
I am trying to get the video streams from a meeting using this docs: [https://developers.zoom.us/docs/meeting-sdk/macos/raw-data/](https://developers.zoom.us/docs/meeting-sdk/macos/raw-data/)

And following this post:

> [@macOS SDK Raw Data Help/Examples?](https://devforum.zoom.us/t/macos-sdk-raw-data-help-examples/64525):
>
> Description Are there any examples of using raw data with the macOS SDK? I’ve been following the docs ([https://marketplace.zoom.us/docs/sdk/native-sdks/macos/raw-data/](https://marketplace.zoom.us/docs/sdk/native-sdks/macos/raw-data/)) and I’m stuck on: Once the recording has started, set up a ZoomSDKRenderer , set your ZoomSDKRendererDelegate as the delegate property, and subscribe to the user via the subscribe method. I’ve tried this after recording is started: ZoomSDKRenderer \*sdkRenderer = nil; ZoomSDKError e = [[[ZoomSDK sharedSDK] getRawDataControl…

My idea was to use the ZoomSDKSample Objective-C project from here: [https://developers.zoom.us/docs/meeting-sdk/macos/get-started/](https://developers.zoom.us/docs/meeting-sdk/macos/get-started/)

And add some Swift classes to do something similar of what is done in the post. I will include the Swift code using this: [Importing Swift into Objective-C | Apple Developer Documentation](https://developer.apple.com/documentation/swift/importing-swift-into-objective-c)

However I am struggling to do the next steps:

- **startRawRecording** , How do you trigger this function?

- where do you call this function?  
zoomSDKMeetingRecordController.startRawRecording()

- **subscribe** , How do you subscribe to the stream of each user?

- where do you call this function?  
zoomSDKRenderer.subscribe(userID, rawDataType:ZoomSDKRawDataType)

- How do I link the zoomSDKRenderer to this callback **onRawDataReceived**

**Which macOS Meeting SDK version**  
zoom-sdk-macos-5.14.11.19310

**Device:**

- Device: [e.g. Apple MacBook Pro (16-inch, Intel)]
- OS: [macOS Ventura 13.4.1]

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [July 17, 2023, 8:30am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/2 "2023-07-17T08:30:02Z")

</div>

@maltamirano , let me try to answer your questions as much as possible

However I am struggling to do the next steps:

- **startRawRecording** , How do you trigger this function?

There is a recording helper called `ZoomSDKMeetingRecordController`  
You can access `ZoomSDKMeetingRecordController` by getting it from the `ZoomSDKMeetingService` 's `getRecordController`. You can get ZoomSDKMeetingService from the ZoomSDK singleton object

- where do you call this function?

You would want to call it when you meet 2 criterial. When you are inmeeting, and when you have recording or host permission. I typically call it using a meeting status callback. This will ensure that I have definitely joined the meeting, hence the “inmeeting” status.

zoomSDKMeetingRecordController.startRawRecording()

- **subscribe** , How do you subscribe to the stream of each user?
- where do you call this function?  
zoomSDKRenderer.subscribe(userID, rawDataType:ZoomSDKRawDataType)
- How do I link the zoomSDKRenderer to this callback **onRawDataReceived**

I would create an instance of this interface `IZoomSDKRenderer` and `IZoomSDKRendererDelegate`

```auto
ZoomSDKRendererDelegate* videoSource = new ZoomSDKRendererDelegate();
IZoomSDKRenderer* videoHelper;

```

For my case I call this `videohelper`. The code is in c++ for windows, but it should be similarly implemented on macOS

I would call the code below after doing these things

- make sure i’m in meeting
- make sure i have recording or host permission
- call the `StartRawRecording()` method

` createRenderer(&videoHelper, videoSource);` //createRenderer is a provided method  
`videoHelper->subscribe(getUserID(), RAW_DATA_TYPE_VIDEO); }`

---

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [July 17, 2023, 11:34am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/3 "2023-07-17T11:34:09Z")

</div>

Hello @chunsiong.zoom

First things first, thanks for your help! I started following the steps you mentioned. Please see code below.

```auto
//-- Triggering startRawRecording --

 // Get ZoomSDKMeetingService object from the the ZoomSDK singleton object
 ZoomSDKMeetingService *meetingService = [[ZoomSDK sharedSDK] getMeetingService];

 // Get the ZoomSDKMeetingRecordController object from meetingService object
 ZoomSDKMeetingRecordController *recordController = [meetingService getRecordController];

//Start recording
 [recordController startRawRecording];

```

But I am stuck in this step: I typically call it using a meeting status callback.

- Which callback could I use to trigger the raw recording in order to see the **inmeeting** status?
- How do I hook the callback to the ongoing meeting?

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [July 18, 2023, 2:56am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/4 "2023-07-18T02:56:43Z")

</div>

- Which callback could I use to trigger the raw recording in order to see the **inmeeting** status?
- How do I hook the callback to the ongoing meeting?

On the main thread, you can assign an event to the meetingService. It goes something like this on

############### Main Thread (Windows C++ Code) ######################

`	meetingService->SetEvent(new MeetingServiceEventListener(&onMeetingJoined, &onMeetingEndsQuitApp, &onInMeeting));`

The methods `onMeetingJoined`, `onMeetingEndsQuitApp`, and `onInMeeting` are methods in the main thread. These will be called from the callback `onMeetingStatusChanged`

######################### code for MeetingServiceEventListener ######################

```auto
#include "MeetingServiceEventListener.h"
#include <rawdata/zoom_rawdata_api.h>
#include <iostream>

using namespace std;

MeetingServiceEventListener::MeetingServiceEventListener(void (*onMeetingStarts)(), void (*onMeetingEnds)(), void (*onInMeeting)())
{
	onMeetingEnds_ = onMeetingEnds;
	onMeetingStarts_ = onMeetingStarts;
	onInMeeting_ = onInMeeting;
}

void MeetingServiceEventListener::onMeetingStatusChanged(MeetingStatus status, int iResult)
{
	cout << "onMeetingStatusChanged: " << status << ", iResult: " << iResult << endl;
	switch (status)
	{
	case MEETING_FAIL_MEETING_NOT_EXIST:
		printf("Meeting doesn't exitst, check your Meeting Number.\n");
		break;

	case MEETING_STATUS_INMEETING:
		printf("onMeetingStatusChanged() In Meeting.\n");
		if (onInMeeting_) onInMeeting_();

		break;
	}

	if (status == MEETING_STATUS_ENDED && onMeetingEnds_) onMeetingEnds_();
}

void MeetingServiceEventListener::onMeetingStatisticsWarningNotification(StatisticsWarningType type)
{
	cout << "onMeetingStatisticsWarningNotification, type: " << type << endl;
}

void MeetingServiceEventListener::onMeetingParameterNotification(const MeetingParameter* meeting_param)
{
	cout << "onMeetingParameterNotification" <<endl;
	if (onMeetingStarts_) onMeetingStarts_();
}

void MeetingServiceEventListener::onSuspendParticipantsActivities()
{
	cout << "onSuspendParticipantsActivities" << endl;
}

```

---

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [July 25, 2023, 1:12pm UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/5 "2023-07-25T13:12:09Z")

</div>

Hello @chunsiong.tan  
I did the next steps to create the **renderer-object** ( **ZoomSDKRenderer** ) and to subscribe it to the video stream of one user.

I donwnloaded the **ZoomSDKSample** project from here: [Download | Meeting SDK | macOS](https://developers.zoom.us/docs/meeting-sdk/macos/get-started/download/)

Then I modified the file **ZMSDKMeetingStatusMgr.m**.  
I used the callback called **onLocalRecordingPrivilegeRequestStatus** to trigger the **raw-recording**.  
If the user that wants to record needs to ask for permission to the host, then to start the **local-recording** he will need to click 2 times the record button.  
The first time to get the permission and the 2nd to start the local-recording.  
However, I’m using the 1st click to trigger the **raw-recording** after he gets the privilege to record. See code below:

```auto
//Fired up when privileges are granted/denied to do local-recording or raw-recording
- (void) onLocalRecordingPrivilegeRequestStatus:(ZoomSDKRequestLocalRecordingStatus)status{
          
    //If I am authorized to local recoding then I will trigger raw data recording
    if(status == ZoomSDKRequestLocalRecordingStatus_Granted){
       
        //1. Start recording with recordController
           
         // Get ZoomSDKMeetingService object from the the ZoomSDK singleton object
        ZoomSDKMeetingService *meetingService = [[ZoomSDK sharedSDK] getMeetingService];

        // Get the ZoomSDKMeetingRecordController object from meetingService object
        ZoomSDKMeetingRecordController *recordController = [meetingService getRecordController];

        //Start raw recording
        ZoomSDKError rawRecordingError = [recordController startRawRecording];

```

After the **raw-recording** has started I’m creating the **renderer-object** , then getting the userID from any user, and subscribing the renderer to the video stream of that user. See code below:

```auto
if(rawRecordingError == ZoomSDKError_Success){
            
            //2. Subscribe to user stream with renderer
            
            //Creating the renderer getting a raw-controller from the sharedSDK singleton
            //and calling creatRender and passing pointer to renderer
            ZoomSDKRenderer *renderer = nil;
            ZoomSDKError rendererError = [[[ZoomSDK sharedSDK] getRawDataController] creatRender:&renderer];
            
            //Assigning the property delegate to be the same object so we can have the ZoomSDKRendererDelegate
            //callbacks in the same class
            renderer.delegate = self;
                        
            //Remove duplictaes from UserIds
            userIdsNoDuplicates = [userIds valueForKeyPath:@"@distinctUnionOfObjects.self"];
            
            //Subscribing renderer to the active user
            int userID = [[userIdsNoDuplicates objectAtIndex:1] integerValue];
            ZoomSDKError subscribeError = [renderer subscribe:userID rawDataType:ZoomSDKRawDataType_Video];
                  
            if(subscribeError == ZoomSDKError_Success){
                NSLog(@">>renderer subscribed!!");
                //We will trigger onRawDataReceived
            }
                        
        }
        
    }    
    
}        

```

To implement the callbacks used during the raw-recording I added the protocol **ZoomSDKRendererDelegate** to the header file **ZMSDKMeetingStatusMgr.h**. See code below:

```auto
@interface ZMSDKMeetingStatusMgr : NSObject <ZoomSDKMeetingServiceDelegate,ZoomSDKMeetingActionControllerDelegate,ZoomSDKWebinarControllerDelegate,ZoomSDKMeetingRecordDelegate,ZoomSDKRendererDelegate>
{
    ZMSDKMainWindowController* _mainWindowController;
    ZoomSDKMeetingService* _meetingService;
    
    //To store user ids for raw-recording
    NSMutableArray *userIds;
    NSMutableArray *userIdsNoDuplicates;

}
- (id)initWithWindowController:(ZMSDKMainWindowController*)mainWindowController;
@end

```

Finally, I implemented a callback ( **onRawDataReceived** ) that is called after the raw-recording hast started in the file: **ZMSDKMeetingStatusMgr.m**

```auto
#pragma mark -- ZoomSDKRendererDelegate

//3. Create ZoomSDKRendererDelegate to manage raw recording events

// Fired after the renderer is subscribed to the stream of an user
- (void)onRawDataReceived:(ZoomSDKYUVRawDataI420*)data {
   NSLog(@">>Hola from ZMSDKMeetingStatusMgr.m - onRawDataReceived!!");
}

```

To get the user-ids I’m using the callback **onVideoStatusChange** from **ZoomSDKMeetingActionControllerDelegate**. See code below:

```auto
- (void)onVideoStatusChange:(ZoomSDKVideoStatus)videoStatus UserID:(unsigned int)userID {
    
    if([ZMSDKCommonHelper sharedInstance].isUseCutomizeUI)
        [[ZMSDKConfUIMgr sharedConfUIMgr].userHelper onVideoStatusChange:videoStatus UserID:userID];
    
    //Fired when any user hide/show video
    NSLog(@">>Hola from ZMSDKMeetingStatusMgr.m - onVideoStatusChange!!");
    NSLog(@"userID: %d\n", userID );
    
    //Save userID
    [userIds addObject: [NSNumber numberWithUnsignedInteger: userID]];
    
}

```

Thanks for your help!  
🙂

---

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [July 25, 2023, 2:12pm UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/6 "2023-07-25T14:12:48Z")

</div>

Hello again @chunsiong.zoom  
By the way, I tried to use Swift in the **ZoomSDKSample** project from here: [Download | Meeting SDK | macOS](https://developers.zoom.us/docs/meeting-sdk/macos/get-started/download/) to create the **renderer-object** and subscribe to a video stream.

I integrated the Swift file using an interface described here:

> **[Importing Swift into Objective-C | Apple Developer Documentation](https://developer.apple.com/documentation/swift/importing-swift-into-objective-c)**
>
> Access Swift types and declarations from within your Objective-C codebase.

And adding this line to the file: **ZMSDKMeetingStatusMgr.m**

```auto
//Interfce to see the Swift classes created by Xcode
#import "ZoomSDKSample_intel-Swift.h"

```

However, when I was passing the pointer to the function **creatRender** the function finished successfully but the object **renderer-object** was **nil**.  
Using the function creatRender was not a problem in Objective-C because the pointer worked fine, maybe because the creatRender function is designed to work with Objective-C?

Then the **subscribe** function failed because the renderer-object was **nil** even if creatRender was successful.

Here I am creating the **Swift** object called **rendererWrapper** to later create the **renderer-object** ( **ZoomSDKRenderer** ).

I am passing the **sharedSDK** (ZoomSDK) to **rendererWrapper** (ZoomRendererWrapper). I added the next code to the file **ZMSDKMeetingStatusMgr.m**.

```auto
//Fired up when privileges are granted/denied to do local-recording or raw-recording
- (void) onLocalRecordingPrivilegeRequestStatus:(ZoomSDKRequestLocalRecordingStatus)status{
          
    //If I am authorized to local recoding then I will trigger raw data recording
    if(status == ZoomSDKRequestLocalRecordingStatus_Granted){
       
        //1. Start recording with recordController
        
        //SWIFT - Start recording and Create a renderer
        ZoomRendererWrapper *rendererWrapper = [[ZoomRendererWrapper alloc] init];

        [rendererWrapper initWithSharedSDKWithSharedSDK:[ZoomSDK sharedSDK]];

```

This is the Swift implementation of the **ZoomRendererWrapper**

```auto
@objc class ZoomRendererWrapper: NSObject {

    var meetingService: ZoomSDKMeetingService?
    var recordController: ZoomSDKMeetingRecordController?
    var rawDataController: ZoomSDKRawDataController?
    private(set) var renderer: ZoomSDKRenderer?
    var rendererPointer: AutoreleasingUnsafeMutablePointer<ZoomSDKRenderer?>?
    var error: ZoomSDKError?

    .
    .
    .

@objc func initWithSharedSDK(sharedSDK: ZoomSDK){
        
        //Start recording
        meetingService = sharedSDK.getMeetingService()
        recordController = meetingService?.getRecordController()
        error = recordController?.startRawRecording()
        
        //Create renderer if startRawRecording OK
        if(error == ZoomSDKError_Success){
            rawDataController = sharedSDK.getRawDataController()
            renderer = ZoomSDKRenderer()          
           
            rendererPointer = .init(&renderer)
           
            var rendererError: ZoomSDKError?

            rendererError = rawDataController?.creatRender(rendererPointer)
            
            if(rendererError == ZoomSDKError_Success){
                print(">>initWithSharedSDK renderer created!")
            }
        }
        
    }

```

During a meeting I was able to start the recording with the Swift object **ZoomRendererWrapper**. However, **creatRender** created a **ZoomSDKRenderer** object with **nil** value.

Here an example when debugging with Xcode:

 ![renderer-nil](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/3/5/353ca28f88b4c2e092152efbcccea0ff5622ec1c.png)

Do you know how could I use Swift to create the renderer ( **ZoomSDKRenderer** )?  
Do you recommend me to use Objective-C insetad of Swift?

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [July 26, 2023, 3:03am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/7 "2023-07-26T03:03:37Z")

</div>

@maltamirano I’m not familiar with MacOS and objective C / Swift, but let me try my best to help

`rendererError = rawDataController?.creatRender(rendererPointer)`  
Is there a specific renderError given?

---

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [July 26, 2023, 8:25am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/8 "2023-07-26T08:25:29Z")

</div>

Hello @chunsiong.zoom

When running this in Swift:

```auto
rendererError = rawDataController?.creatRender(rendererPointer)

```

The results is that **rendererError** is equal to **ZoomSDKError\_Success** and the renderer is created but in the debugger the value of the renderer is **nil** as shown in the previous image.

---

<div class="post-metadata">

**Author:** ![chunsiong.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/chunsiong.zoom/32/35488_2.png) [@chunsiong.zoom](https://devforum.zoom.us/u/chunsiong.zoom)\
**Post date:** [July 26, 2023, 8:48am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/9 "2023-07-26T08:48:42Z")

</div>

@maltamirano

It does not return nil in objective C right?  
If thats the case, let me raise this internally

One last thing, does this happen in newer version of the SDK as well? The 5.15.x

---

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [July 28, 2023, 11:08am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/10 "2023-07-28T11:08:19Z")

</div>

@chunsiong.zoom  
When I create the renderer in Objective-C I successfully get the renderer object .

However when I try to do the same with Swift I get a renderer=nil.  
Maybe there is a problem with the pointer passed to the function **creatRender**

I tried also with **zoom-sdk-macos-5.15.5.20804** and I got the same error.

---

<div class="post-metadata">

**Author:** ![jon.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/jon.zoom/32/13495_2.png) [@jon.zoom](https://devforum.zoom.us/u/jon.zoom)\
**Post date:** [August 14, 2023, 5:17pm UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/11 "2023-08-14T17:17:58Z")

</div>

Hi @maltamirano , thank you for your patience as we looked into this.

Since you are using the SDK sample app and have made local modifications to it, can you please provide a diff of the changes so we can ensure we’re on the same page? **Please remove any private information such as credentials or other sensitive data from the diff before posting it**.

Thanks!

---

<div class="post-metadata">

**Author:** ![maltamirano](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maltamirano/32/50044_2.png) [@maltamirano](https://devforum.zoom.us/u/maltamirano)\
**Post date:** [August 15, 2023, 8:07am UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/12 "2023-08-15T08:07:55Z")

</div>

Hello @jon.zoom, thanks for your reply. However, I decided to continue working with the **SDK-sample** with Objective-C instead of Swift. I choose Objective-C over Swift for some reasons:

- The **ZoomErrors** are not visible when debugging in Xcode, maybe because it is an Objective-C project and the inrterface-header (the translation of Swift into Objective-C objects) blocks the visibility of the Swift objects in runtime.
- We need to build the project to see the new functions from a Swift class for autocomplete in Xcode. The interface-header only updates after building the project.

I called the **interface-header** to the translation that Xcode does automatically using an autogenerated header that you must include in your Objective-C files to use Swift classes. See image:

 ![image](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/7/d/7dbd2796ab69d4732a34023007df6ca55bd7abf4.png)

More info about this interface-header here: [Importing Swift into Objective-C | Apple Developer Documentation](https://developer.apple.com/documentation/swift/importing-swift-into-objective-c)

Thanks for your help!

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/6/1/614bdd549b610bbaa46ff934617683a02bdaa03c.png) [@system](https://devforum.zoom.us/u/system)\
**Post date:** [September 14, 2023, 6:08pm UTC](https://devforum.zoom.us/t/how-to-use-raw-data-function-startrawrecording-macos/91827/13 "2023-09-14T18:08:39Z")

</div>

Closed on September 14, 2023, 6:08pm UTC

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
