Skip to content

Latest commit

History

112 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Online Documentation (Recommended)

🌐 https://insta360develop.github.io/Insta360-Developer_Docs/

⚠️ If the above Pages site fails to load (access to github.io is unstable on some networks), you may directly browse the Markdown documents at the link below: https://github.com/Insta360Develop/Insta360-Developer_Docs

⚠️ This repository will no longer be maintained moving forward; all subsequent content will be migrated to the aforementioned Online Documentation.

Note:

Currently on V1.9.2 branch. To view other versions, please switch branches.

How to get?

Please visit https://www.insta360.com/sdk/apply to apply for the latest SDK.

Support

Developers' Page: https://www.insta360.com/developer/home
Insta360 Enterprise: https://www.insta360.com/enterprise
Issue Report: https://insta.jinshuju.com/f/hZ4aMW

Overview

The iOS SDK is mainly used to connect, set and obtain camera parameters, control the camera to take pictures and record, download files, upgrade firmware, and support video and image export, etc.

Supported models: X5, X4 Air, X4, X3, ONE X2, ONE X, ONE RS, ONE RS 1-Inch.

Table of contents

Environmental preparation

  1. Locate the following dependency libraries in the provided sample project and drag them into the target project:
INSCoreMedia.xcframework
INSCameraServiceSDK.xcframework
INSCameraSDK.xcframework
SSZipArchive.xcframework
  1. In Xcode's Build Settings, add the build option TO_B_SDK=1, and then try compiling to confirm that the project can build normally.

Camera SDK Function

Connection Module

Determine if the Camera is Connected

Obtain the camera's connection status through the following methods:

INSCameraManager.socket().cameraState

If the returned status is INSCameraStateConnected, it indicates a successful connection has been established. The status is defined as follows:

INSCameraManager.socket().cameraState
// There are the following states in total:typedefNS_ENUM(NSUInteger, INSCameraState) {
/// an insta360 camera is found, but not connected, will not response
INSCameraStateFound,
/// an insta360 camera is synchronized, but not connected, will not response
INSCameraStateSynchronized,
/// the nano device is connected, app is able to send requests
INSCameraStateConnected,
/// connect failed
INSCameraStateConnectFailed,
/// default state, no insta360 camera is found
INSCameraStateNoConnection,
};

Connecting the Camera

Connect the Camera via Wi-Fi

  1. Connection

After connecting the camera to the phone via Wi-Fi, you can invoke the interface in INSCameraSDK to establish a connection. This interface uses the singleton pattern: an instance is created upon the first call, and subsequent calls reuse the same instance.

INSCameraManager.socket().setup()
  1. Disconnection

When you need to disconnect from the camera, call the following interface:

INSCameraManager.socket().shutdown()

Connect the Camera via Bluetooth

Note: Large data transfers are not supported when connected via Bluetooth. Therefore, functions involving the transfer of large data files are not supported.

Unsupported functions: Preview, retrieve supported list, download files, firmware upgrade, playback, export images.

  1. Search for Bluetooth Devices

Call the following method to scan Bluetooth devices

INSBluetoothManager().scanCameras
  1. Establish a Bluetooth Connection

Establish a Bluetooth connection using the following interface:

- (id)connectDevice:(INSBluetoothDevice *)device
completion:(void (^)(NSError * _Nullable))completion;
  1. Disconnect Bluetooth
- (void)disconnectDevice:(INSBluetoothDevice *)device;

Send Heartbeat Packets to the Camera

While maintaining a connection with the camera, it is necessary to periodically send heartbeat packets to the camera. Otherwise, the camera will assume the connection has been lost, resulting in interrupted previews or invalid commands.

Typically, if no heartbeat is received within 30 seconds, the camera will actively disconnect.

Therefore, in scenarios requiring prolonged sessions—such as entering preview or recording modes—the application should continuously send heartbeat packets.

The following code example demonstrates how to use GCDTimer to send heartbeat commands at regular intervals, every 0.5 seconds:

funcstartSendingHeartbeats(){letcommandManager=INSCameraManager.shared().commandManagerprint("Heartbeat task started")// Send a heartbeat every 0.5 seconds to ensure the connection remains active.GCDTimer.shared.scheduledDispatchTimer(WithTimerName: "HeartbeatsTimer",timeInterval: 0.5,queue: DispatchQueue.main,repeats: true){commandManager.sendHeartbeats(with: nil)print("Heartbeat sent")}}

Wi-Fi Control Module

Wi-Fi Information Retrieval

After establishing a Bluetooth connection, call the interface to retrieve Wi-Fi information. The sample code is as follows:

letbluetoothManager=INSBluetoothManager()bluetoothManager.command(by: peripheral)?.getOptionsWithTypes(optionTypes){(err,options,successTypes)inguardletoptions=optionselse{self?.showAlert(row.tag!,String(describing: err))return}self?.showAlert("ssid:\(String(describing: options.wifiInfo?.ssid)) pw:\(String(describing: options.wifiInfo?.password))",String(describing: err))}

Wi-Fi Country Codes and Camera Wi-Fi Channel Settings

⚠️ Note: After setting the country code, you must restart the camera's Wi-Fi for the settings to take effect. The channel depends on the country code, with each country corresponding to a different channel list. After restarting the camera, retrieve the channel list again to switch channels (both Bluetooth and Wi-Fi connections are supported).

  1. Retrieve the Current Country Code
func getWifiCountryCode() {
let optionTypes = [
NSNumber(value: INSCameraOptionsType.wifiChannelList.rawValue)
]
INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { err, options, successTypes in
guard let options = options else {
print("ERROR: \(err?.localizedDescription ?? "Unknown error")")
return
}
self.printWifiChannelList(options.wifiChannelList)
}
}

Note:

  • Use getOptionsWithTypes to retrieve the camera's current Wi-Fi channel list and country code information.
  • The callback returns options.wifiChannelList, which can be viewed using a custom print function.
  1. Set the Country Code
func setCountryCode(to countryCode: String = "JP") {
let optionTypes = [
NSNumber(value: INSCameraOptionsType.wifiChannelList.rawValue)
]
let wifiChannelList = INSCameraWifiChannelList(countryCode: countryCode)
let options = INSCameraOptions()
options.wifiChannelList = wifiChannelList
INSCameraManager.shared().commandManager.setOptions(options, forTypes: optionTypes) { error, types in
if let error = error {
print("Failed to set country code: \(error.localizedDescription)")
} else {
print("Country code set to \(countryCode). ⚠️ Wi-Fi restart required to apply changes.")
}
}
}

Note:

  • The countryCode parameter supports any ISO country code, such as “JP”, ‘US’, or “CN”.
  • After configuration, restart the camera's Wi-Fi for changes to take effect.
  • The callback can be used to confirm whether the settings were applied successfully.
  1. Restart Wi-Fi and Set the Channel.
INSCameraManager.shared().commandManager.resetCameraWifi(channel)

Information Retrieval Module

Information Retrieval

Camera Models

INSCameraManager.shared().currentCamera?.name

Camera Serial Number

The code can be called after establishing a connection with the camera

INSCameraManager.shared().currentCamera?.serialNumber

Firmware Version Number

INSCameraManager.shared().currentCamera?.firmwareRevision

Camera Activation Time

letoptionTypes=[NSNumber(value:INSCameraOptionsType.activateTime.rawValue),];
INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes){(err, options, successTypes)inguardlet options = options else{self.showAlert("get options",String(describing: err))return}
// Activation time
letformatter=DateFormatter()
formatter.dateFormat ="yyyy-MM-dd HH:mm:ss.SSS"letdate=Date(timeIntervalSince1970:Double(options.activateTime /1000))print("date :\(date)")}

SD Card Total Space (Total Capacity Size) and Free Space (Available Capacity Size)

@interfaceINSCameraStorageStatus : NSObject//SDcardstatus@property (nonatomic) INSCameraCardStatecardState;//Availablecapacitysize@property (nonatomic) int64_tfreeSpace;//Totalcapacitysize@property (nonatomic) int64_ttotalSpace;//TODO: RestrictaccesstocertainSDKs@property (nonatomic) INSStorageCardLocationcardLocation;@endletoptionTypes= [
NSNumber(value: INSCameraOptionsType.storageState.rawValue),
];
INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) inguardletoptions=optionselse {
self.showAlert("get options", String(describing: err))
return
}
}

SD Card Status

letoptionTypes=[NSNumber(value:INSCameraOptionsType.storageState.rawValue),];
INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes){(err, options, successTypes)inguardlet options = options else{self.showAlert("get options",String(describing: err))return}varsdCardStatus="error"switch options.storageStatus?.cardState {case.normal:
sdCardStatus ="Normal"breakcase.noCard:
sdCardStatus ="NoCard"breakcase.noSpace:
sdCardStatus ="NoSpace"breakcase.invalidFormat:
sdCardStatus ="INvalid Format"breakcase.writeProtectCard:
sdCardStatus ="Write Protect Card"breakcase.unknownError:
sdCardStatus ="UnknownError"breakdefault:
sdCardStatus ="Status Error"}}

Battery Level Information

letoptionTypes=[NSNumber(value: INSCameraOptionsType.batteryStatus.rawValue),];INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes){(err,options,successTypes)inguardletoptions=optionselse{self.showAlert("get options",String(describing: err))return}print("battery: \(options.batteryStatus!.batteryLevel)")}

Camera System Time

Notification Module

Battery Low Notification

Notification string:INSCameraBatteryLowNotification

NotificationCenter.default.addObserver(self,
selector: #selector(self.batteryLowNotification(_:)),
name:NSNotification.Name.INSCameraBatteryLow,
object:nil)

Callback example:

@objcfunc batteryLowNotification(_ notification:Notification){iflet status = notification.userInfo?["storage_status"]as?INSCameraBatteryStatus{self.showAlert("Notification","Battery Low: \(status.batteryScale)%")}print("Notification: Battery Low")}

SD Card Status Notification

Notification string:INSCameraStorageStatusNotification

NotificationCenter.default.addObserver(self,
selector: #selector(self.storageFullNotification(_:)),
name: NSNotification.Name.INSCameraStorageStatus,
object: nil)

Status types:

typedefNS_ENUM(NSInteger, INSPBCardState) {
INSPBCardState_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,
INSPBCardState_StorCsPass = 0, // Normal
INSPBCardState_StorCsNocard = 1, // No card
INSPBCardState_StorCsNospace = 2, // No space
INSPBCardState_StorCsInvalidFormat = 3, // Invalid format
INSPBCardState_StorCsWpcard = 4, // Write protection
INSPBCardState_StorCsOtherError = 5// Other error
};

Callback example:

@objcfunc storageFullNotification(_ notification:Notification){iflet status = notification.userInfo?["card_state"]as?INSCameraCardState{self.showAlert("Notification","Battery Low :\(status)")}print("Notification: Storage Full")}

Camera Capturing Stopped Notification (Anomaly)

Notification string:INSCameraCaptureStoppedNotification

NotificationCenter.default.addObserver(self,
selector: #selector(self.captureStoppedNotification(_:)),
name: NSNotification.Name.INSCameraCaptureStopped,
object: nil)

Callback example:

@objcfunc captureStoppedNotification(_ notification:Notification){iflet info = notification.userInfo?["video"]as?INSCameraVideoInfo,let errorCode = notification.userInfo?["error_code"]as?Int{self.showAlert("Notification","Capture Stop, error code:\(errorCode)")}print("Notification: Capture Stop")}

Note: If any anomalies occur during recording, such as storage errors or excessive temperature, the device will automatically stop recording. In such cases, the user should be prompted to restart the operation to prevent loss of important content.

CameraTemperature Status Notification (Overheating)

Notification string:INSCameraTemperatureStatusNotification

NotificationCenter.default.addObserver(self,
selector: #selector(self.temperatureValueNotification(_:)),
name: NSNotification.Name.INSCameraTemperatureStatus,
object: nil)

Callback example:

@objcfunc temperatureValueNotification(_ notification:Notification){iflet status = notification.userInfo?["temperature_status"]as?INSCameraTemperatureStatus{self.showAlert("Notification","Temperature warning, \(status.temperature)")}print("Notification: Temperature warning")}

Note: High temperatures may cause reduced performance or even damage to the camera. Upon receiving this notification, users should be advised to cease operation and allow the camera to cool before resuming use.

Sensor Device (Lens) Control Module

The following is the enumeration of sensor device types (lens types) available for the camera:

typedef NS_ENUM(NSUInteger, INSSensorDevice) {
INSSensorDeviceUnknown, // Unknown
INSSensorDeviceFront, // Front
INSSensorDeviceRear, // Rear
INSSensorDeviceAll, // Panoramic
};

Retrieve Active Sensor Type

INSCameraManager.socket().commandManager.getActiveSensor { error, device, str1, str2iniferror!=nil {
self.showAlert("HDR Take:", "Failed!")
return
}
print("device:\(device)")
}
  • For cameras with interchangeable lenses (One RS, One R), use the following code to retrieve the current sensor type: Wide indicates wide-angle, Pano indicates panorama:
func getLensType(){letsettings:INSCameraDeviceSettings?=INSCameraManager.shared().currentCamera?.settings
guardlet mediaOffset = settings?.mediaOffset else{return}letsecnsorType=INSLensOffset(offset: mediaOffset).lensType
if secnsorType ==INSLensType.oneR577Wide.rawValue {print("secnsorType:577Wide")}elseif secnsorType ==INSLensType.oneR577Pano.rawValue{print("secnsorType:577Pano")}print("secnsorType:\(secnsorType)")}

Switching Sensors

INSCameraManager.shared().commandManager.setActiveSensorWith(activeSensorDevice) { [weak self] err, mediaOffset, mediaOffsetV3 in
if let err = err {
self?.showAlert("失败", String(describing: err))
} else {
self?.showAlert("成功", "current offset: \(mediaOffset ?? "")")
self?.shouldRestartPreview = true
self?.runMediaSession()
}
}

Usage Notes:

  • activeSensorDevice: Pass the sensors type to switch to (e.g., .front, .rear, .all)

Preview Module

The preview has the following core classes; for details, refer to:demo:CameraConfigByJsonController

  • INSCameraSessionPlayer
    • Bind iOS-side bounds
    • Implementation protocol: INSCameraSessionPlayerDelegate
    • Implementation protocol: INSCameraSessionPlayerDataSource, it is recommended to implement the following two protocols:
      1. Configure Offset information: updateOffsetToPlayer
      2. Configure stabilization information: updateStabilizerParamToPlayer
  • INSCameraMediaSession
func setupRenderView(){varframe=self.view.bounds;
letheight= frame.size.width *0.667
frame.origin.x =0
frame.origin.y = frame.size.height - height
frame.size.height = height
newPlayer =INSCameraSessionPlayer()
newPlayer?.delegate =self
newPlayer?.dataSource =self
newPlayer?.render.renderModelType.displayType =.sphereStitch
iflet view = newPlayer?.renderView {
view.frame = frame;
print("预览流: getView = \(view), frame = \(frame)")self.view.addSubview(view)}letconfig=INSH264DecoderConfig()
config.shouldReloadDecoder =false
config.decodeErrorMaxCount =30
config.debugLiveStrem =false
config.debugLog =falseself.mediaSession.setDecoderConfig(config)}

Preview Real-Time Stabilization Data Acquisition

During the preview process, implementing the INSCameraSessionGyroDelegate protocol in INSCameraSessionPlayer enables real-time callbacks for stabilization data. The callback data exists in two formats: raw NSData and parsed INSGyroRawItem format.

@protocolINSCameraSessionGyroDelegate <NSObject>
@optional
- (void)onRawGyroData:(NSData *)rawDatatimestampMs:(int64_t)timestampMs;
- (void)onParsedGyroData:(NSMutableArray<INSGyroRawItem *> *)gyroItemstimestampMs:(int64_t)timestampMs;
@end@interfaceINSCameraSessionPlayer : NSObject<INSCameraPlayerSession>
@property (nonatomic, weak ) id<INSCameraSessionGyroDelegate> gyroDelegate;
@end

Capturing Control Module

This module primarily covers camera mode switching, parameter configuration, and functions for retrieving the camera's current capturing mode and settings. The JSON configuration mechanism is a key focus.

The camera interface supports configuring all parameters, but note that not all parameters take effect in every mode. For example, setting the photo interval parameter in video recording mode is ineffective. To address this, the camera internally maintains a JSON configuration table defining the list of available parameters and their valid ranges for each mode.

Developers can download this JSON configuration table to accurately retrieve the available parameters and their corresponding values for different capture modes, enabling more rational and efficient camera control and configuration.

Additionally, we provide a management class, INSCameraAttrManagerWrapper, to maintain camera parameters and their dependencies. This class stores all camera parameters and determines parameter support and valid ranges based on the JSON configuration table. Refer to CameraConfigByJsonController.swift in the demo for usage details.

In practice, developers can first retrieve current parameters from the camera and set them in this class. Class methods can then be used to query parameter support status and available values.

Retrieve the Camera JSON Configuration File

For X4 and later cameras, capture modes and attributes are determined by the properties configured in the supported list. Different cameras support varying capture modes, and supported attributes also differ across modes. Before capturing, synchronize the camera's supported list (JSON file).

INSCameraManager.socket().commandManager.fetchStorageFileInfo(with: .json, completion: {error, fileResp in
if let err = error {
return
}
guard let fileResp = fileResp else {
return
}
print("Info: fetchStorageFileInfo Success!")
INSCameraManager.socket().commandManager.fetchResource(withURI: fileResp.uri, toLocalFile: outputURL, progress: {progress in
}, completion: { error in
if let error = error {
print("Error: fetchResource Failed!")
return
}
print("Info: fetchResource Success!")
completion?()
})
})

Retrieve the Current Capture Mode

Use the interface INSCameraManager.shared().commandManager.getOptionsWithTypes to retrieve the current camera's capture mode. This method requires the following parameters:

  • optionTypes Specify which parameters to retrieve. Each parameter corresponds to an enumeration value (see INSCameraOptionsType) and must be converted to an NSNumber array.
  • requestOptions The maximum configurable request timeout duration (default 10 seconds).
  • completion Returned in callback:
    • error: nil indicates successful retrieval; otherwise, contains the error reason.
    • cameraOptions: Contains the current camera capture mode (capture mode is either photoSubMode or videoSubMode; see below for specific enumeration meanings).

Capture mode enumeration:

// Photo capturingtypedefNS_ENUM(NSUInteger,INSPhotoSubMode){
INSPhotoSubModeSingle =0,
INSPhotoSubModeHdr,
INSPhotoSubModeInterval,
INSPhotoSubModeBurst,
INSPhotoSubModeNightscape,
INSPhotoSubModeInstaPano,
INSPhotoSubModeInstaPanoHdr,
INSPhotoSubModeStarlapse,
INSPhotoSubModeNone =100,};// Video recordingtypedefNS_ENUM(NSUInteger,INSVideoSubMode){INSVideoSubModeNormal=0,INSVideoSubModeBulletTime,INSVideoSubModeTimelapse,INSVideoSubModeHDR,INSVideoSubModeTimeShift,INSVideoSubModeSuperVideo,INSVideoSubModeLoopRecording,INSVideoSubModeFPV,INSVideoSubModeMovieRecording,INSVideoSubModeSlowMotion,INSVideoSubModeSelfie,INSVideoSubModePure,INSVideoSubModeLiveview,INSVideoSubModeCameraLiveview,INSVideoSubModeDashCam,INSVideoSubModePTZ,INSVideoSubModeNone=100,};

Call demo:

funcgetCurrentCameraMode(completion: (()->Void)?)->Void{lettypeArray: [INSCameraOptionsType]=[.videoSubMode,.photoSubMode]letoptionTypes=typeArray.map{(type)->NSNumberinreturnNSNumber(value: type.rawValue)}letrequestOptions=INSCameraRequestOptions()requestOptions.timeout=10INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes,requestOptions: requestOptions){[weakself]error,cameraOptions,_inifleterror=error{self?.showAlert("Failed","The camera mode has been get failed: \(error.localizedDescription)")return}guardletcameraOptions=cameraOptionselse{return}varcaptureMode: HUMCaptureMode? =nilifcameraOptions.photoSubMode!=100{
captureMode =HUMCaptureMode.modePhotoFrom(value: cameraOptions.photoSubMode)}elseifcameraOptions.videoSubMode!=100{
captureMode =HUMCaptureMode.modeVideoFrom(value: cameraOptions.videoSubMode)}guardletmode=captureModeelse{return}completion?()}}

Switching Capture Mode

The method INSCameraManager.shared().commandManager.setOptions configures the specified mode for the camera. When setting the capture mode, note the following key points:

  • INSCameraOptions

Holds the capture mode configuration, primarily comprising two properties:

  • photoSubMode: Photo mode

  • videoSubMode: Video mode

  • INSCameraOptionsType

Specifies which parameters in INSCameraOptions should take effect:

  • Photo mode: INSCameraOptionsType::INSCameraOptionsTypePhotoSubMode
  • Video mode: INSCameraOptionsType::INSCameraOptionsTypeVideoSubMode

The following is sample code (using photo mode configuration as an example):

// Photo Capture Mode EnumerationtypedefNS_ENUM(NSUInteger, INSPhotoSubMode) {
INSPhotoSubModeSingle = 0,
INSPhotoSubModeHdr,
INSPhotoSubModeInterval,
INSPhotoSubModeBurst,
INSPhotoSubModeNightscape,
INSPhotoSubModeInstaPano,
INSPhotoSubModeInstaPanoHdr,
INSPhotoSubModeStarlapse,
INSPhotoSubModeNone = 100,
};
var typeArray: [INSCameraOptionsType] = [.photoSubMode]
let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) }
let cameraOptions = INSCameraOptions()
cameraOptions.photoSubMode = INSPhotoSubMode.single
INSCameraManager.shared().commandManager.setOptions(cameraOptions, forTypes: optionTypes) { [weak self] error, _ in
if let error = error {
self?.showAlert("Failed", "The camera mode has been set failed: \(error.localizedDescription)")
print("Failed: The camera mode has been set failed: \(error.localizedDescription)")
return
}
print("SUCCESS")
}

Parameter Setting

Capturing Parameters

White Balance (Numeric Type)

The property in INSPhotographyOptions is:

@property (nonatomic) uint32_t whiteBalanceValue;

The corresponding enumeration in INSPhotographyOptionsType is:

INSPhotographyOptionsTypeWhiteBalance = 13

Assuming the current shooting mode INSCameraFunctionMode is 6, indicating standard photo capture.

  • X2 and One X only support enumeration (INSCameraWhiteBalance) settings; X3 and later models support using whiteBalanceValue.
@property(nonatomic) uint32_t whiteBalanceValue;
@property(nonatomic) INSCameraWhiteBalance whiteBalance;
typedef NS_ENUM(uint16_t, INSCameraWhiteBalance){
INSCameraWhiteBalanceAutomatic =0,
/// Inscandescent
INSCameraWhiteBalanceColorTemp2700K,
/// Sunny. ONE X Fluorescent
INSCameraWhiteBalanceColorTemp4000K,
/// Cloudy. ONE X Sunny
INSCameraWhiteBalanceColorTemp5000K,
/// Fluorescent. ONE X Cloudy
INSCameraWhiteBalanceColorTemp6500K,
/// Outdoor.
INSCameraWhiteBalanceColorTemp7500K =5,};
ExposureBias(Numeric Type)

Adjustment is only supported when the exposure mode is set to “AUTO” or “FULL_AUTO”.

The property in INSPhotographyOptions is: exposureBias

@property (nonatomic) float exposureBias;

The corresponding enumeration in INSPhotographyOptionsType is:

INSPhotographyOptionsTypeExposureBias = 7
ISO,shutterSpeed(Numeric Type)

Adjustment is supported only in the “MANUAL” and “ISO_PRIORITY” exposure modes.

The respective properties in INSPhotographyOptions are: stillExposure.isostillExposure.shutterSpeed

@property (nullable, nonatomic) INSCameraExposureOptions *stillExposure;
@interfaceINSCameraExposureOptions : NSObject@property (nonatomic) uint8_t program;
@property (nonatomic) NSUInteger iso;
#if TARGET_OS_IOS
@property (nonatomic) CMTime shutterSpeed;
#endif@end

The corresponding enumeration in INSPhotographyOptionsType is:

INSPhotographyOptionsTypeStillExposureOptions = 20
lapse_time(Numeric Type)

This parameter is only effective in timelapse mode.

funcsetLapseTimeToCamera(completion: (()->Void)?){let functionMode =self.attrManage.getIntFunctionsMode()letfunctionModeHum=HUMCaptureMode.modeFuncionFrom(value: functionMode)varmode:INSTimelapseMode? =niliffunctionModeHum.isPhotoMode{
mode =INSTimelapseMode.image}elseiffunctionModeHum.isVideoMode{
mode =INSTimelapseMode.video}guardletmode=modeelse{return}guardletoptions=self.currentLapseTimeelse{return}options.lapseTime=UInt(self.attrManage.getLapseTime()*1000)// options.duration = self.attrManage.getRecordDuration()INSCameraManager.shared().commandManager.setTimelapseOptions(options,for: mode,completion: {(err)inifleterr=err{self.showAlert("Set LapseTime failed",err.localizedDescription);return}completion?()})}
Resolution(Enumeration)

Starting from version 1.8.1, resolution is uniformly managed via enumeration. You must manually configure isUseJsonOptions to true.

INSPhotographyOptions.isUseJsonOptions = true
  • Photo

The property in INSPhotographyOptions is: photoSizeForJson

photoSizeForJson = 17`, indicating that the x4 camera has a resolution of `8192 x 6144

The corresponding enumeration in INSPhotographyOptionsType is:

INSPhotographyOptionsTypePhotoSize = 40

Assuming the current shooting mode INSCameraFunctionMode is 6, indicating standard photo capture.

Code example:

letfunctionMode=INSCameraFunctionMode.init(functionMode:6)vartypeArray:[INSPhotographyOptionsType]=[.photoSize]letoptionTypes= typeArray.map{NSNumber(value: $0.rawValue)}
options.isUseJsonOptions =true
option.photoSizeForJson =17INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion:{[weak self] error, _ inguardlet error = error else{self?.showAlert("Success"," set successfully")return}self?.showAlert("Failed","set failed: \(error.localizedDescription)")})

Correspondence between Resolution and Enumeration Values

"photo_resolution":{"6912_3456":"0", // X3 18MP
"6272_3136":"1","6080_3040":"2","4000_3000":"3","4000_2250":"4","5212_3542":"5","5312_2988":"6","8000_6000":"7","8000_4500":"8","2976_2976":"9","5984_5984":"10","11968_5984":"11","5952_2976":"12", // 72MP
"8192_6144":"17", // X4 18MP
"8192_4608":"18","4096_3072":"19","4096_2304":"20","7680_3840":"21","3840_3840":"22"}
  • Video

The property in INSPhotographyOptions is: videoResolutionForJson

Not displayed here; refer to the record_resolution list in the common_camera_setting_proto.json file.

Exposure Mode (Enumeration)

The properties in INSPhotographyOptions are:

@property (nullable, nonatomic) INSCameraExposureOptions *stillExposure;
@interfaceINSCameraExposureOptions : NSObject@property (nonatomic) uint8_t program; // Exposure mode@property (nonatomic) NSUInteger iso;
#if TARGET_OS_IOS
@property (nonatomic) CMTime shutterSpeed;
#endif@end

The corresponding enumeration in INSPhotographyOptionsType is:

INSPhotographyOptionsTypeStillExposureOptions = 20"exposure_program": {
"AUTO": "0",
"ISO_PRIORITY": "1",
"SHUTTER_PRIORITY": "2",
"MANUAL": "3",
"ADAPTIVE": "4",
"FULL_AUTO": "5"
},

Supports setting multiple parameters for the camera simultaneously, as follows:

vartypeArray:[INSPhotographyOptionsType]=[.photoSize,.whiteBalanceValue]letoptionTypes= typeArray.map{NSNumber(value: $0.rawValue)}
option.photoSizeForJson =11
option.whiteBalanceValue =4000INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion:{[weak self] error, _ inguardlet error = error else{self?.showAlert("Success","The camera resolution has been set successfully")return}self?.showAlert("Failed","The camera resolution has been set failed: \(error.localizedDescription)")completion?()})
Capture Type (Enumeration)

Note: The X5 defaults to PureShot mode and does not support disabling it.

The property in INSPhotographyOptions is:

@property (nonatomic) uint8_t rawCaptureType;

The corresponding enumeration in INSPhotographyOptionsType is:

INSPhotographyOptionsTypeRawCaptureType = 25,

Enumeration type:

"raw_capture_type": {
"OFF": "0",
"RAW": "1",
"PURESHOT": "3",
"PURESHOT_RAW": "4",
"INSP": "5",
"INSP_RAW": "6"
},
In-camera Splicing (Bool)

When capturing photos, the camera internally splices panoramic images, eliminating the need for external splicing of source material. Supported only on x4 and later camera models.

vartypeArray=[INSCameraOptionsType]()letcameraOptions=INSCameraOptions()
// Open is true, Closed is false
cameraOptions.enableInternalSplicing =true
typeArray.append(.internalSplicing)letoptionTypes= typeArray.map{(type)->NSNumberinreturnNSNumber(value: type.rawValue)}INSCameraManager.shared().commandManager.setOptions(cameraOptions, forTypes: optionTypes){[weak self] error, _ iniflet error = error {self?.showAlert("Failed","The camera mode has been set failed: \(error.localizedDescription)")return}completion?()}

Retrieve Current Capture Parameters

The camera is obtained via the getPhotographyOptions method. The primary input parameters required are three: functionMode and optionTypes, along with a closure callback.

/*!
* @discussion Get photography options. Your app should not call this method to get the current photography options. Instead, your app should rely on the photography options that just set, or they will be as default.
*
* @param functionMode the target function mode to get
* @param optionTypes array of the INSPhotographyOptionsType to get
* @param completion the callback block. If all succeed, error would be nil, if partial failed, error's code would be <code>INSCameraErrorCodeAccept</code>, if all fail, error's code would be the maximum error code.
*/
-(void)getPhotographyOptionsWithFunctionMode:(INSCameraFunctionMode*)functionMode
types:(NSArray <NSNumber *>*)optionTypes
completion:(void(^)(NSError * _Nullable error, INSPhotographyOptions * _Nullable options, NSArray <NSNumber *>* _Nullable successTypes))completion;
  • functionMode: Indicates the current shooting mode
  • optionTypes: Each parameter corresponds to an enumeration value
    • For example,

    • Resolution corresponds to:INSPhotographyOptionsTypePhotoSize = 40

    • White balance corresponds to: INSPhotographyOptionsTypeWhiteBalance = 13

  • The closure returns an NSError and INSPhotographyOptions
    • NSError being nil indicates success; otherwise, it contains the reason for failure
    • INSPhotographyOptions contains the specific values of current camera parameters, such as resolution, white balance, etc.

(Example) Retrieve the current camera white balance value:

vartypeArray:[INSPhotographyOptionsType]=[.whiteBalanceValue]letoptionTypes= typeArray.map{NSNumber(value: $0.rawValue)}letfunctionMode= currentFunctionMode.functionMode
INSCameraManager.shared().commandManager.getPhotographyOptions(with: functionMode, types: optionTypes, completion:{[weak self] error, camerOptions, successTags inif let error = error {print("Get Message Failed! Error: \(error.localizedDescription)")return}print("getPhotographyOptions Success!")
print("whiteBalance: \(camerOptions?.whiteBalance ??"N/A")"})

Setting Camera Parameters

To configure camera parameters, use the method: INSCameraManager.shared().commandManager.setPhotographyOptions.

The primary input parameters are as follows:

  • INSPhotographyOptions: Stores the configured parameters
  • INSPhotographyOptionsType: Indicates which parameters require configuration (each parameter corresponds to an enumeration)
  • INSCameraFunctionMode: The current capture mode.
    • 相机设置需要的拍摄模式INSCameraFunctionMode和从相机拿到的拍摄模式INSPhotoSubModeINSVideoSubMode不能直接转换,对应关系参考工程文件中的类:HUMCaptureMode。通过HUMCaptureMode将相机当前模式INSPhotoSubModeINSVideoSubMode转成统一的INSCameraFunctionMode
    • The camera settings require the INSCameraFunctionMode, which cannot be directly converted from the INSPhotoSubMode or INSVideoSubMode obtained from the camera. It can refer to the class HUMCaptureMode in the project documentation for the mapping relationship. Use HUMCaptureMode to convert the camera's current mode (INSPhotoSubMode or INSVideoSubMode) into the unified INSCameraFunctionMode.
  • Closure callback: Returns whether the retrieval was successful.

All parameter types must be set to values supported by the camera screen and cannot be set arbitrarily.

Sample code is as follows: Set specified white balance

letfunctionMode=INSCameraFunctionMode.init(functionMode:6)vartypeArray:[INSPhotographyOptionsType]=[.whiteBalanceValue]letoptionTypes= typeArray.map{NSNumber(value: $0.rawValue)}
option.whiteBalanceValue =4000INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion:{[weak self] error, _ inguardlet error = error else{self?.showAlert("Success","set successfully")return}self?.showAlert("Failed","set failed: \(error.localizedDescription)")})

Photo Capturing

Standard Capturing

通过INSCameraManager.shared().commandManager.takePicture方法向相机下达拍摄指令,若 errornil,则表示拍摄成功,反之则包含错误信息。optionInfo 中涵盖照片的远程访问地址,可进行远程导出(无需下载至本地)。

The camera is commanded to take a photo via the INSCameraManager.shared().commandManager.takePicture method. If error is nil, the photo capture was successful; otherwise, it contains error information. The optionInfo contains the remote access URL for the photo, enabling remote export (without downloading to the local device).

INSCameraManager.shared().commandManager.takePicture(with: nil, completion: { (error, optionInfo) in
print("end takePicture \(Date())") guard let uri = optionInfo?.uri else {
return
}
print("Take Picture Url:\(uri)")\
})

HDR Photo Capturing

Operation Method Change (x4 and Later Models):

For x4 and later models, switch to the corresponding capturing mode before initiating the shot.

letoptions:INSTakePictureOptions=INSTakePictureOptions()INSCameraManager.shared().commandManager.takePicture(with: options, completion:{(error, optionInfo)inguardlet uri = optionInfo?.uri else{return}})

For HDR capturing on the X3 and earlier models, you need to set the mode to AEB mode in capturing parameters before taking the photo.

letoptions:INSTakePictureOptions=INSTakePictureOptions()
options.mode =INSPhotoMode.aeb
INSCameraManager.shared().commandManager.takePicture(with: options, completion:{(error, optionInfo)inguardlet uri = optionInfo?.uri else{return}})

Countdown photo capture (only supports X5 and X4 Air)

You need to set the photographySelfTimer parameter using setPhotographyOptions, and set countDown to 0.

Video Recording

Standard Recording

开始录制:

INSCameraManager.shared().commandManager.startCapture(with: nil, completion: { (err) inifleterr=err {
self.showAlert(row.tag!, "\(String(describing: err))")
return
}
})

Stop recording

INSCameraManager.shared().commandManager.stopCapture(with: nil, completion: { (err, info) inifleterr=err {
self.showAlert(row.tag!, "\(String(describing: err))")
return
}
})

Timelapse Recording

Starting and stopping recording follows the standard procedure, but there are some important points to note:

  • For the X5 and later models, if you need to save IMU data during timelapse recording, you must use our SDK for recording. Using our app for recording will not save IMU data.
  • Furthermore, the IMU data storage function must be triggered by calling the following command:

Start recording

/*! * Start time lapse capture. For ONE X, you can input `INSExtraInfo` via options if the `INSTimelapseMode` is image. * * availability(ONE, ONE X)*/
- (void)startCaptureTimelapseWithOptions:(INSStartCaptureTimelapseOptions * _Nonnull)options completion:(void(^)(NSError * _Nullable error))completion;

Stop recording

/*! * Start time lapse capture * * availability(ONE)*/
- (void)stopCaptureTimelapseWithCompletion:(void(^)(NSError * _Nullable error,
INSCameraVideoInfo * _Nullable videoInfo))completion;

File Management Module

Get File List

- (void)fetchPhotoListWithOptions:(INSGetFileListOptions *)options
completion:(void (^)(NSError * _Nullable error, INSCameraResources * _Nullable res))completion;

File Download

- (NSURLSessionTask *)fetchResourceWithURI:(NSString *)URI toLocalFile:(NSURL *)localFileURL
progress:(void (^)(NSProgress * _Nullable progress))progress
completion:(void(^)(NSError * _Nullable error))completion;

CameraSDK Logger Module

In INSCameraSDK, all log information is passed to the upper layer as callbacks via the INSCameraSDKLoggerProtocol protocol. Upon receiving these logs, the upper layer can choose to print them for developers to observe the SDK's operational status during debugging.

Logs can also be stored persistently to support subsequent data analysis or troubleshooting. For detailed configuration methods, refer to the sample controller CameraConfigByJsonController.

Log callbacks are implemented via the INSCameraSDKLogger singleton object, which serves as the protocol delegate for INSCameraSDKLoggerProtocol.

Developers must assign their custom log delegate object to the logDelegate property of INSCameraSDKLogger to receive log messages of all levels output by the SDK.

The logging protocol INSCameraSDKLoggerProtocol includes the following methods:

@protocolINSCameraSDKLoggerProtocol
- (void)logError:(NSString *)messagefilePath:(NSString *)filePathfuncName:(NSString *)funcNamelineNum:(NSInteger)lineNum;
- (void)logWarning:(NSString *)messagefilePath:(NSString *)filePathfuncName:(NSString *)funcNamelineNum:(NSInteger)lineNum;
- (void)logInfo:(NSString *)messagefilePath:(NSString *)filePathfuncName:(NSString *)funcNamelineNum:(NSInteger)lineNum;
- (void)logDebug:(NSString *)messagefilePath:(NSString *)filePathfuncName:(NSString *)funcNamelineNum:(NSInteger)lineNum;
- (void)logCrash:(NSString *)messagefilePath:(NSString *)filePathfuncName:(NSString *)funcNamelineNum:(NSInteger)lineNum;
@end

GPS Data Module

Settings in Photo Capture Mode

When calling the capture interface, pass the INSMediaGps data into the capture parameters.

funcpictureGps(){// Constructing current location (GPS) data, using Hong Kong coordinate points as an example.letnewestLocation=CLLocation(coordinate: CLLocationCoordinate2D(latitude: 22.2803,longitude: 114.1655),// 经纬度altitude: 10.0,// Altitude (meters)horizontalAccuracy: 5.0,// Horizontal Accuracy (meters)verticalAccuracy: 5.0,// Vertical Accuracy (meters)timestamp: Date()// Current Timestamp)// Create extended metadata objects (for attaching GPS, gyroscope, magnetometer, and other information)letmetaData=INSExtraMetadata()// Create a media GPS information object using a constructed CLLocation.letmediaGps=INSMediaGps(clLocation: newestLocation,isValidLocation: true)// Write GPS information into the metadatametaData.gps=mediaGps// Create an extended information object and set its metadata (gyroscope data is not set here).letextraInfo=INSExtraInfo(version: Int32(INSExtraInfoVersion.one2.rawValue),// Using Extended Information Version one2metadata: metaData,// Metadata with GPS informationgyroData: nil// No gyroscope data)// Construct a photo selection object containing extended information
let options: INSTakePictureOptions=INSTakePictureOptions(extraInfo: extraInfo)// Call the camera to take a photoINSCameraManager.shared().commandManager.takePicture(with: options,completion: {(error,optionInfo)inprint("end takePicture \(Date())")// Printing the photo capture completion time// Extract the photo URI from the response dataguardleturi=optionInfo?.urielse{return// If retrieval fails, return directly.}print("Take Picture Url:\(uri)")// Print the Url of the photo file})}

Settings in Video Recording Mode

After starting recording, transmit the constructed GPS data to the camera via uploadGpsDatas.

// Create an extra information object (typically used to pass extended parameters)letextraInfo=INSExtraInfo()// Create a recording parameter object and set extraInfo.letoptions=INSCaptureOptions(extraInfo: extraInfo)// Start capturingself?.commandsManager.startCapture(with: options,completion: {(err)inifleterr=err{// Startup failed, pop-up alertprint("\(row.title!) failed with error: \(err)")self?.showAlert(row.title!,err.localizedDescription)return}// Execute GPS data upload after a 5-second delay.DispatchQueue.main.asyncAfter(deadline: .now()+5){// Create a GPS data array (simulating 100 entries)vargpsDatas: [INSCameraGpsInfo]=[]for_in0..<100{let location =CLLocation(coordinate: CLLocationCoordinate2DMake(22.219749,11.264474),altitude: 50.0,horizontalAccuracy: 1.0,verticalAccuracy: 1.0,course: 0.012,speed: 10.0,timestamp: Date())letmediaGps=INSCameraGpsInfo(clLocation: location,isValidLocation: true)gpsDatas.append(mediaGps)}// Convert to binary data format (optional: for debugging or uploading)vardatas=Data()forgpsingpsDatas{
guard letgpsD=gps.toGpsData()else{continue}datas.append(gpsD)}print("--- \(datas)")// Output debugging information// Upload GPS data to the cameraINSCameraManager.shared().commandManager.uploadGpsDatas(gpsDatas,completion: {(error)inifleterror=error{self?.showAlert("error","upload gps datas error: \(error)")print("upload gps datas error: \(error)")}else{self?.showAlert("success","upload gps datas success")print("upload gps datas success")}// Stop recording after upload completes.INSCameraManager.shared().commandManager.stopCapture(with: options,completion: {[weakself](err,video)inifleterr=err{print("\(row.title!) failed with error: \(err)")self?.showAlert(row.title!,err.localizedDescription)return}})})}})

Other Function Module

Camera Activation

The App ID and secret required to activate the camera must be requested from Insta360:

guardlet serialNumber =INSCameraManager.shared().currentCamera?.serialNumber else{self?.showAlert("提示","请先连接相机")return}letcommandManager=INSCameraManager.shared().commandManager
// You need to apply and enter your real app ID and secret.
INSCameraActivateManager.setAppid("Appid", secret:"secret")INSCameraActivateManager.share().activateCamera(withSerial: serialNumber, commandManager: commandManager){ deviceInfo, error iniflet activateError = error {self?.showAlert("Activate to \(serialNumber)",String(describing: activateError))}else{letdeviceType=deviceInfo?["deviceType"]??""letserialNumber=deviceInfo?["serial"]??""self?.showAlert("Activate to success","deviceType: \(deviceType), serial: \(serialNumber)")}}

Turn off Notification Sounds

letoptionTypes=[NSNumber(value:INSCameraOptionsType.mute.rawValue),];
letoptions=INSCameraOptions()
options.mute =trueINSCameraManager.socket().commandManager.setOptions(options, forTypes: optionTypes, completion:{error,successTypes iniflet error = error {print("Error:\(error)")return}print("Success")})

Formatting the SD Card

letoptionTypes=[NSNumber(value:INSCameraOptionsType.mute.rawValue),];
letoptions=INSCameraOptions()
options.mute =trueINSCameraManager.socket().commandManager.setOptions(options, forTypes: optionTypes, completion:{error,successTypes iniflet error = error {print("Error:\(error)")return}print("Success")})

Camera Lock Screen

Note: Only supports X4 and X5

Screen Lock:

INSSetAccessCameraFileStateAccessStateLiveView

Turn off Screen Lock:

INSSetAccessCameraFileStateAccessStateIdle = 1
typedef NS_ENUM(NSUInteger, INSSetAccessCameraFileStateAccessState) {
INSSetAccessCameraFileStateAccessStateUnknown = 0,
/**没在在访问文件 */
INSSetAccessCameraFileStateAccessStateIdle = 1,
INSSetAccessCameraFileStateAccessStateExport = 2,
INSSetAccessCameraFileStateAccessStateDownload = 3,
INSSetAccessCameraFileStateAccessStatePlayback = 4,
INSSetAccessCameraFileStateAccessStateLiveView = 5,
};
INSCameraManager.shared().commandManager.setAppAccessFileState(state, completion: { _ in
// The callback completion can be handled here
})

Turn off Camera

Command to control camera shutdown. Sample code is as follows:

Note: Only Insta360 X5 and later cameras support this feature.

INSCameraManager.socket().commandManager.closeCamera({_ in
})

Firmware Upgrade

Proactively upgrade by calling updateFirwareWithOptions interface. INSCameraWriteFileOptions

@interface INSCameraWriteFileOptions : NSObject
/// file type of data to write
@property (nonatomic) INSCameraFileType fileType;
/// data of a file. if fileType is photo, data should be encoded in JPG format.
@property (nonatomic) NSData *data;
/// destinate path of the file in camera, if nil, camera will decide the uri with fileType.
@property (nonatomic, nullable) NSString *uri;
@end- (void)updateFirwareWithOptions:(INSCameraWriteFileOptions *)options
completion:(void (^)(NSError * _Nullable))completion;

Error Code

typedefNS_ENUM(NSUInteger, INSCameraErrorCode) {
/// ok
INSCameraErrorCodeOK = 200,
/// accepted
INSCameraErrorCodeAccept = 202,
/// mainly means redirection
INSCameraErrorCodeMovedTemporarily = 302,
/// bad request, check your params
INSCameraErrorCodeBadRequest = 400,
/// the command has timed out
INSCameraErrorCodeTimeout = 408,
/// the requests are sent too often
INSCameraErrorCodeTooManyRequests = 429,
/// request is interrupted and no response has been gotten
INSCameraErrorCodeNoResopnse = 444,
INSCameraErrorCodeShakeHandeError = 445,
INSCameraErrorCodePairError = 446,
/// error on camera
INSCameraErrorCodeInternalServerError = 500,
/// the command is not implemented for this camera or firmware
INSCameraErrorCodeNotImplemented = 501,
/// there is no connection
INSCameraErrorCodeNoConnection = 503,
/// firmware error
INSCameraErrorCodeFirmwareError = 504,
/// Invalid Request
INSCameraErrorCodeInvalidRequest = 505,
/// bluetooth not inited
INSCameraErrorCodeCentralManagerNotInited = 601,
};

Media SDK Function

Export Video

Video Export: INSExportSimplify Located in INSCoreMedia This class primarily simplifies video export operations, providing a set of configurable properties and methods to enable developers to customize the export process according to their needs. (Supports video export only).

Use Instruction

This method ensures basic export functionality, with all parameters set to their default values. Users can configure relevant parameters according to specific requirements.

Initialization Methods

-(nonnull instancetype)initWithURLs:(nonnull NSArray<NSURL>)urls outputUrl:(nonnull NSURL*)outputUrl;
  • Function: Initializes an INSExportSimplify object to specify an array of input video file URLs and the output video file URL.
  • Parameters:
    • urls: An array of input video file URLs. Cannot be empty.
    • outputURL: The URL of the output video file. Cannot be empty.
  • Return Value: Returns an INSExportSimplify object.
  • Sample Code:
NSArray<NSURL*> *inputUrls = @[[NSURLfileURLWithPath:@"path/to/input1.mp4"], [NSURLfileURLWithPath:@"path/to/input2.mp4"]];
NSURL *outputUrl = [NSURLfileURLWithPath:@"path/to/output.mp4"];
INSExportSimplify *exporter = [[INSExportSimplify alloc] initWithURLs:inputUrls outputUrl:outputUrl];

Start Exporting

-(nullable NSError*)start;

Cancel Exporting

-(void)cancel;

Shutdown Exporting

Cancel export. After exporting is complete, you must explicitly call the function; otherwise, it may cause a crash.

-(void)shutDown;

Parameter Description

Export Resolution

This interface is used to output image resolution (aspect ratio must be 2:1).

/** * Default width and height: 1920 × 960 (The exported aspect ratio must be 2:1)*/
@property (nonatomic) int width;
@property (nonatomic) int height;

Stitching Type

There are a total of three stitching type, namely Dynamic stitching, Disflow stitching, and AI Flow stitching.

  • Dynamic Stitching: Suitable for scenes containing close-ups, or situations involving motion and rapid changes.
  • Disflow Stitching: The usage scenario is identical to Dynamic stitching.
  • AI Flow stitching: Based on the optimized algorithm of Insta360's existing Disflow stitching technology, this mode delivers superior stitching results. It requires configuring the stitching model path aiStitchPath. The model file is located in the project directory: model_export_v22_d7c49187.mlmodelc.
@property (nonatomic) NSString *aiStitchPath;
typedefNS_ENUM(NSInteger, INSOpticalFlowType) {
// Dynamic Stitching
INSOpticalFlowTypeDynamicStitch = 0,
// Disflow Stitching
INSOpticalFlowTypeDisflow = 1,
// AI Flow Stitching
INSOpticalFlowTypeAiFlow = 2,
};

Stabilization Mode

The stabilization mode supports the following options in total. For panoramic cameras, there are two modes: Still and Full Directional:

  • Still: No matter how you rotate the camera, the view remains unchanged.
  • Full Directional: The perspective always shifts with the camera's movement.
/** * Stabilization mode, default: INSStabilizerStabModeZDirectional*/
@property (nonatomic)INSStabilizerStabMode stabMode;
typedefNS_ENUM(NSInteger, INSStabilizerStabMode) {
/// Turn off Stabilization
INSStabilizerStabModeOff = -1,
/// Still
INSStabilizerStabModeStill,
/// Disable yaw stabilization for directional lock; the view can only move around the z-axis (pan movement).
INSStabilizerStabModeZDirectional,
/// Enable image stabilization and enable horizontal correction, i.e., full-directional
INSStabilizerStabModeFullDirectional,
///Without calibrating the horizon, i.e., free-footage, total free camera mode, camera can move through three axis
INSStabilizerStabModeFreeFootage,
/// //Process flipping
INSStabilizerStabModeFlipEffect,
///Enable image stabilization and average attitude correction, i.e.,relative-refine
INSStabilizerStabModeRelativeRefine,
///Enable anti-shake, enable level correction, i.e., absolute-refine
INSStabilizerStabModeAbsoluteRefine,
/// Bullet Time
INSStabilizerStabModeBulletTime,
/// Pano Fpv
INSStabilizerStabModePanoFPV
};

Lens Guards Type

If wearing lens guards during filming, configure this parameter according to the type. (Standard lens guards in the store is rated Class A, while premium lens guards is rated Class S.)

/** * Lens Guards*/
@property (nonatomic) INSOffsetConvertOptions protectType;
typedefNS_OPTIONS(NSUInteger, INSOffsetConvertOptions) {
INSOffsetConvertOptionNone = 0,
INSOffsetConvertOptionEnableWaterProof = 1 << 0, // ONE X lens guards
INSOffsetConvertOptionEnableDivingAir = 1 << 1, // Invisible dive case (Air)
INSOffsetConvertOptionEnableDivingWater = 1 << 2, // Invisible dive case(Water)
INSOffsetConvertOptionEnableDivingAirV2 = 1 << 3, // Invisible dive case (Air, V2)
INSOffsetConvertOptionEnableDivingWaterV2 = 1 << 4, // Invisible dive case (Water, V2)
INSOffsetConvertOptionEnableBuckleShell = 1 << 5, // Buckle shell
INSOffsetConvertOptionEnableAdhesiveShell = 1 << 6, // Adhesive shell
INSOffsetConvertOptionEnableGlassShell = 1 << 7, // Premium lens guards (S)
INSOffsetConvertOptionEnablePlasticCement = 1 << 8, // Standard lens guards (A)
INSOffsetConvertOptionEnableAverageShell = 1 << 9// A/S average shell
};

Color Fusion

/** * Color Fusion: Default false*/
@property (nonatomic) BOOL colorFusion;

The primary causes of chromatic aberration are as follows:

  • First, since the two lenses operate independently, their respective video exposures may not align perfectly. When stitched together, noticeable brightness differences can occur. This stems from variations in capturing parameters and sensor performance between lenses, resulting in differing light intensities captured.
  • Second, uneven lighting on either side of the lens leads to differing camera exposures, sometimes resulting in noticeable brightness differences between the front and rear lens footage. This phenomenon is particularly pronounced in high-contrast lighting scenarios, such as areas where bright light meets shadow, or environments with significant indoor-outdoor lighting disparities. In these cases, the camera struggles to balance light intensity across different zones, causing substantial brightness variations in the captured images.

To address these issues, Color Fusion technology was developed. Through a series of algorithms and image processing techniques, it adjusts and optimizes footage captured by different lenses to reduce or eliminate brightness discrepancies. This ensures the stitched video appears more natural and seamless.

Defringe

This interface features a function to eliminate specific phenomena, specifically designed to counteract purple fringing caused by lighting conditions during recording. In real-world recording scenarios where lighting is complex and variable, this interface effectively addresses purple fringing issues arising from two common lighting situations. The first scenario involves intense outdoor sunlight. When recording during bright daylight hours, high-intensity outdoor light easily triggers purple fringing. This interface effectively eliminates fringing in such conditions. The second scenario pertains to indoor lighting. Light emitted by various indoor sources, such as incandescent bulbs or fluorescent lights, can also cause purple fringing in recorded footage. This interface similarly eliminates fringing in these indoor lighting scenarios.

Usage: To utilize this algorithm, configure the corresponding model managed via a JSON file: coreml_model_v2_scale6_scale4.json. Copy these models and JSON files into the app. Refer to the following code for parameter configuration:

Video

let jsonFilePath: String=Bundle.main.path(forResource: "coreml_model_v2_scale6_scale4",ofType: "json")!letcomponents=jsonFilePath.split(separator: "/")letmodelFilePath=components.dropLast().joined(separator: "/")varjsonContent=""do{letdata=tryData(contentsOf: URL(fileURLWithPath: jsonFilePath))jsonContent=String(data: data,encoding: .utf8)??""}catch{assertionFailure("\(jsonFilePath)文件无法读取")}letinitInfo=INSDePurpleFringeFilterInitInfo.init(imageTransferType: .AUTO,algoAccelType: .AUTO)letdepurpleFringInfo=INSDePurpleFringeFilterInfo()depurpleFringInfo.setInit(initInfo)depurpleFringInfo.setModelJsonContent(jsonContent)depurpleFringInfo.setModelFilePath(modelFilePath)

Photo

 let jsonFilePath: String=Bundle.main.path(forResource: "coreml_model_v2_scale6_scale4",ofType: "json")!letcomponents=jsonFilePath.split(separator: "/")letmodelFilePath=components.dropLast().joined(separator: "/")varjsonContent=""do{letdata=tryData(contentsOf: URL(fileURLWithPath: jsonFilePath))jsonContent=String(data: data,encoding: .utf8)??""}catch{assertionFailure("\(jsonFilePath)文件无法读取")}letdepurpleFringInfo=INSExporter2DefringConfiguration.init()depurpleFringInfo.modelJsonContent=jsonContentdepurpleFringInfo.modelFilePath=modelFilePathdepurpleFringInfo.enableDetect=truedepurpleFringInfo.useFastInferSpeed=falsevideoExporter?.defringeConfig=depurpleFringInfo

Denoise

In the field of video processing, multi-frame denoising technology is a crucial image processing method that can reduce or eliminate noise in video frames. Noise adversely affects image quality and viewing experience. Unlike single-frame denoising, which processes only a single frame, multi-frame denoising leverages redundant information from preceding and subsequent frames to more accurately distinguish between image content and noise. This approach preserves image details while removing noise, resulting in high-quality footage. However, multi-frame denoising also has drawbacks. It requires processing multiple frames, involving complex computational analysis that consumes system resources. This may cause devices to slow down or experience lag, while also reducing video export speed and increasing time costs.

/** * Denoise * This property controls whether to enable multi-frame noise reduction for video. When set to YES, noise reduction is enabled; when set to NO, noise reduction is disabled.*/
@property (nonatomic) BOOL enableDenoise;

Color Enhancement

/** * Color enhancement, disabled by default*/
@property (nonatomic) BOOL clolorPlus;

Progress and Status Callbacks

After exporting begins, the INSRExporter2ManagerDelegate protocol will provide real-time callbacks regarding the export progress and status.

typedefNS_ENUM(NSInteger, INSExporter2State) {
INSExporter2StateError = -1, // Indicates that an error occurred during the export process.
INSExporter2StateComplete = 0, // Indicates that the export has been successfully completed.
INSExporter2StateCancel = 1, // Indicates that the user manually canceled the export operation.
INSExporter2StateInterrupt = 2, // Indicates that the export was unexpectedly interrupted.
INSExporter2StateDisconnect = 3, // Indicates disconnection from the server
INSExporter2StateInitError = 4, // Indicates an error occurred during initialization.
};
@protocolINSRExporter2ManagerDelegate <NSObject>
- (void)exporter2Manager:(INSExporter2Manager *)managerprogress:(float)progress;
- (void)exporter2Manager:(INSExporter2Manager *)managerstate:(INSExporter2State)stateerror:(nullable NSError*)error;
// Used for panoramic tracking detection (generally not required)
- (void)exporter2Manager:(INSExporter2Manager *)managercorrectOffset:(NSString*)correctOffseterrorNum:(int)errorNumtotalNum:(int)totalNumclipIndex:(int)clipIndextype:(NSString*)type;
@end

Error Code

typedefNS_ENUM(NSInteger, INSExporter2State) {
INSExporter2StateError = -1, // Indicates that an error occurred during the export process.
INSExporter2StateComplete = 0, // Indicates that the export has been successfully completed.
INSExporter2StateCancel = 1, // Indicates that the user manually canceled the export operation.
INSExporter2StateInterrupt = 2, // Indicates that the export was unexpectedly interrupted.
INSExporter2StateDisconnect = 3, // Indicates disconnection from the server
INSExporter2StateInitError = 4, // Indicates an error occurred during initialization.
};
};

Photo Export

Instruction for Use

Photo Export: The INSExportImageSimplify class belongs to the INSCoreMedia framework. This class aims to simplify photo export operations by providing a set of configurable properties and methods. It supports exporting both standard photos and HDR photos, allowing developers to customize the export process according to their requirements.

Standard Photos Export

- (NSError*)exportImageWithInputUrl:(nonnull NSURL *)inputUrl outputUrl:(nonnull NSURL *)outputUrl;
  • Functions: Exports standard photos, supporting both remote and local.
  • Parameters:
    • inputURL: URL of the input image. Cannot be empty.
    • outputURL: URL of the output image. Cannot be empty.
  • Return Value: Returns an NSError object if an error occurs during export; returns nil if export succeeds.
  • Sample Code:
INSExportImageSimplify *exporter = [[INSExportImageSimplify alloc] init];
NSURL *inputUrl = [NSURLfileURLWithPath:@"path/to/input.jpg"];
NSURL *outputUrl = [NSURLfileURLWithPath:@"path/to/output.jpg"];
NSError *error = [exporter exportImageWithInputUrl:inputUrl outputUrl:outputUrl];
if (error) {
NSLog(@"导出失败:%@", error.localizedDescription);
} else {
NSLog(@"导出成功");
}

HDR image compositing method (supports only local HDR images)

For X3 and earlier models, HDR needs to be composited externally. After shooting, please download the HDR footage to your local device and then use this interface to composite it.

- (NSError*)exportHdrImageWithInputUrl:(nonnull NSArray<NSURL*> *)inputUrl outputUrl:(nonnull NSURL *)outputUrl;
  • Function:
    • This function is primarily used for exporting high dynamic range (HDR) images. It supports only local photos, which must be stored on the local device to perform the export operation. Additionally, to ensure the quality and effectiveness of the export, a minimum of 3 input photos is required.
  • Parameters:
    • inputURL: An array of URLs for input photos. This array cannot be empty, and its elements must be greater than or equal to 3. These URLs point to local photos requiring HDR export.
    • outputURL: Specifies the URL for the output photo. Similarly, this parameter cannot be empty and determines the storage location for the exported HDR photo.
  • Return Values:
    • During export, any errors encountered will return an NSError object. This object contains detailed error information for developer error handling and debugging.
    • If export succeeds without errors, the return value will be nil, indicating the operation completed successfully.
  • Sample Code:
INSExportImageSimplify *exporter = [[INSExportImageSimplify alloc] init];
NSArray<NSURL*> *inputUrls = @[[NSURLfileURLWithPath:@"path/to/input1.jpg"], [NSURLfileURLWithPath:@"path/to/input2.jpg"], [NSURLfileURLWithPath:@"path/to/input3.jpg"]];
NSURL *outputUrl = [NSURLfileURLWithPath:@"path/to/output_hdr.jpg"];
NSError *error = [exporter exportHdrImageWithInputUrl:inputUrls outputUrl:outputUrl];
if (error) {
NSLog(@"导出失败:%@", error.localizedDescription);
} else {
NSLog(@"导出成功");
}

Parameters Description

参考视频参数,图片参数是视频参数的子集。区别点:图片导出没有回调方法,直接通过返回值返回错误信息。

Refer to the video parameters; image parameters are a subset of video parameters. Key difference: Image export does not use callback methods; error messages are returned directly via the return value.

Error Code

typedef NS_ENUM(NSInteger, INSExportSimplifyError) {
INSExportSimplifyErrorSuccess = 0,// Success
INSExportSimplifyErrorInitFailed = 3001, // Export failed
INSExportSimplifyErrorImageInitFailed = 4001, // Initialization failed
};

Logging

Within the INSCoreMedia library, log management tasks can be accomplished using the INSRegisterLogCallback class. This class offers a rich set of functionalities. First, it supports flexible configuration of log output paths. Developers can direct logs to specified files or storage locations based on project requirements, facilitating centralized log review and analysis later. Second, it features log level filtering. Logs of different levels—such as debug, info, warning, and error—hold varying importance during different stages of project development and operation. By configuring filter levels, developers can output only logs of specific levels or higher, reducing unnecessary log clutter and enhancing development and debugging efficiency.

Additionally, INSCoreMedia supports callback registration. Users can register callback functions to implement custom log processing within these callbacks. For instance, logs can be printed to the console in callbacks, enabling developers to view log content in real-time during debugging. Alternatively, logs can be stored as log files for detailed retrospective analysis and tracing, providing robust data support for project maintenance and optimization.

Configuring log output files:

/** 1. If the configuration includes file output for logging, the file path must be set. 2. Set the output log level; logs of this level or higher will be output.*/
- (void)configLogKind:(InsLogKind)kind minLogLevel:(InsLogLevel)level optionalFullFilePath:(NSString * __nullable)fullFilePath;

Registration callback:

/** Custom log received callbacks*/
- (void)registerLogCallBack:(void(^)(NSString *_Nonnull tag, InsLogLevel level, NSString * _Nonnull fileName, NSString * _Nonnull funcName, int line, NSString *_Nonnull message))block;
- (void)registerLogCallBackBmg:(void(^)(InsLogLevel level,NSString *_Nonnull message))block;

FAQ

Issues Related to URI Returned by HDR Capturing

  1. The x4 and x5 models support in-camera HDR merging. When in-camera merging is enabled, HDR synthesis occurs within the camera, resulting in a single merged image after processing.
  2. Cameras up to and including the X3 return multiple URIs when capturing HDR images. However, newer cameras such as the X4 and X5 return only one URI regardless of whether in-camera merging is enabled (not supported at the firmware level).

About

iOS SDK enables integration of Insta360 360 cameras into iOS apps for control and media management.

Resources

Stars

63 stars

Watchers

8 watching

Forks

Releases

Packages

Contributors