├── README.md └── README_zh.md /README.md: -------------------------------------------------------------------------------- 1 | # How to get? 2 | 3 | Please visit [https://www.insta360.com/sdk/apply](https://www.insta360.com/sdk/apply) to apply for the latest SDK. 4 | 5 | # Support 6 | 7 | Developers' Page: https://www.insta360.com/developer/home 8 | Insta360 Enterprise: https://www.insta360.com/enterprise 9 | Issue Report: https://insta.jinshuju.com/f/hZ4aMW 10 | 11 | # [中文文档](README_zh.md) 12 | 13 | # Overview 14 | 15 | 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. 16 | 17 | Supported models: X5, X4, X3, ONE X2, ONE X, ONE RS, ONE RS 1-Inch. 18 | 19 | # Table of contents 20 | * [INSCameraSDK](#inscamerasdk) 21 | * [Environmental preparation](#environmental-preparation) 22 | * [Camera connection and status](#camera-connection-and-status) 23 | * [Shooting mode](#shooting-mode) 24 | * [Camera parameters](#camera-parameters) 25 | * [Photo Capture](#photo-capture) 26 | * [Video Recording](#video-recording) 27 | * [Preview](#preview) 28 | * [Other features](#other-features) 29 | * [INSMediaSDK](#insmediasdk) 30 | * [Export (video)](#export-video) 31 | * [Export (image)](#export-image) 32 | 33 | # INSCameraSDK 34 | 35 | ## Environmental preparation 36 | 37 | ### Connect the camera via Wi-Fi 38 | 39 | - **Enable camera Wi-Fi function** 40 | 41 | Enable Wi-Fi function on the camera. 42 | 43 | - **Connect to Wi-Fi** 44 | 45 | In the Wi-Fi settings of your phone, find and select the corresponding camera name. 46 | 47 | - **Enter connection password** 48 | 49 | | Model | Password acquisition method | 50 | | -------- | ------------------------------------------------------------ | 51 | | X2 | Fixed password:`88888888` | 52 | | X3/X4/X5 | Manual acquisition: Camera screen → Settings → Wi-Fi → Show password
Bluetooth acquisition: see 1.2.3 | 53 | 54 | ### Connect the camera via Bluetooth 55 | 56 | After connecting the camera via Bluetooth, you can use shooting, recording and other functions normally, but it does not support real-time preview and file download. If you need preview function, you can get the WIFI name and password by calling the corresponding interface after Bluetooth pairing is successful, and then connect via wifi. 57 | 58 | #### Search for Bluetooth devices 59 | 60 | Call the following method to scan Bluetooth devices 61 | 62 | ```python 63 | INSBluetoothManager().scanCameras 64 | ``` 65 | 66 | #### Establish a Bluetooth connection 67 | 68 | Establish a Bluetooth connection using the following interface: 69 | 70 | ```c++ 71 | - (id)connectDevice:(INSBluetoothDevice *)device 72 | completion:(void (^)(NSError * _Nullable))completion; 73 | ``` 74 | 75 | #### Get camera wifi account and password 76 | 77 | After successful Bluetooth connection, call the interface to obtain Wi-Fi information. Example code is as follows: 78 | ```javascript 79 | let bluetoothManager = INSBluetoothManager() 80 | bluetoothManager.command(by: peripheral)?.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 81 | guard let options = options else { 82 | self?.showAlert(row.tag!, String(describing: err)) 83 | return 84 | } 85 | self?.showAlert("ssid:\(String(describing: options.wifiInfo?.ssid)) pw:\(String(describing: options.wifiInfo?.password))", String(describing: err)) 86 | } 87 | ``` 88 | 89 | ## Camera connection and camera status 90 | 91 | ### Connect the camera 92 | 93 | After connecting the camera via Wi-Fi, the interface in INSCameraSDK can be called to establish the connection. The interface uses singleton mode, and an instance is created when the first call is made, and the same instance is used to reuse in subsequent calls. 94 | 95 | ```c++ 96 | INSCameraManager.socket().setup() 97 | ``` 98 | 99 | ### Disconnect the camera 100 | 101 | When you need to disconnect from the camera, please call the following interface: 102 | 103 | ```c++ 104 | INSCameraManager.socket().shutdown() 105 | ``` 106 | 107 | ### Checking camera connection status 108 | 109 | Obtain the connection status of the camera through the following methods: 110 | 111 | ```swift 112 | INSCameraManager.socket().cameraState 113 | ``` 114 | 115 | Returning to the status, if the status is `INSCameraStateConnected`indicates that the connection has been successfully established. The status is defined as follows: 116 | 117 | ```c++ 118 | INSCameraManager.socket().cameraState 119 | 120 | // There are several states in total 121 | typedef NS_ENUM(NSUInteger, INSCameraState) { 122 | /// an insta360 camera is found, but not connected, will not response 123 | INSCameraStateFound, 124 | 125 | /// an insta360 camera is synchronized, but not connected, will not response 126 | INSCameraStateSynchronized, 127 | 128 | /// the nano device is connected, app is able to send requests 129 | INSCameraStateConnected, 130 | 131 | /// connect failed 132 | INSCameraStateConnectFailed, 133 | 134 | /// default state, no insta360 camera is found 135 | INSCameraStateNoConnection, 136 | }; 137 | ``` 138 | 139 | ## Shooting mode 140 | 141 | This section primarily introduces how to configure and retrieve various camera parameters, including shooting modes and photographic settings. The parameters are generally categorized into two types: numerical parameters (such as ISO, EV value, and shutter speed) and enumerated parameters (such as shooting mode, exposure mode, and resolution). 142 | 143 | ### Get the current shooting mode 144 | 145 | Use the interface `INSCameraManager.shared ().commandManager.getOptionsWithTypes`to obtain the shooting mode of the current camera. This method requires passing the following parameters: 146 | 147 | * **optionTypes** 148 | Specifies which parameters need to be retrieved, with each parameter corresponding to an enumeration value (see `INSCameraOptionsType`) that needs to be converted to an `NSNumber` array. 149 | * **requestOptions** 150 | Maximum configurable request timeout (default 10 seconds). 151 | * **completion** 152 | Return in callback: 153 | * `error`: `nil` indicates successful acquisition, otherwise contains the reason for the error. 154 | * `cameraOptions`: Contains the current camera shooting mode (shooting mode is `photoSubMode` or `videoSubMode`, see below for specific enumeration meanings). 155 | 156 | Enumeration of shooting modes: 157 | ```typescript 158 | // Take photo 159 | typedef NS_ENUM(NSUInteger, INSPhotoSubMode) { 160 | INSPhotoSubModeSingle = 0, 161 | INSPhotoSubModeHdr, 162 | INSPhotoSubModeInterval, 163 | INSPhotoSubModeBurst, 164 | INSPhotoSubModeNightscape, 165 | INSPhotoSubModeInstaPano, 166 | INSPhotoSubModeInstaPanoHdr, 167 | INSPhotoSubModeStarlapse, 168 | INSPhotoSubModeNone = 100, 169 | }; 170 | // Record video 171 | typedef NS_ENUM(NSUInteger, INSVideoSubMode) { 172 | INSVideoSubModeNormal = 0, 173 | INSVideoSubModeBulletTime, 174 | INSVideoSubModeTimelapse, 175 | INSVideoSubModeHDR, 176 | INSVideoSubModeTimeShift, 177 | INSVideoSubModeSuperVideo, 178 | INSVideoSubModeLoopRecording, 179 | INSVideoSubModeFPV, 180 | INSVideoSubModeMovieRecording, 181 | INSVideoSubModeSlowMotion, 182 | INSVideoSubModeSelfie, 183 | INSVideoSubModePure, 184 | INSVideoSubModeLiveview, 185 | INSVideoSubModeCameraLiveview, 186 | INSVideoSubModeDashCam, 187 | INSVideoSubModePTZ, 188 | INSVideoSubModeNone = 100, 189 | }; 190 | ``` 191 | 192 | Call demo: 193 | ```typescript 194 | func getCurrentCameraMode(completion: (()->Void)?)->Void{ 195 | 196 | let typeArray: [INSCameraOptionsType] = [.videoSubMode, .photoSubMode] 197 | 198 | let optionTypes = typeArray.map { (type) -> NSNumber in 199 | return NSNumber(value: type.rawValue) 200 | } 201 | let requestOptions = INSCameraRequestOptions() 202 | requestOptions.timeout = 10 203 | 204 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes, requestOptions: requestOptions) { [weak self] error, cameraOptions, _ in 205 | if let error = error { 206 | self?.showAlert("Failed", "The camera mode has been get failed: \(error.localizedDescription)") 207 | return 208 | } 209 | 210 | guard let cameraOptions = cameraOptions else {return} 211 | var captureMode: HUMCaptureMode? = nil 212 | if cameraOptions.photoSubMode != 100 { 213 | captureMode = HUMCaptureMode.modePhotoFrom(value: cameraOptions.photoSubMode) 214 | } 215 | else if cameraOptions.videoSubMode != 100 { 216 | captureMode = HUMCaptureMode.modeVideoFrom(value: cameraOptions.videoSubMode) 217 | } 218 | guard let mode = captureMode else {return} 219 | completion?() 220 | } 221 | } 222 | ``` 223 | 224 | ### Set shooting mode 225 | 226 | Configure the specified mode to the camera through the method: `INSCameraManager.shared ().commandManager.setOptions.` There are several important points in setting the shooting mode 227 | 228 | * **INSCameraOptions** 229 | It is used to carry the shooting mode configuration, mainly including the following two attributes: 230 | * `photoSubMode`:Camera mode 231 | * `videoSubMode`:Video mode 232 | 233 | * **INSCameraOptionsType** 234 | Used to specify which parameters in `INSCameraOptions` need to take effect. 235 | 236 | * Camera mode:`INSCameraOptionsType::INSCameraOptionsTypePhotoSubMode` 237 | * Video mode:`INSCameraOptionsType::INSCameraOptionsTypeVideoSubMode` 238 | 239 | The following is an example code (using setting the image shooting mode as an example): 240 | 241 | ```c++ 242 | // Picture shooting mode enumeration 243 | typedef NS_ENUM(NSUInteger, INSPhotoSubMode) { 244 | INSPhotoSubModeSingle = 0, 245 | INSPhotoSubModeHdr, 246 | INSPhotoSubModeInterval, 247 | INSPhotoSubModeBurst, 248 | INSPhotoSubModeNightscape, 249 | INSPhotoSubModeInstaPano, 250 | INSPhotoSubModeInstaPanoHdr, 251 | INSPhotoSubModeStarlapse, 252 | INSPhotoSubModeNone = 100, 253 | }; 254 | 255 | var typeArray: [INSCameraOptionsType] = [.photoSubMode] 256 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 257 | let cameraOptions = INSCameraOptions() 258 | cameraOptions.photoSubMode = INSPhotoSubMode.single 259 | 260 | INSCameraManager.shared().commandManager.setOptions(cameraOptions, forTypes: optionTypes) { [weak self] error, _ in 261 | if let error = error { 262 | self?.showAlert("Failed", "The camera mode has been set failed: \(error.localizedDescription)") 263 | print("Failed: The camera mode has been set failed: \(error.localizedDescription)") 264 | return 265 | } 266 | print("SUCCESS") 267 | } 268 | ``` 269 | 270 | ## Camera parameters 271 | 272 | Camera parameters are usually divided into two categories. The first is a specific numerical value, such as exposure ISO, EV value, shutter speed, etc. The second is an enumeration value, such as shooting mode, exposure mode, etc. For the former, you can directly assign values to the parameters in the `INSPhotographyOptions` and send them to the camera. For the latter, you need to check the meaning represented by the corresponding enumeration in the table, and then assign the corresponding enumeration value to the `INSPhotographyOptions`. The following is the relationship between resolution and its corresponding enumeration value. Other parameters can be viewed through the `"common_camera_setting_proto json"` file in the SDK project. 273 | 274 | ### Get camera parameters 275 | 276 | Get the camera through the method: `getPhotographyOptions` get. The main imported parameters required are three `functionMode` and `optionTypes`, as well as a closure callback. 277 | ```swift 278 | /*! 279 | * @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. 280 | * 281 | * @param functionMode the target function mode to get 282 | * @param optionTypes array of the INSPhotographyOptionsType to get 283 | * @param completion the callback block. If all succeed, error would be nil, if partial failed, error's code would be INSCameraErrorCodeAccept, if all fail, error's code would be the maximum error code. 284 | */ 285 | - (void)getPhotographyOptionsWithFunctionMode:(INSCameraFunctionMode*)functionMode 286 | types:(NSArray *)optionTypes 287 | completion:(void(^)(NSError * _Nullable error, 288 | INSPhotographyOptions * _Nullable options, 289 | NSArray * _Nullable successTypes))completion; 290 | ``` 291 | 292 | * `functionMode`: Indicates the current shooting mode 293 | * `optionTypes`: Each parameter corresponds to an enumeration value. 294 | * Corresponding to resolution: INSPhotographyOptionsTypePhotoSize = 40 295 | * White balance corresponds to: INSPhotographyOptionsTypeWhiteBalance = 13 296 | * Closure returns an `NSError` and `INSPhotographyOptions` 297 | * `NSError` is `nil` indicating success, otherwise it will include the reason for failure 298 | * `INSPhotographyOptions` contains the specific values of the current camera parameters, such as resolution, white balance, etc 299 | 300 | Sample code is as follows: Get the value of the current camera white balance 301 | ```swift 302 | var typeArray: [INSPhotographyOptionsType] = [.whiteBalanceValue] 303 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 304 | 305 | let functionMode = currentFunctionMode.functionMode 306 | 307 | 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 308 | } 309 | print("getPhotographyOptions Success!") 310 | print("whiteBalance: \(camerOptions?.whiteBalance ?? "N/A")") 311 | }) 312 | 313 | ``` 314 | 315 | 316 | ### Set camera parameters 317 | To set parameters for the camera, you need to use the following method:`INSCameraManager.shared().commandManager.setPhotographyOptions`, the main imported parameters are as follows. 318 | 319 | * `INSPhotographyOptions`: Store configured parameters 320 | 321 | * `INSPhotographyOptionsType`: Indicates which parameters need to be configured (each parameter corresponds to an enumeration). 322 | 323 | * `INSCameraFunctionMode`: Current shooting mode, current shooting mode. 324 | * Camera settings required shooting mode `INSCameraFunctionMode` and get from the camera shooting mode `INSPhotoSubMode` or `INSVideoSubMode` can not be directly converted, the corresponding relationship reference project file class: `HUMCaptureMode`. `HUMCaptureMode` will be the camera current mode INSPhotoSubMode or INSVideoSubMode into a unified INSCameraFunctionMode. 325 | 326 | * Closure callback: return whether the acquisition was successful 327 | 328 | > All parameter types can only be set to parameters supported on the camera screen and cannot be set arbitrarily 329 | 330 | Example code is as follows: Set specified white balance 331 | 332 | ```swift 333 | let functionMode = INSCameraFunctionMode.init(functionMode: 6) 334 | var typeArray: [INSPhotographyOptionsType] = [.whiteBalanceValue] 335 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 336 | 337 | option.whiteBalanceValue = 4000 338 | INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion: { [weak self] error, _ in 339 | guard let error = error else { 340 | self?.showAlert("Success", "set successfully") 341 | return 342 | } 343 | self?.showAlert("Failed", "set failed: \(error.localizedDescription)") 344 | }) 345 | ``` 346 | 347 | ### Numeric type 348 | 349 | #### White balance 350 | 351 | * The properties in `INSPhotographyOptions` are: 352 | ```objective-c 353 | @property (nonatomic) uint32_t whiteBalanceValue; 354 | ``` 355 | * The corresponding enumeration in `INSPhotographyOptionsType` is: 356 | ```objective-c 357 | INSPhotographyOptionsTypeWhiteBalance = 13 358 | ``` 359 | * Suppose the current shooting mode `INSCameraFunctionMode 6 `represents normal photography. 360 | 361 | #### ExposureBias (Only auto exposure supports "AUTO") 362 | 363 | > Adjustment supported only in exposure mode "AUTO" "FULL\_AUTO" 364 | 365 | * `INSPhotographyOptions` properties are: exposureBias 366 | ```objective-c 367 | @property (nonatomic) float exposureBias; 368 | ``` 369 | 370 | * The corresponding enumeration in `INSPhotographyOptionsType` is: 371 | ```objective-c 372 | INSPhotographyOptionsTypeExposureBias = 7 373 | ``` 374 | 375 | #### ISO,shutterSpeed 376 | 377 | > Adjustment is supported only in exposure modes "MANUAL" and "ISO\_PRIORITY" 378 | 379 | * `INSPhotographyOptions` properties are: stillExposure.iso, stillExposure.shutterSpeed 380 | 381 | ```objective-c 382 | @property (nullable, nonatomic) INSCameraExposureOptions *stillExposure; 383 | 384 | 385 | @interface INSCameraExposureOptions : NSObject 386 | 387 | @property (nonatomic) uint8_t program; 388 | 389 | @property (nonatomic) NSUInteger iso; 390 | 391 | #if TARGET_OS_IOS 392 | @property (nonatomic) CMTime shutterSpeed; 393 | #endif 394 | 395 | @end 396 | ``` 397 | 398 | * The corresponding enumeration in `INSPhotographyOptionsType` is: 399 | 400 | ```objective-c 401 | INSPhotographyOptionsTypeStillExposureOptions = 20 402 | ``` 403 | 404 | ### Enumeration and Bool 405 | 406 | #### Photo resolution 407 | 408 | * `INSPhotographyOptions` properties are: photoSizeForJson 409 | * PhotoSizeForJson = 17, indicating that the resolution of the X4 camera is 8192 x 6144. 410 | * The corresponding enumeration in INSPhotographyOptionsType is: 411 | 412 | ```objective-c 413 | INSPhotographyOptionsTypePhotoSize = 40 414 | ``` 415 | 416 | * Suppose the current shooting mode `INSCameraFunctionMode 6` represents normal photography. 417 | 418 | Code example: 419 | ```swift 420 | let functionMode = INSCameraFunctionMode.init(functionMode: 6) 421 | var typeArray: [INSPhotographyOptionsType] = [.photoSize] 422 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 423 | 424 | options.isUseJsonOptions = true 425 | option.photoSizeForJson = 17 426 | 427 | INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion: { [weak self] error, _ in 428 | guard let error = error else { 429 | self?.showAlert("Success", " set successfully") 430 | return 431 | } 432 | self?.showAlert("Failed", "set failed: \(error.localizedDescription)") 433 | }) 434 | ``` 435 | 436 | Correspondence between resolution and enumeration values 437 | ```swift 438 | "photo_resolution": { 439 | "6912_3456": "0", // X3 18MP 440 | "6272_3136": "1", 441 | "6080_3040": "2", 442 | "4000_3000": "3", 443 | "4000_2250": "4", 444 | "5212_3542": "5", 445 | "5312_2988": "6", 446 | "8000_6000": "7", 447 | "8000_4500": "8", 448 | "2976_2976": "9", 449 | "5984_5984": "10", 450 | "11968_5984": "11", 451 | "5952_2976": "12", // 72MP 452 | "8192_6144": "17", // X4 18MP 453 | "8192_4608": "18", 454 | "4096_3072": "19", 455 | "4096_2304": "20", 456 | "7680_3840": "21", 457 | "3840_3840": "22" 458 | } 459 | ``` 460 | 461 | #### Exposure mode 462 | 463 | * The properties in `INSPhotographyOptions` are: 464 | ```objective-c 465 | @property (nullable, nonatomic) INSCameraExposureOptions *stillExposure; 466 | 467 | 468 | @interface INSCameraExposureOptions : NSObject 469 | 470 | @property (nonatomic) uint8_t program; // Exposure mode 471 | 472 | @property (nonatomic) NSUInteger iso; 473 | 474 | #if TARGET_OS_IOS 475 | @property (nonatomic) CMTime shutterSpeed; 476 | #endif 477 | 478 | @end 479 | ``` 480 | 481 | * The corresponding enumeration in `INSPhotographyOptionsType` is: 482 | ```objective-c 483 | INSPhotographyOptionsTypeStillExposureOptions = 20 484 | ``` 485 | 486 | ```json 487 | "exposure_program": { 488 | "AUTO": "0", 489 | "ISO_PRIORITY": "1", 490 | "SHUTTER_PRIORITY": "2", 491 | "MANUAL": "3", 492 | "ADAPTIVE": "4", 493 | "FULL_AUTO": "5" 494 | }, 495 | ``` 496 | 497 | > Support setting multiple parameters to the camera at the same time, as follows: 498 | ```swift 499 | var typeArray: [INSPhotographyOptionsType] = [.photoSize, .whiteBalanceValue] 500 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 501 | 502 | option.photoSizeForJson = 11 503 | option.whiteBalanceValue = 4000 504 | 505 | INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion: { [weak self] error, _ in 506 | guard let error = error else { 507 | self?.showAlert("Success", "The camera resolution has been set successfully") 508 | return 509 | } 510 | self?.showAlert("Failed", "The camera resolution has been set failed: \(error.localizedDescription)") 511 | 512 | completion?() 513 | }) 514 | ``` 515 | #### Pureshot 516 | 517 | > Note: X5 has PureShot turned on by default and does not support turning it off 518 | 519 | * The properties in `INSPhotographyOptions` are: 520 | 521 | ```objective-c 522 | @property (nonatomic) uint8_t rawCaptureType; 523 | ``` 524 | 525 | * The corresponding enumeration in `INSPhotographyOptionsType` is: 526 | 527 | ```objective-c 528 | INSPhotographyOptionsTypeRawCaptureType = 25, 529 | ``` 530 | 531 | * Enumeration type: 532 | 533 | ```json 534 | "raw_capture_type": { 535 | "OFF": "0", 536 | "RAW": "1", 537 | "PURESHOT": "3", 538 | "PURESHOT_RAW": "4", 539 | "INSP": "5", 540 | "INSP_RAW": "6" 541 | }, 542 | ``` 543 | 544 | #### In-camera Stitching (Bool) 545 | 546 | When taking pictures, stitch panoramic images inside the camera without the need for external stitching. Only cameras after X4 are supported. 547 | 548 | ```swift 549 | var typeArray = [INSCameraOptionsType]() 550 | let cameraOptions = INSCameraOptions() 551 | 552 | // Open is true, close is false 553 | cameraOptions.enableInternalSplicing = true 554 | typeArray.append(.internalSplicing) 555 | 556 | let optionTypes = typeArray.map { (type) -> NSNumber in 557 | return NSNumber(value: type.rawValue) 558 | } 559 | INSCameraManager.shared().commandManager.setOptions(cameraOptions, forTypes: optionTypes) { [weak self] error, _ in 560 | if let error = error { 561 | self?.showAlert("Failed", "The camera mode has been set failed: \(error.localizedDescription)") 562 | return 563 | } 564 | completion?() 565 | } 566 | ``` 567 | 568 | ## Photo Capture 569 | 570 | Send shooting instructions to the camera through the `"INSCameraManager.shared ().commandManager.takePicture"` method. If the error is nil, it means the shooting is successful, otherwise it contains error information. The remote access address of the photo is included in optionInfo, which can be exported remotely (without downloading to the local). 571 | ```bash 572 | INSCameraManager.shared().commandManager.takePicture(with: nil, completion: { (error, optionInfo) in 573 | 574 | print("end takePicture \(Date())") 575 | guard let uri = optionInfo?.uri else { 576 | return 577 | } 578 | print("Take Picture Url:\(uri)")\ 579 | }) 580 | ``` 581 | 582 | ## Video Recording 583 | 584 | Start recording: 585 | ```python 586 | INSCameraManager.shared().commandManager.startCapture(with: nil, completion: { (err) in 587 | if let err = err { 588 | self.showAlert(row.tag!, "\(String(describing: err))") 589 | return 590 | } 591 | }) 592 | ``` 593 | 594 | Stop recording: 595 | ```python 596 | INSCameraManager.shared().commandManager.stopCapture(with: nil, completion: { (err, info) in 597 | if let err = err { 598 | self.showAlert(row.tag!, "\(String(describing: err))") 599 | return 600 | } 601 | }) 602 | ``` 603 | 604 | ## Preview 605 | 606 | Preview must be done after establishing a connection with the camera. There are several core classes. Please refer to the demo for details: CameraConfigByJsonController. 607 | 608 | * INSCameraSessionPlayer 609 | * Bind bounds on the iOS side. 610 | * Implementation Agreement: INSCameraSessionPlayerDelegate. 611 | * Implementation protocol: INSCameraSessionPlayerDataSource, it is recommended to implement the following two protocols: 612 | Configure offset information: updateOffsetToPlayer. 613 | Configure stabilization information: updateStabilizerParamToPlayer. 614 | * INSCameraMediaSession 615 | ```swift 616 | func setupRenderView() { 617 | var frame = self.view.bounds; 618 | let height = frame.size.width * 0.667 619 | frame.origin.x = 0 620 | frame.origin.y = frame.size.height - height 621 | frame.size.height = height 622 | 623 | newPlayer = INSCameraSessionPlayer() 624 | newPlayer?.delegate = self 625 | newPlayer?.dataSource = self 626 | newPlayer?.render.renderModelType.displayType = .sphereStitch 627 | 628 | if let view = newPlayer?.renderView { 629 | view.frame = frame; 630 | print("预览流: getView = \(view), frame = \(frame)") 631 | self.view.addSubview(view) 632 | } 633 | 634 | let config = INSH264DecoderConfig() 635 | config.shouldReloadDecoder = false 636 | config.decodeErrorMaxCount = 30 637 | config.debugLiveStrem = false 638 | config.debugLog = false 639 | self.mediaSession.setDecoderConfig(config) 640 | } 641 | ``` 642 | 643 | 644 | 645 | ## Other features 646 | 647 | ### Firmware upgrade 648 | 649 | Proactively upgrade by calling updateFirwareWithOptions interface. INSCameraWriteFileOptions 650 | ```markdown 651 | @interface INSCameraWriteFileOptions : NSObject 652 | 653 | /// file type of data to write 654 | @property (nonatomic) INSCameraFileType fileType; 655 | 656 | /// data of a file. if fileType is photo, data should be encoded in JPG format. 657 | @property (nonatomic) NSData *data; 658 | 659 | /// destinate path of the file in camera, if nil, camera will decide the uri with fileType. 660 | @property (nonatomic, nullable) NSString *uri; 661 | 662 | @end 663 | 664 | 665 | - (void)updateFirwareWithOptions:(INSCameraWriteFileOptions *)options 666 | completion:(void (^)(NSError * _Nullable))completion; 667 | ``` 668 | 669 | ### Activate 670 | 671 | Appid and secret need to be requested from Insta360. 672 | ```swift 673 | guard let serialNumber = INSCameraManager.shared().currentCamera?.serialNumber else { 674 | self?.showAlert("提示", "请先连接相机") 675 | return 676 | } 677 | let commandManager = INSCameraManager.shared().commandManager 678 | 679 | // "提示" means "Note", "请先连接相机" means "Please connect the camera first." 680 | 681 | //You need to apply, fill in your real appid and secret. 682 | INSCameraActivateManager.setAppid("Appid", secret: "secret") 683 | 684 | INSCameraActivateManager.share().activateCamera(withSerial: serialNumber, commandManager: commandManager) { deviceInfo, error in 685 | if let activateError = error { 686 | self?.showAlert("Activate to \(serialNumber)", String(describing: activateError)) 687 | } else { 688 | let deviceType = deviceInfo?["deviceType"] ?? "" 689 | let serialNumber = deviceInfo?["serial"] ?? "" 690 | self?.showAlert("Activate to success", "deviceType: \(deviceType), serial: \(serialNumber)") 691 | } 692 | } 693 | ``` 694 | 695 | ### Get SD card status 696 | 697 | ```swift 698 | let optionTypes = [ 699 | NSNumber(value: INSCameraOptionsType.storageState.rawValue), 700 | ]; 701 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 702 | guard let options = options else { 703 | self.showAlert("get options", String(describing: err)) 704 | return 705 | } 706 | var sdCardStatus = "error" 707 | switch options.storageStatus?.cardState { 708 | case .normal: 709 | sdCardStatus = "Normal" 710 | break 711 | case .noCard: 712 | sdCardStatus = "NoCard" 713 | break 714 | case .noSpace: 715 | sdCardStatus = "NoSpace" 716 | break 717 | case .invalidFormat: 718 | sdCardStatus = "INvalid Format" 719 | break 720 | case .writeProtectCard: 721 | sdCardStatus = "Write Protect Card" 722 | break 723 | case .unknownError: 724 | sdCardStatus = "UnknownError" 725 | break 726 | default: 727 | sdCardStatus = "Status Error" 728 | } 729 | } 730 | ``` 731 | 732 | ### Get current battery level 733 | 734 | ```javascript 735 | let optionTypes = [ 736 | NSNumber(value: INSCameraOptionsType.batteryStatus.rawValue), 737 | ]; 738 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 739 | guard let options = options else { 740 | self.showAlert("get options", String(describing: err)) 741 | return 742 | } 743 | print("battery: \(options.batteryStatus!.batteryLevel)") 744 | } 745 | ``` 746 | 747 | ### Get activation time 748 | 749 | ```swift 750 | let optionTypes = [ 751 | NSNumber(value: INSCameraOptionsType.activateTime.rawValue), 752 | ]; 753 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 754 | guard let options = options else { 755 | self.showAlert("get options", String(describing: err)) 756 | return 757 | } 758 | // Activation time 759 | let formatter = DateFormatter() 760 | formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" 761 | let date = Date(timeIntervalSince1970: Double(options.activateTime / 1000)) 762 | print("date :\(date)") 763 | 764 | } 765 | ``` 766 | 767 | ### Silent switch 768 | 769 | ```swift 770 | let optionTypes = [ 771 | NSNumber(value: INSCameraOptionsType.mute.rawValue), 772 | ]; 773 | 774 | let options = INSCameraOptions() 775 | options.mute = true 776 | 777 | INSCameraManager.socket().commandManager.setOptions(options, forTypes: optionTypes, completion: {error,successTypes in 778 | if let error = error { 779 | print("Error:\(error)") 780 | return 781 | } 782 | 783 | print("Success") 784 | }) 785 | ``` 786 | 787 | ### Serial number 788 | 789 | It can be called after establishing a connection with the camera 790 | ```swift 791 | INSCameraManager.shared().currentCamera?.serialNumber 792 | ``` 793 | 794 | ### Firmware version number 795 | 796 | ```swift 797 | INSCameraManager.shared().currentCamera?.firmwareRevision 798 | ``` 799 | 800 | ### Turn off camera 801 | The command to control the camera to close, currently only supports the X5 camera. The example is as follows: 802 | ```swift 803 | INSCameraManager.socket().commandManager.closeCamera({_ in}) 804 | ``` 805 | 806 | ### LOG management 807 | 808 | In INSCameraSDK, all the logs generated by it will be passed to the upper layer in the form of callbacks by means of the `INSCameraSDKLoggerProtocol` protocol. For the upper layer, after receiving these logs, it can choose to print out the logs, which is convenient for developers to view the relevant information in the running process of the SDK during the debugging phase, and can also store the logs for subsequent Data Analysis or troubleshooting. If you want to know more detailed operations and configurations, you can refer to the `CameraConfigByJsonController`. 809 | 810 | INSCameraSDKLogger takes a singleton as the carrier of the `INSCameraSDKLoggerProtocol`, and the `logDelegate` property needs to be configured to carry `INSCameraSDKLoggerProtocol` callbacks. 811 | 812 | ```swift 813 | @protocol INSCameraSDKLoggerProtocol 814 | 815 | - (void)logError:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 816 | - (void)logWarning:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 817 | - (void)logInfo:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 818 | - (void)logDebug:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 819 | 820 | - (void)logCrash:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 821 | 822 | @end 823 | ``` 824 | 825 | ### Error code 826 | 827 | ```objective-c 828 | typedef NS_ENUM(NSUInteger, INSCameraErrorCode) { 829 | /// ok 830 | INSCameraErrorCodeOK = 200, 831 | 832 | /// accepted 833 | INSCameraErrorCodeAccept = 202, 834 | 835 | /// mainly means redirection 836 | INSCameraErrorCodeMovedTemporarily = 302, 837 | 838 | /// bad request, check your params 839 | INSCameraErrorCodeBadRequest = 400, 840 | 841 | /// the command has timed out 842 | INSCameraErrorCodeTimeout = 408, 843 | 844 | /// the requests are sent too often 845 | INSCameraErrorCodeTooManyRequests = 429, 846 | 847 | /// request is interrupted and no response has been gotten 848 | INSCameraErrorCodeNoResopnse = 444, 849 | 850 | INSCameraErrorCodeShakeHandeError = 445, 851 | 852 | INSCameraErrorCodePairError = 446, 853 | 854 | /// error on camera 855 | INSCameraErrorCodeInternalServerError = 500, 856 | 857 | /// the command is not implemented for this camera or firmware 858 | INSCameraErrorCodeNotImplemented = 501, 859 | 860 | /// there is no connection 861 | INSCameraErrorCodeNoConnection = 503, 862 | 863 | /// firmware error 864 | INSCameraErrorCodeFirmwareError = 504, 865 | 866 | /// Invalid Request 867 | INSCameraErrorCodeInvalidRequest = 505, 868 | 869 | /// bluetooth not inited 870 | INSCameraErrorCodeCentralManagerNotInited = 601, 871 | }; 872 | ``` 873 | 874 | # INSMediaSDK 875 | 876 | ## Export (video) 877 | 878 | Video Export: Provides a simplified export method `INSExportSimplify` specifically for tob users, located in `INSCoreMedia`. This class is mainly used to simplify the operation of video export, providing a series of configurable properties and methods to facilitate developers to customize the export process according to their needs. (Only supports exporting videos). 879 | ### Instructions for use 880 | 881 | This method can ensure the basic export effect, and all parameters used for export are default values. Users can configure relevant parameters according to specific needs. 882 | 883 | #### Initialization method 884 | 885 | ```objective-c 886 | -(nonnull instancetype)initWithURLs:(nonnull NSArray)urls outputUrl:(nonnull NSURL*)outputUrl; 887 | ``` 888 | * **Function**: Initialize the `INSExportSimplify` object to specify the URL array of the input video file and the URL of the output video file. 889 | 890 | * **Parameters**: 891 | * `urls`: Enter the URL array of the video file, it cannot be empty. 892 | * `outputUrl`: Output the URL of the video file, cannot be empty. 893 | 894 | * **Return value**: Returns an `INSExportSimplify` object. 895 | 896 | * **Example code:** 897 | 898 | ```objective-c 899 | NSArray *inputUrls = @[[NSURL fileURLWithPath:@"path/to/input1.mp4"], [NSURL fileURLWithPath:@"path/to/input2.mp4"]]; 900 | NSURL *outputUrl = [NSURL fileURLWithPath:@"path/to/output.mp4"]; 901 | INSExportSimplify *exporter = [[INSExportSimplify alloc] initWithURLs:inputUrls outputUrl:outputUrl]; 902 | ``` 903 | 904 | #### Start exporting 905 | 906 | ```objective-c 907 | -(nullable NSError*)start; 908 | ``` 909 | 910 | #### Cancel export 911 | 912 | ```objective-c 913 | -(void)cancel; 914 | ``` 915 | 916 | #### Destroy export 917 | 918 | Cancel the export. After the export is completed, be sure to call it actively, otherwise it may cause a crash. 919 | 920 | ```objective-c 921 | -(void)shutDown; 922 | ``` 923 | 924 | ### Parameter description 925 | 926 | #### Export resolution 927 | 928 | This interface is used to output image resolution (aspect ratio must be 2:1) 929 | ```objective-c 930 | /** 931 | * Default width and height: 1920 * 960 (the exported image ratio needs to be 2:1). 932 | */ 933 | @property (nonatomic) int width; 934 | @property (nonatomic) int height; 935 | ``` 936 | 937 | #### **Stitching Type**(opticalFlowType) 938 | 939 | There are a total of four stitching type, namely template stitching, dynamic stitching, optical flow stitching, and AI stitching (not supported yet). 940 | * **Template Stitching**: An older stitching algorithm that provides poor stitching results for near-field scenes, but is fast and has low computational cost. 941 | * **Dynamic Stitching**: Suitable for scenes containing motion or situations with rapid changes in movement. 942 | * **Optical Flow Stitching**: Similar in function to dynamic stitching but optimized for higher accuracy. 943 | * **AI Stitching**: Based on Insta360’s optimized optical flow stitching technology, offering superior stitching results. 944 | ```objective-c 945 | typedef NS_ENUM(NSInteger, INSOpticalFlowType) { 946 | // Dynamic Stitching 947 | INSOpticalFlowTypeDynamicStitch = 0, 948 | // Optical Flow Stitching 949 | INSOpticalFlowTypeDisflow = 1, 950 | // AI Stitching 951 | INSOpticalFlowTypeAiFlow = 2, 952 | }; 953 | ``` 954 | 955 | #### Stabilization mode(stabMode) 956 | 957 | The Stabilization mode supports the following types in total, and there are two commonly used ones, enable stabilization and directional locking. 958 | - Enable Stabilization: No matter how the camera is rotated, the camera image remains unchanged. 959 | - Enable Direction Lock: The viewing angle always rotates with the camera 960 | ```objective-c 961 | /** 962 | * Stabilization mode, default INSStabilizerStabModeZDirectional 963 | */ 964 | @property (nonatomic)INSStabilizerStabMode stabMode; 965 | ``` 966 | 967 | ```objective-c 968 | typedef NS_ENUM(NSInteger, INSStabilizerStabMode) { 969 | /// Turn off stabilization 970 | INSStabilizerStabModeOff = -1, 971 | /// Enable Stabilization 972 | INSStabilizerStabModeStill, 973 | /// Remove the Stabilization in the yaw direction, used for directional locking, view can only move arround z-axis (pan move) 974 | INSStabilizerStabModeZDirectional, 975 | /// Turn on Stabilization and turn on horizontal correction, that is, full-direcional. 976 | INSStabilizerStabModeFullDirectional, 977 | /// Uncalibrated horizon, i.e. free-footage, total free camera mode, camera can move through three axes 978 | INSStabilizerStabModeFreeFootage, 979 | /// Handling flip 980 | INSStabilizerStabModeFlipEffect, 981 | /// Turn on Stabilization and average posture correction, that is, relative-refine. 982 | INSStabilizerStabModeRelativeRefine, 983 | /// Turn on Stabilization and turn on horizontal correction, that is, absulute-refine. 984 | INSStabilizerStabModeAbsoluteRefine, 985 | /// Bullet time 986 | INSStabilizerStabModeBulletTime, 987 | /// Pano Fpv 988 | INSStabilizerStabModePanoFPV 989 | }; 990 | ``` 991 | #### Lens Guard 992 | 993 | If lens guards are worn during shooting, this parameter needs to be configured according to the type. (Standard lens guards in the store are classified as A-grade, while Premium guards are classified as S-grade.) 994 | ```objective-c 995 | /** 996 | * Lens Guard 997 | */ 998 | @property (nonatomic) INSOffsetConvertOptions protectType; 999 | ``` 1000 | 1001 | ```objective-c 1002 | typedef NS_ENUM(NSInteger, INSProtectType) { 1003 | // No Lens Guard 1004 | INSProtectTypeNone = 0, 1005 | // X3 S-grade 1006 | INSProtectType_OneX3_Glass = 1, 1007 | // X3 A-grade 1008 | INSProtectType_OneX3_PlasticCement = 2, 1009 | // X4 S-grade 1010 | INSProtectType_OneX4_Glass = 3, 1011 | // X4 A-grade 1012 | INSProtectType_OneX4_PlasticCement = 4, 1013 | }; 1014 | ``` 1015 | #### Chromatic Calibration(colorFusion) 1016 | 1017 | ```objective-c 1018 | /** 1019 | * Chromatic Calibration fault: false 1020 | */ 1021 | @property (nonatomic) BOOL colorFusion; 1022 | ``` 1023 | 1024 | The main reasons for color difference are as follows: 1025 | 1026 | * Firstly, due to the fact that the two lenses are separated, their respective video exposures may not be consistent. When they are spliced together, there will be a noticeable brightness difference. This is because there are differences in parameter settings and photosensitive element performance during shooting between different lenses, resulting in different light intensities captured. 1027 | 1028 | * Secondly, because the lighting on both sides of the lens is different and the camera exposure is different, sometimes there will be a significant brightness difference in the images taken by the front and rear lenses. This phenomenon is particularly evident in areas with large light aberration ratios, such as areas where strong light meets shadows, or in environments with large differences in indoor and outdoor light. In these cases, the camera finds it difficult to balance the light intensity in different areas, resulting in significant differences in brightness in the captured images. 1029 | 1030 | It is precisely to solve such problems that chromatic calibration technology has been developed. It adjusts and optimizes the images captured by different lenses through a series of algorithms and image processing methods to reduce or eliminate brightness differences, making the spliced video look more natural and coherent. 1031 | 1032 | #### Removing purple fringing(defringeConfig) 1033 | 1034 | This interface has the function of eliminating specific phenomena. Specifically, it is specifically used to eliminate the purple edge phenomenon caused by lighting factors during the recording process. In actual recording scenes, the lighting conditions are complex and changeable. This interface can specifically solve the purple edge problem that occurs in two common lighting scenes. The first is the outdoor strong light scene. When recording in strong sunlight during the day, the outdoor high-intensity light is prone to cause the purple edge phenomenon. This interface can effectively eliminate the purple edge phenomenon in this scene. The second is the indoor lighting scene. The light emitted by different types of indoor lights such as incandescent lamps and fluorescent lamps may also cause the recorded image to appear purple edge. This interface can also eliminate the purple edge phenomenon in this indoor lighting scene. 1035 | 1036 | Usage: To use this algorithm, you need to configure the corresponding model, which is managed by a json file (coreml_model_v2_scale6_scale4 json). You need to copy these models and json files to the App. Please refer to the following code for parameter configuration 1037 | 1038 | **Video:** 1039 | 1040 | ```javascript 1041 | let jsonFilePath: String = Bundle.main.path(forResource: "coreml_model_v2_scale6_scale4", ofType: "json")! 1042 | let components = jsonFilePath.split(separator: "/") 1043 | let modelFilePath = components.dropLast().joined(separator: "/") 1044 | 1045 | var jsonContent = "" 1046 | do { 1047 | let data = try Data(contentsOf: URL(fileURLWithPath: jsonFilePath)) 1048 | jsonContent = String(data: data, encoding: .utf8) ?? "" 1049 | } catch { 1050 | assertionFailure("\(jsonFilePath)文件无法读取") 1051 | } 1052 | 1053 | let initInfo = INSDePurpleFringeFilterInitInfo.init(imageTransferType: .AUTO, algoAccelType: .AUTO) 1054 | 1055 | let depurpleFringInfo = INSDePurpleFringeFilterInfo() 1056 | depurpleFringInfo.setInit(initInfo) 1057 | depurpleFringInfo.setModelJsonContent(jsonContent) 1058 | depurpleFringInfo.setModelFilePath(modelFilePath) 1059 | ``` 1060 | 1061 | **Picture:** 1062 | 1063 | ```javascript 1064 | let jsonFilePath: String = Bundle.main.path(forResource: "coreml_model_v2_scale6_scale4", ofType: "json")! 1065 | let components = jsonFilePath.split(separator: "/") 1066 | let modelFilePath = components.dropLast().joined(separator: "/") 1067 | var jsonContent = "" 1068 | do { 1069 | let data = try Data(contentsOf: URL(fileURLWithPath: jsonFilePath)) 1070 | jsonContent = String(data: data, encoding: .utf8) ?? "" 1071 | } catch { 1072 | assertionFailure("\(jsonFilePath)文件无法读取") 1073 | } 1074 | 1075 | let depurpleFringInfo = INSExporter2DefringConfiguration.init() 1076 | depurpleFringInfo.modelJsonContent = jsonContent 1077 | depurpleFringInfo.modelFilePath = modelFilePath 1078 | depurpleFringInfo.enableDetect = true 1079 | depurpleFringInfo.useFastInferSpeed = false 1080 | videoExporter?.defringeConfig = depurpleFringInfo 1081 | ``` 1082 | 1083 | #### Progress and status callbacks 1084 | 1085 | Once you start exporting, the protocol (INSRExporter2ManagerDelegate) pulls back the progress and status of the export in real time. 1086 | 1087 | ```objective-c 1088 | typedef NS_ENUM(NSInteger, INSExporter2State) { 1089 | INSExporter2StateError = -1, // Indicates that an error occurred during the export process 1090 | INSExporter2StateComplete = 0, // Indicates that the export was successfully completed 1091 | INSExporter2StateCancel = 1, // Indicates that the user manually canceled the export operation 1092 | INSExporter2StateInterrupt = 2, // Indicates that export was unexpectedly interrupted 1093 | INSExporter2StateDisconnect = 3, // Indicates disconnection from the server 1094 | INSExporter2StateInitError = 4, // Indicates that an error occurred during initialization 1095 | }; 1096 | ``` 1097 | 1098 | ```objective-c 1099 | @protocol INSRExporter2ManagerDelegate 1100 | 1101 | - (void)exporter2Manager:(INSExporter2Manager *)manager progress:(float)progress; 1102 | 1103 | - (void)exporter2Manager:(INSExporter2Manager *)manager state:(INSExporter2State)state error:(nullable NSError*)error; 1104 | 1105 | // For panoramic event tracking detection (generally not used) 1106 | - (void)exporter2Manager:(INSExporter2Manager *)manager correctOffset:(NSString*)correctOffset errorNum:(int)errorNum totalNum:(int)totalNum clipIndex:(int)clipIndex type:(NSString*)type; 1107 | @end 1108 | ``` 1109 | 1110 | #### Error code 1111 | 1112 | Export error code. 1113 | 1114 | ```objective-c 1115 | typedef NS_ENUM(NSInteger, INSExporter2State) { 1116 | INSExporter2StateError = -1, // Indicates that an error occurred during the export process 1117 | INSExporter2StateComplete = 0, // Indicates that the export was successfully completed 1118 | INSExporter2StateCancel = 1, // Indicates that the user manually canceled the export operation 1119 | INSExporter2StateInterrupt = 2, // Indicates that export was unexpectedly interrupted 1120 | INSExporter2StateDisconnect = 3, // Indicates disconnection from the server 1121 | INSExporter2StateInitError = 4, // Indicates that an error occurred during initialization 1122 | }; 1123 | ``` 1124 | 1125 | ## Export (image) 1126 | 1127 | ### Instructions for use 1128 | 1129 | Image Export: `INSExportImageSimplify` class belongs to the `INSCoreMedia` framework. This class aims to simplify image export operations, providing a series of configurable properties and methods, supporting the export of `normal` and `HDR` images, allowing developers to customize the export process according to their needs. 1130 | 1131 | #### Export normal image 1132 | 1133 | ```objective-c 1134 | - (NSError*)exportImageWithInputUrl:(nonnull NSURL *)inputUrl outputUrl:(nonnull NSURL *)outputUrl; 1135 | ``` 1136 | 1137 | * **Function**: Export normal images, support remote or local images. Support remote and local 1138 | 1139 | * **Parameter**: 1140 | * `inputUrl`: The URL of the input image cannot be empty. 1141 | * `outputUrl`: The URL of the output image cannot be empty. 1142 | 1143 | * **Return value**: If an error occurs during the export process, return an `NSError` object; if the export is successful, return `nil`. 1144 | 1145 | * **Example code**: 1146 | 1147 | ```objective-c 1148 | INSExportImageSimplify *exporter = [[INSExportImageSimplify alloc] init]; 1149 | NSURL *inputUrl = [NSURL fileURLWithPath:@"path/to/input.jpg"]; 1150 | NSURL *outputUrl = [NSURL fileURLWithPath:@"path/to/output.jpg"]; 1151 | NSError *error = [exporter exportImageWithInputUrl:inputUrl outputUrl:outputUrl]; 1152 | if (error) { 1153 | NSLog(@"导出失败:%@", error.localizedDescription); 1154 | } else { 1155 | NSLog(@"导出成功"); 1156 | } 1157 | ``` 1158 | 1159 | #### Export HDR image method (only supports local HDR images) 1160 | 1161 | ```objective-c 1162 | - (NSError*)exportHdrImageWithInputUrl:(nonnull NSArray *)inputUrl outputUrl:(nonnull NSURL *)outputUrl; 1163 | ``` 1164 | 1165 | * **Function**: 1166 | * This feature is mainly used to export high dynamic range (HDR) images. It only supports local images, which means that the images must be stored on the local device for export operation. In addition, to ensure the quality and effect of export, the number of input images is required to be at least 3. 1167 | 1168 | * **Parameters**: 1169 | * `inputUrl`: This is an array of URLs for input images. The array cannot be empty and the number of elements in it must be greater than or equal to 3. These URLs point to local images that need to be exported through HDR. 1170 | * `outputUrl`: Specify the URL of the output image. Similarly, this parameter cannot be empty and is used to determine the storage location of the exported HDR image. 1171 | 1172 | * **Return value**: 1173 | * During the export process, if any errors occur, an `NSError` object will be returned. This object contains detailed information about the error for developers to handle and debug. 1174 | * If the export is successful and no errors occur, the return value will be `nil`, indicating that the operation is successfully completed. 1175 | 1176 | * **Example code**: 1177 | ```objective-c 1178 | INSExportImageSimplify *exporter = [[INSExportImageSimplify alloc] init]; 1179 | NSArray *inputUrls = @[[NSURL fileURLWithPath:@"path/to/input1.jpg"], [NSURL fileURLWithPath:@"path/to/input2.jpg"], [NSURL fileURLWithPath:@"path/to/input3.jpg"]]; 1180 | NSURL *outputUrl = [NSURL fileURLWithPath:@"path/to/output_hdr.jpg"]; 1181 | NSError *error = [exporter exportHdrImageWithInputUrl:inputUrls outputUrl:outputUrl]; 1182 | if (error) { 1183 | NSLog(@"导出失败:%@", error.localizedDescription); 1184 | } else { 1185 | NSLog(@"导出成功"); 1186 | } 1187 | 1188 | //"导出失败" means "Export failed". "导出成功" means "Export successful". 1189 | ``` 1190 | 1191 | #### Error code 1192 | 1193 | ```objective-c 1194 | typedef NS_ENUM(NSInteger, INSExportSimplifyError) { 1195 | INSExportSimplifyErrorSuccess = 0, // Success 1196 | INSExportSimplifyErrorInitFailed = 3001, // Export failed 1197 | INSExportSimplifyErrorImageInitFailed = 4001, // Initialization failed 1198 | }; 1199 | ``` 1200 | 1201 | ### Parameter description 1202 | 1203 | Please refer to video parameters, image parameters are a subset of video parameters. Difference: There is no callback method for exporting images, and error messages are directly returned through the return value. 1204 | 1205 | ### Other features 1206 | 1207 | #### LOG management 1208 | 1209 | In the INSCoreMedia library, the management of logs can be completed with the help of INSRegisterLogCallback class. This class provides rich functions. Firstly, it supports flexible configuration of log output paths. Developers can output logs to specified files or storage locations according to their own project needs, which is convenient for centralized viewing and analysis of logs in the future. Secondly, this class also has the function of log level filtering. Different levels of logs, such as debugging level, information level, warning level, error level, etc., have different importance in different stages of project development and operation. By configuring filtering levels, only logs of specific levels and above can be output, thereby reducing unnecessary log information interference and improving the efficiency of development and debugging. 1210 | 1211 | In addition, INSCoreMedia also supports registering callbacks. Users can customize log processing in the callback by registering the callback function. For example, log information can be printed to the Console in the callback, making it convenient for developers to view log content in real-time during debugging; logs can also be stored as log files for detailed tracing and analysis of historical logs, providing strong data support for project maintenance and optimization. 1212 | 1213 | Configure log output file: 1214 | 1215 | ```Objective-C 1216 | /** 1217 | 1.If the configuration log includes file output, the file path needs to be set. 1218 | 2.Set the output log level, logs greater than or equal to this level will be output. 1219 | */ 1220 | - (void)configLogKind:(InsLogKind)kind minLogLevel:(InsLogLevel)level optionalFullFilePath:(NSString * __nullable)fullFilePath; 1221 | ``` 1222 | 1223 | Registration Callback: 1224 | 1225 | ```Objective-C 1226 | /** 1227 | Custom log received callbacks 1228 | */ 1229 | - (void)registerLogCallBack:(void(^)(NSString *_Nonnull tag, InsLogLevel level, NSString * _Nonnull fileName, NSString * _Nonnull funcName, int line, NSString *_Nonnull message))block; 1230 | - (void)registerLogCallBackBmg:(void(^)(InsLogLevel level,NSString *_Nonnull message))block; 1231 | ``` 1232 | 1233 | -------------------------------------------------------------------------------- /README_zh.md: -------------------------------------------------------------------------------- 1 | # 简要 2 | 3 | iOS SDK主要用于连接、设置和获取相机参数、控制相机进行拍照和录制、文件下载、固件升级和支持视频导出与图片导出等。 4 | 5 | 支持机型:X5, X4, X3, ONE X2, ONE X, ONE RS, ONE RS一英寸。 6 | 7 | # 目录 8 | * [INSCameraSDK](#inscamerasdk) 9 | * [环境准备](#环境准备) 10 | * [相机连接与相机状态](#相机连接与相机状态) 11 | * [拍摄模式](#拍摄模式) 12 | * [相机参数](#相机参数) 13 | * [拍照](#拍照) 14 | * [录制](#录制) 15 | * [预览](#预览) 16 | * [其他功能](#其他功能) 17 | * [INSMediaSDK](#insmediasdk) 18 | * [导出(视频)](#导出视频) 19 | * [导出(图片)](#导出图片) 20 | 21 | 22 | # INSCameraSDK 23 | 24 | ## 环境准备 25 | 26 | ### 通过Wi-Fi连接相机 27 | 28 | - **启用相机 Wi-Fi 功能** 29 | 30 | 在相机上开启 Wi-Fi 功能。 31 | 32 | - **连接 Wi-Fi** 33 | 34 | 在手机的 Wi-Fi 设置中,查找并选择对应的相机名称。 35 | 36 | - **输入连接密码** 37 | 38 | | 机型 | 密码获取方式 | 39 | | -------- | -------------------------------------------- | 40 | | X2 | 固定密码:`88888888` | 41 | | X3/X4/X5 | 手动获取:相机屏幕 → 设置 → Wi-Fi → 显示密码
蓝牙获取:见1.2.3 | 42 | 43 | ### 通过蓝牙连接相机 44 | 45 | 通过蓝牙连接相机后,可以正常使用拍摄、录制等功能,但不支持实时预览和文件下载。如果您需要预览功能,可以在蓝牙配对成功后,通过调用相应的接口获取到WIFI的名称和密码,然后通过wifi连接 46 | 47 | #### 搜索蓝牙设备 48 | 49 | 调用以下方法扫描蓝牙设备 50 | 51 | ```python 52 | INSBluetoothManager().scanCameras 53 | ``` 54 | 55 | #### 建立蓝牙连接 56 | 57 | 使用下面的接口建立蓝牙连接: 58 | 59 | ```c++ 60 | - (id)connectDevice:(INSBluetoothDevice *)device 61 | completion:(void (^)(NSError * _Nullable))completion; 62 | ``` 63 | 64 | #### 获取相机wifi账号和密码 65 | 66 | 蓝牙连接成功后,调用接口获取 Wi-Fi 信息。示例代码如下: 67 | 68 | ```javascript 69 | let bluetoothManager = INSBluetoothManager() 70 | bluetoothManager.command(by: peripheral)?.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 71 | guard let options = options else { 72 | self?.showAlert(row.tag!, String(describing: err)) 73 | return 74 | } 75 | self?.showAlert("ssid:\(String(describing: options.wifiInfo?.ssid)) pw:\(String(describing: options.wifiInfo?.password))", String(describing: err)) 76 | } 77 | ``` 78 | 79 | ## 相机连接与相机状态 80 | 81 | ### 连接相机 82 | 83 | 通过 Wi-Fi 连接相机后,可调用 INSCameraSDK 中的接口建立连接。该接口采用单例模式,首次调用时会创建实例,后续调用则复用同一实例。 84 | 85 | ```c++ 86 | INSCameraManager.socket().setup() 87 | ``` 88 | 89 | ### 断开相机 90 | 91 | 当需要断开与相机的连接时,请调用以下接口: 92 | 93 | ```c++ 94 | INSCameraManager.socket().shutdown() 95 | ``` 96 | 97 | ### 判断相机连接状态 98 | 99 | 通过以下方式获取相机的连接状态: 100 | 101 | ```swift 102 | INSCameraManager.socket().cameraState 103 | ``` 104 | 105 | 返回状态中,若状态为 `INSCameraStateConnected` 则表示已成功建立连接。状态定义如下: 106 | 107 | ```c++ 108 | INSCameraManager.socket().cameraState 109 | 110 | // 总共有以下几种状态 111 | typedef NS_ENUM(NSUInteger, INSCameraState) { 112 | /// an insta360 camera is found, but not connected, will not response 113 | INSCameraStateFound, 114 | 115 | /// an insta360 camera is synchronized, but not connected, will not response 116 | INSCameraStateSynchronized, 117 | 118 | /// the nano device is connected, app is able to send requests 119 | INSCameraStateConnected, 120 | 121 | /// connect failed 122 | INSCameraStateConnectFailed, 123 | 124 | /// default state, no insta360 camera is found 125 | INSCameraStateNoConnection, 126 | }; 127 | ``` 128 | 129 | ## 拍摄模式 130 | 131 | 本节主要介绍如何设置与获取相机的各项参数,包括拍摄模式、摄影参数等。参数类型主要分为数值型(如曝光 ISO、EV 值、快门速度等)和枚举型(如拍摄模式、曝光模式、分辨率等)。 132 | 133 | ### 获取当前拍摄模式 134 | 135 | 使用接口 `INSCameraManager.shared().commandManager.getOptionsWithTypes` 获取当前相机的拍摄模式。该方法需要传入以下参数: 136 | * **optionTypes** 137 | 指定需要获取哪些参数,每个参数对应一个枚举值(参见 `INSCameraOptionsType`),需要转换为 `NSNumber` 数组。 138 | * **requestOptions** 139 | 可配置请求的最大超时时长(默认 10 秒)。 140 | * **completion** 141 | 回调中返回: 142 | * `error`:为 `nil` 表示获取成功,否则包含错误原因。 143 | * `cameraOptions`:包含当前相机拍摄模式(拍摄模式为 `photoSubMode` 或 `videoSubMode`,具体枚举含义参见下文)。 144 | 145 | 拍摄模式枚举: 146 | ```typescript 147 | // 拍照 148 | typedef NS_ENUM(NSUInteger, INSPhotoSubMode) { 149 | INSPhotoSubModeSingle = 0, 150 | INSPhotoSubModeHdr, 151 | INSPhotoSubModeInterval, 152 | INSPhotoSubModeBurst, 153 | INSPhotoSubModeNightscape, 154 | INSPhotoSubModeInstaPano, 155 | INSPhotoSubModeInstaPanoHdr, 156 | INSPhotoSubModeStarlapse, 157 | INSPhotoSubModeNone = 100, 158 | }; 159 | // 视频录制 160 | typedef NS_ENUM(NSUInteger, INSVideoSubMode) { 161 | INSVideoSubModeNormal = 0, 162 | INSVideoSubModeBulletTime, 163 | INSVideoSubModeTimelapse, 164 | INSVideoSubModeHDR, 165 | INSVideoSubModeTimeShift, 166 | INSVideoSubModeSuperVideo, 167 | INSVideoSubModeLoopRecording, 168 | INSVideoSubModeFPV, 169 | INSVideoSubModeMovieRecording, 170 | INSVideoSubModeSlowMotion, 171 | INSVideoSubModeSelfie, 172 | INSVideoSubModePure, 173 | INSVideoSubModeLiveview, 174 | INSVideoSubModeCameraLiveview, 175 | INSVideoSubModeDashCam, 176 | INSVideoSubModePTZ, 177 | INSVideoSubModeNone = 100, 178 | }; 179 | ``` 180 | 181 | 调用demo: 182 | ```typescript 183 | func getCurrentCameraMode(completion: (()->Void)?)->Void{ 184 | 185 | let typeArray: [INSCameraOptionsType] = [.videoSubMode, .photoSubMode] 186 | 187 | let optionTypes = typeArray.map { (type) -> NSNumber in 188 | return NSNumber(value: type.rawValue) 189 | } 190 | let requestOptions = INSCameraRequestOptions() 191 | requestOptions.timeout = 10 192 | 193 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes, requestOptions: requestOptions) { [weak self] error, cameraOptions, _ in 194 | if let error = error { 195 | self?.showAlert("Failed", "The camera mode has been get failed: \(error.localizedDescription)") 196 | return 197 | } 198 | 199 | guard let cameraOptions = cameraOptions else {return} 200 | var captureMode: HUMCaptureMode? = nil 201 | if cameraOptions.photoSubMode != 100 { 202 | captureMode = HUMCaptureMode.modePhotoFrom(value: cameraOptions.photoSubMode) 203 | } 204 | else if cameraOptions.videoSubMode != 100 { 205 | captureMode = HUMCaptureMode.modeVideoFrom(value: cameraOptions.videoSubMode) 206 | } 207 | guard let mode = captureMode else {return} 208 | completion?() 209 | } 210 | } 211 | ``` 212 | 213 | ### 设置拍摄模式 214 | 215 | 通过方法:`INSCameraManager.shared().commandManager.setOptions`将指定模式配置给相机。在设置拍摄模式中有以下几个重要的点 216 | * **INSCameraOptions** 217 | 用于承载拍摄模式配置,主要包含以下两个属性: 218 | * `photoSubMode`:拍照模式 219 | * `videoSubMode`:录像模式 220 | * **INSCameraOptionsType** 221 | 用于指定 `INSCameraOptions` 中哪些参数需要生效: 222 | * 拍照模式:`INSCameraOptionsType::INSCameraOptionsTypePhotoSubMode` 223 | * 录制模式:`INSCameraOptionsType::INSCameraOptionsTypeVideoSubMode` 224 | 225 | 以下为示例代码(以设置图片拍摄模式为例): 226 | 227 | ```c++ 228 | // 图片拍摄模式枚举 229 | typedef NS_ENUM(NSUInteger, INSPhotoSubMode) { 230 | INSPhotoSubModeSingle = 0, 231 | INSPhotoSubModeHdr, 232 | INSPhotoSubModeInterval, 233 | INSPhotoSubModeBurst, 234 | INSPhotoSubModeNightscape, 235 | INSPhotoSubModeInstaPano, 236 | INSPhotoSubModeInstaPanoHdr, 237 | INSPhotoSubModeStarlapse, 238 | INSPhotoSubModeNone = 100, 239 | }; 240 | 241 | var typeArray: [INSCameraOptionsType] = [.photoSubMode] 242 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 243 | let cameraOptions = INSCameraOptions() 244 | cameraOptions.photoSubMode = INSPhotoSubMode.single 245 | 246 | INSCameraManager.shared().commandManager.setOptions(cameraOptions, forTypes: optionTypes) { [weak self] error, _ in 247 | if let error = error { 248 | self?.showAlert("Failed", "The camera mode has been set failed: \(error.localizedDescription)") 249 | print("Failed: The camera mode has been set failed: \(error.localizedDescription)") 250 | return 251 | } 252 | print("SUCCESS") 253 | } 254 | ``` 255 | 256 | ## 相机参数 257 | 258 | 相机参数通常分为两类,第一种为具体的数值,如曝光iso,ev值,快门速度等。第二种为枚举值,如拍摄模式,曝光模式等。对于前者,能够直接向 `INSPhotographyOptions` 中的参数赋值,并发送至相机。对于后者,则需查阅表中对应枚举所表示的含义,再将对应的枚举值赋值给`INSPhotographyOptions`。如下所示为分辨率与其对应枚举值的关系。其他参数可通过SDK工程中的`“common_camera_setting_proto.json”`文件查看。 259 | 260 | ### 获取相机参数 261 | 262 | 获取相机通过方法:`getPhotographyOptions`获取。需要的主要入参有三个`functionMode`和`optionTypes`,以及一个闭包回调。 263 | 264 | ```swift 265 | /*! 266 | * @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. 267 | * 268 | * @param functionMode the target function mode to get 269 | * @param optionTypes array of the INSPhotographyOptionsType to get 270 | * @param completion the callback block. If all succeed, error would be nil, if partial failed, error's code would be INSCameraErrorCodeAccept, if all fail, error's code would be the maximum error code. 271 | */ 272 | - (void)getPhotographyOptionsWithFunctionMode:(INSCameraFunctionMode*)functionMode 273 | types:(NSArray *)optionTypes 274 | completion:(void(^)(NSError * _Nullable error, 275 | INSPhotographyOptions * _Nullable options, 276 | NSArray * _Nullable successTypes))completion; 277 | ``` 278 | * `functionMode`:表示当前的拍摄模式 279 | 280 | * `optionTypes`:每个参数对应一个枚举值, 281 | * 如分辨率对应:INSPhotographyOptionsTypePhotoSize = 40 282 | * 白平衡对应:INSPhotographyOptionsTypeWhiteBalance = 13 283 | 284 | * 闭包会返回一个`NSError`和`INSPhotographyOptions` 285 | * `NSError`为`nil`表示成功,否则会包含失败原因 286 | * `INSPhotographyOptions`中包含当前相机参数的具体值,如分辨率,白平衡等 287 | 288 | 289 | 290 | 示例代码如下:获取当前相机白平衡的值 291 | ```swift 292 | 293 | var typeArray: [INSPhotographyOptionsType] = [.whiteBalanceValue] 294 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 295 | 296 | let functionMode = currentFunctionMode.functionMode 297 | 298 | 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 299 | } 300 | print("getPhotographyOptions Success!") 301 | print("whiteBalance: \(camerOptions?.whiteBalance ?? "N/A")") 302 | }) 303 | 304 | ``` 305 | 306 | 307 | ### 设置相机参数 308 | 309 | 给相机设置参数需要通过方法:`INSCameraManager.shared().commandManager.setPhotographyOptions`,需要的主要入参主要有以下几个参数。 310 | 311 | * `INSPhotographyOptions`:存储被配置的参数 312 | 313 | * `INSPhotographyOptionsType`:表示哪些参数需要被配置(每个参数对应一个枚举) 314 | 315 | * `INSCameraFunctionMode`:当前的拍摄模式,当前拍摄模式。 316 | 317 | * 相机设置需要的拍摄模式`INSCameraFunctionMode`和从相机拿到的拍摄模式`INSPhotoSubMode`或`INSVideoSubMode`不能直接转换,对应关系参考工程文件中的类:`HUMCaptureMode`。通过`HUMCaptureMode`将相机当前模式INSPhotoSubMode或INSVideoSubMode转成统一的`INSCameraFunctionMode` 318 | 319 | * 闭包回调:返回是否获取成功 320 | 321 | > 所有参数类型只能设置为相机屏幕上支持的参数,不能随意设置 322 | 323 | 示例代码如下:设置指定白平衡 324 | ```swift 325 | let functionMode = INSCameraFunctionMode.init(functionMode: 6) 326 | var typeArray: [INSPhotographyOptionsType] = [.whiteBalanceValue] 327 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 328 | 329 | option.whiteBalanceValue = 4000 330 | INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion: { [weak self] error, _ in 331 | guard let error = error else { 332 | self?.showAlert("Success", "set successfully") 333 | return 334 | } 335 | self?.showAlert("Failed", "set failed: \(error.localizedDescription)") 336 | }) 337 | ``` 338 | 339 | ### 数值类型 340 | 341 | #### 白平衡 342 | 343 | * `INSPhotographyOptions`中的属性为: 344 | 345 | ```objective-c 346 | @property (nonatomic) uint32_t whiteBalanceValue; 347 | ``` 348 | 349 | * 在`INSPhotographyOptionsType`中对应的枚举为: 350 | 351 | ```objective-c 352 | INSPhotographyOptionsTypeWhiteBalance = 13 353 | ``` 354 | 355 | * 假设当前拍摄模式`INSCameraFunctionMode`为6表示普通拍照。 356 | 357 | #### ExposureBias(仅自动曝光支持"AUTO) 358 | 359 | > 仅在曝光模式为"AUTO" "FULL\_AUTO"下支持调节 360 | 361 | * `INSPhotographyOptions`中的属性为:exposureBias 362 | 363 | ```objective-c 364 | @property (nonatomic) float exposureBias; 365 | ``` 366 | 367 | * `INSPhotographyOptionsType`中对应的枚举为: 368 | 369 | ```objective-c 370 | INSPhotographyOptionsTypeExposureBias = 7 371 | ``` 372 | 373 | #### ISO,shutterSpeed 374 | 375 | > 仅在曝光模式为"MANUAL"和"ISO\_PRIORITY"两种模式下支持调节 376 | 377 | * `INSPhotographyOptions`中的分别属性为:stillExposure.iso,stillExposure.shutterSpeed 378 | 379 | ```objective-c 380 | @property (nullable, nonatomic) INSCameraExposureOptions *stillExposure; 381 | 382 | 383 | @interface INSCameraExposureOptions : NSObject 384 | 385 | @property (nonatomic) uint8_t program; 386 | 387 | @property (nonatomic) NSUInteger iso; 388 | 389 | #if TARGET_OS_IOS 390 | @property (nonatomic) CMTime shutterSpeed; 391 | #endif 392 | 393 | @end 394 | ``` 395 | 396 | * `INSPhotographyOptionsType`中对应的枚举为: 397 | 398 | ```objective-c 399 | INSPhotographyOptionsTypeStillExposureOptions = 20 400 | ``` 401 | 402 | ### 枚举和Bool 403 | 404 | #### 图片分辨率 405 | 406 | * `INSPhotographyOptions`中的属性为:photoSizeForJson 407 | 408 | * photoSizeForJson = 17,表示x4相机的分辨率为8192 x 6144。 409 | 410 | * 在`INSPhotographyOptionsType`中对应的枚举为: 411 | 412 | ```objective-c 413 | INSPhotographyOptionsTypePhotoSize = 40 414 | ``` 415 | 416 | * 假设当前拍摄模式`INSCameraFunctionMode`为6表示普通拍照。 417 | 418 | 代码示例: 419 | 420 | ```swift 421 | let functionMode = INSCameraFunctionMode.init(functionMode: 6) 422 | var typeArray: [INSPhotographyOptionsType] = [.photoSize] 423 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 424 | 425 | options.isUseJsonOptions = true 426 | option.photoSizeForJson = 17 427 | 428 | INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion: { [weak self] error, _ in 429 | guard let error = error else { 430 | self?.showAlert("Success", " set successfully") 431 | return 432 | } 433 | self?.showAlert("Failed", "set failed: \(error.localizedDescription)") 434 | }) 435 | ``` 436 | 437 | 分辨率与枚举值的对应关系 438 | ```swift 439 | "photo_resolution": { 440 | "6912_3456": "0", // X3 18MP 441 | "6272_3136": "1", 442 | "6080_3040": "2", 443 | "4000_3000": "3", 444 | "4000_2250": "4", 445 | "5212_3542": "5", 446 | "5312_2988": "6", 447 | "8000_6000": "7", 448 | "8000_4500": "8", 449 | "2976_2976": "9", 450 | "5984_5984": "10", 451 | "11968_5984": "11", 452 | "5952_2976": "12", // 72MP 453 | "8192_6144": "17", // X4 18MP 454 | "8192_4608": "18", 455 | "4096_3072": "19", 456 | "4096_2304": "20", 457 | "7680_3840": "21", 458 | "3840_3840": "22" 459 | } 460 | ``` 461 | 462 | #### 曝光模式 463 | 464 | * `INSPhotographyOptions`中的属性为: 465 | 466 | ```objective-c 467 | @property (nullable, nonatomic) INSCameraExposureOptions *stillExposure; 468 | 469 | 470 | @interface INSCameraExposureOptions : NSObject 471 | 472 | @property (nonatomic) uint8_t program; // 曝光模式 473 | 474 | @property (nonatomic) NSUInteger iso; 475 | 476 | #if TARGET_OS_IOS 477 | @property (nonatomic) CMTime shutterSpeed; 478 | #endif 479 | 480 | @end 481 | ``` 482 | 483 | * `INSPhotographyOptionsType`中对应的枚举为: 484 | 485 | ```objective-c 486 | INSPhotographyOptionsTypeStillExposureOptions = 20 487 | ``` 488 | 489 | ```json 490 | "exposure_program": { 491 | "AUTO": "0", 492 | "ISO_PRIORITY": "1", 493 | "SHUTTER_PRIORITY": "2", 494 | "MANUAL": "3", 495 | "ADAPTIVE": "4", 496 | "FULL_AUTO": "5" 497 | }, 498 | ``` 499 | 500 | > 支持同时设置多个参数给相机,如下 501 | 502 | ```swift 503 | var typeArray: [INSPhotographyOptionsType] = [.photoSize, .whiteBalanceValue] 504 | let optionTypes = typeArray.map { NSNumber(value: $0.rawValue) } 505 | 506 | option.photoSizeForJson = 11 507 | option.whiteBalanceValue = 4000 508 | 509 | INSCameraManager.shared().commandManager.setPhotographyOptions(option, for: functionMode, types: optionTypes, completion: { [weak self] error, _ in 510 | guard let error = error else { 511 | self?.showAlert("Success", "The camera resolution has been set successfully") 512 | return 513 | } 514 | self?.showAlert("Failed", "The camera resolution has been set failed: \(error.localizedDescription)") 515 | 516 | completion?() 517 | }) 518 | ``` 519 | 520 | #### Pureshot 521 | 522 | > 注意:X5默认打开pureshot模式,且不支持关闭 523 | 524 | * `INSPhotographyOptions`中的属性为: 525 | 526 | ```objective-c 527 | @property (nonatomic) uint8_t rawCaptureType; 528 | ``` 529 | 530 | * 在`INSPhotographyOptionsType`中对应的枚举为: 531 | 532 | ```objective-c 533 | INSPhotographyOptionsTypeRawCaptureType = 25, 534 | ``` 535 | 536 | * 枚举类型: 537 | 538 | ```json 539 | "raw_capture_type": { 540 | "OFF": "0", 541 | "RAW": "1", 542 | "PURESHOT": "3", 543 | "PURESHOT_RAW": "4", 544 | "INSP": "5", 545 | "INSP_RAW": "6" 546 | }, 547 | ``` 548 | 549 | #### 机内拼接(Bool) 550 | 551 | 在拍摄图片时,在相机内部拼接全景图像,无需再外部拼接素材。仅x4及x4之后的相机支持。 552 | 553 | ```swift 554 | var typeArray = [INSCameraOptionsType]() 555 | let cameraOptions = INSCameraOptions() 556 | 557 | // 打开为true, 关闭为false 558 | cameraOptions.enableInternalSplicing = true 559 | typeArray.append(.internalSplicing) 560 | 561 | let optionTypes = typeArray.map { (type) -> NSNumber in 562 | return NSNumber(value: type.rawValue) 563 | } 564 | INSCameraManager.shared().commandManager.setOptions(cameraOptions, forTypes: optionTypes) { [weak self] error, _ in 565 | if let error = error { 566 | self?.showAlert("Failed", "The camera mode has been set failed: \(error.localizedDescription)") 567 | return 568 | } 569 | completion?() 570 | } 571 | ``` 572 | 573 | 574 | ## 拍照 575 | 576 | 通过“`INSCameraManager.shared().commandManager.takePicture`”方法向相机下达拍摄指令,若 error 为 nil,则表示拍摄成功,反之则包含错误信息。optionInfo 中涵盖照片的远程访问地址,可进行远程导出(无需下载至本地)。 577 | 578 | ```bash 579 | INSCameraManager.shared().commandManager.takePicture(with: nil, completion: { (error, optionInfo) in 580 | 581 | print("end takePicture \(Date())") 582 | guard let uri = optionInfo?.uri else { 583 | return 584 | } 585 | print("Take Picture Url:\(uri)")\ 586 | }) 587 | ``` 588 | 589 | ## 录制 590 | 591 | 开始录制: 592 | ```python 593 | INSCameraManager.shared().commandManager.startCapture(with: nil, completion: { (err) in 594 | if let err = err { 595 | self.showAlert(row.tag!, "\(String(describing: err))") 596 | return 597 | } 598 | }) 599 | ``` 600 | 601 | 停止录制: 602 | ```python 603 | INSCameraManager.shared().commandManager.stopCapture(with: nil, completion: { (err, info) in 604 | if let err = err { 605 | self.showAlert(row.tag!, "\(String(describing: err))") 606 | return 607 | } 608 | }) 609 | ``` 610 | 611 | ## 预览 612 | 613 | 预览必须在和相机建立连接之后才行,有以下几个核心类,具体参考demo:CameraConfigByJsonController 614 | 615 | * INSCameraSessionPlayer 616 | 617 | * 绑定ios端的bounds 618 | 619 | * 实现协议:INSCameraSessionPlayerDelegate 620 | 621 | * 实现协议:INSCameraSessionPlayerDataSource,建议一定实现下面两个协议: 622 | 623 | 配置offset信息:updateOffsetToPlayer 624 | 625 | 配置防抖信息:updateStabilizerParamToPlayer 626 | 627 | * INSCameraMediaSession 628 | 629 | ```swift 630 | func setupRenderView() { 631 | var frame = self.view.bounds; 632 | let height = frame.size.width * 0.667 633 | frame.origin.x = 0 634 | frame.origin.y = frame.size.height - height 635 | frame.size.height = height 636 | 637 | newPlayer = INSCameraSessionPlayer() 638 | newPlayer?.delegate = self 639 | newPlayer?.dataSource = self 640 | newPlayer?.render.renderModelType.displayType = .sphereStitch 641 | 642 | if let view = newPlayer?.renderView { 643 | view.frame = frame; 644 | print("预览流: getView = \(view), frame = \(frame)") 645 | self.view.addSubview(view) 646 | } 647 | 648 | let config = INSH264DecoderConfig() 649 | config.shouldReloadDecoder = false 650 | config.decodeErrorMaxCount = 30 651 | config.debugLiveStrem = false 652 | config.debugLog = false 653 | self.mediaSession.setDecoderConfig(config) 654 | } 655 | ``` 656 | 657 | 658 | 659 | ## 其他功能 660 | 661 | ### 固件升级 662 | 663 | 通过调用updateFirwareWithOptions接口主动升级。INSCameraWriteFileOptions 664 | 665 | ```markdown 666 | @interface INSCameraWriteFileOptions : NSObject 667 | 668 | /// file type of data to write 669 | @property (nonatomic) INSCameraFileType fileType; 670 | 671 | /// data of a file. if fileType is photo, data should be encoded in JPG format. 672 | @property (nonatomic) NSData *data; 673 | 674 | /// destinate path of the file in camera, if nil, camera will decide the uri with fileType. 675 | @property (nonatomic, nullable) NSString *uri; 676 | 677 | @end 678 | 679 | 680 | - (void)updateFirwareWithOptions:(INSCameraWriteFileOptions *)options 681 | completion:(void (^)(NSError * _Nullable))completion; 682 | ``` 683 | 684 | 685 | 686 | ### 激活 687 | 688 | Appid和secret需要向Insta360申请: 689 | 690 | ```swift 691 | guard let serialNumber = INSCameraManager.shared().currentCamera?.serialNumber else { 692 | self?.showAlert("提示", "请先连接相机") 693 | return 694 | } 695 | let commandManager = INSCameraManager.shared().commandManager 696 | 697 | // 需要申请,填入真实的appid和secret 698 | INSCameraActivateManager.setAppid("Appid", secret: "secret") 699 | 700 | INSCameraActivateManager.share().activateCamera(withSerial: serialNumber, commandManager: commandManager) { deviceInfo, error in 701 | if let activateError = error { 702 | self?.showAlert("Activate to \(serialNumber)", String(describing: activateError)) 703 | } else { 704 | let deviceType = deviceInfo?["deviceType"] ?? "" 705 | let serialNumber = deviceInfo?["serial"] ?? "" 706 | self?.showAlert("Activate to success", "deviceType: \(deviceType), serial: \(serialNumber)") 707 | } 708 | } 709 | ``` 710 | 711 | ### 获取SD卡状态 712 | 713 | ```swift 714 | let optionTypes = [ 715 | NSNumber(value: INSCameraOptionsType.storageState.rawValue), 716 | ]; 717 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 718 | guard let options = options else { 719 | self.showAlert("get options", String(describing: err)) 720 | return 721 | } 722 | var sdCardStatus = "error" 723 | switch options.storageStatus?.cardState { 724 | case .normal: 725 | sdCardStatus = "Normal" 726 | break 727 | case .noCard: 728 | sdCardStatus = "NoCard" 729 | break 730 | case .noSpace: 731 | sdCardStatus = "NoSpace" 732 | break 733 | case .invalidFormat: 734 | sdCardStatus = "INvalid Format" 735 | break 736 | case .writeProtectCard: 737 | sdCardStatus = "Write Protect Card" 738 | break 739 | case .unknownError: 740 | sdCardStatus = "UnknownError" 741 | break 742 | default: 743 | sdCardStatus = "Status Error" 744 | } 745 | } 746 | ``` 747 | 748 | ### 获取当前电量 749 | 750 | ```javascript 751 | let optionTypes = [ 752 | NSNumber(value: INSCameraOptionsType.batteryStatus.rawValue), 753 | ]; 754 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 755 | guard let options = options else { 756 | self.showAlert("get options", String(describing: err)) 757 | return 758 | } 759 | print("battery: \(options.batteryStatus!.batteryLevel)") 760 | } 761 | ``` 762 | 763 | ### 获取激活时间 764 | 765 | ```swift 766 | let optionTypes = [ 767 | NSNumber(value: INSCameraOptionsType.activateTime.rawValue), 768 | ]; 769 | INSCameraManager.shared().commandManager.getOptionsWithTypes(optionTypes) { (err, options, successTypes) in 770 | guard let options = options else { 771 | self.showAlert("get options", String(describing: err)) 772 | return 773 | } 774 | // 激活时间 775 | let formatter = DateFormatter() 776 | formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS" 777 | let date = Date(timeIntervalSince1970: Double(options.activateTime / 1000)) 778 | print("date :\(date)") 779 | 780 | } 781 | ``` 782 | 783 | ### 静音开关 784 | 785 | ```swift 786 | let optionTypes = [ 787 | NSNumber(value: INSCameraOptionsType.mute.rawValue), 788 | ]; 789 | 790 | let options = INSCameraOptions() 791 | options.mute = true 792 | 793 | INSCameraManager.socket().commandManager.setOptions(options, forTypes: optionTypes, completion: {error,successTypes in 794 | if let error = error { 795 | print("Error:\(error)") 796 | return 797 | } 798 | 799 | print("Success") 800 | }) 801 | ``` 802 | 803 | ### 序列号 804 | 805 | 与相机建立连接之后即可调用 806 | 807 | ```swift 808 | INSCameraManager.shared().currentCamera?.serialNumber 809 | ``` 810 | 811 | ### 固件版本号 812 | 813 | ```swift 814 | INSCameraManager.shared().currentCamera?.firmwareRevision 815 | ``` 816 | 817 | ### 关闭相机 818 | 控制相机关闭的指令,目前仅支持X5相机。示例如下: 819 | ```swift 820 | INSCameraManager.socket().commandManager.closeCamera({_ in}) 821 | ``` 822 | 823 | ### LOG管理 824 | 825 | 在INSCameraSDK里,其所有产生的日志(log)都会借助`INSCameraSDKLoggerProtocol`协议,以回调的形式传递到上层。对于上层而言,接收到这些日志之后,既能够选择将日志进行打印输出,方便开发人员在调试阶段查看SDK运行过程中的相关信息,也可以对日志进行存储操作,以便后续进行数据分析或者问题排查。若想要了解更为详细的操作和配置,可以具体参考`CameraConfigByJsonController`。 826 | 827 | `INSCameraSDKLogger`以一个单例作为`INSCameraSDKLoggerProtocol`的载体,需要配置`logDelegate`属性来承载`INSCameraSDKLoggerProtocol`的回调 828 | 829 | ```objective-c 830 | @protocol INSCameraSDKLoggerProtocol 831 | 832 | - (void)logError:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 833 | - (void)logWarning:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 834 | - (void)logInfo:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 835 | - (void)logDebug:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 836 | 837 | - (void)logCrash:(NSString *)message filePath:(NSString *)filePath funcName:(NSString *)funcName lineNum:(NSInteger)lineNum; 838 | 839 | @end 840 | ``` 841 | 842 | ### 错误码 843 | 844 | ```objective-c 845 | typedef NS_ENUM(NSUInteger, INSCameraErrorCode) { 846 | /// ok 847 | INSCameraErrorCodeOK = 200, 848 | 849 | /// accepted 850 | INSCameraErrorCodeAccept = 202, 851 | 852 | /// mainly means redirection 853 | INSCameraErrorCodeMovedTemporarily = 302, 854 | 855 | /// bad request, check your params 856 | INSCameraErrorCodeBadRequest = 400, 857 | 858 | /// the command has timed out 859 | INSCameraErrorCodeTimeout = 408, 860 | 861 | /// the requests are sent too often 862 | INSCameraErrorCodeTooManyRequests = 429, 863 | 864 | /// request is interrupted and no response has been gotten 865 | INSCameraErrorCodeNoResopnse = 444, 866 | 867 | INSCameraErrorCodeShakeHandeError = 445, 868 | 869 | INSCameraErrorCodePairError = 446, 870 | 871 | /// error on camera 872 | INSCameraErrorCodeInternalServerError = 500, 873 | 874 | /// the command is not implemented for this camera or firmware 875 | INSCameraErrorCodeNotImplemented = 501, 876 | 877 | /// there is no connection 878 | INSCameraErrorCodeNoConnection = 503, 879 | 880 | /// firmware error 881 | INSCameraErrorCodeFirmwareError = 504, 882 | 883 | /// Invalid Request 884 | INSCameraErrorCodeInvalidRequest = 505, 885 | 886 | /// bluetooth not inited 887 | INSCameraErrorCodeCentralManagerNotInited = 601, 888 | }; 889 | ``` 890 | 891 | # INSMediaSDK 892 | 893 | ## 导出(视频) 894 | 895 | 视频导出:为tob用户专门提供了一套简化的导出方法`INSExportSimplify` ,位于 `INSCoreMedia` 该类主要用于简化视频导出的操作,提供了一系列可配置的属性和方法,方便开发者根据需求定制导出过程。`(仅支持导出视频)`。 896 | 897 | ### 使用说明 898 | 899 | 这种方法可以保证基本的导出效果,所有导出所使用的参数都是默认值。用户可以根据特定需求对相关参数进行配置。 900 | 901 | #### 初始化方法 902 | 903 | ```objective-c 904 | -(nonnull instancetype)initWithURLs:(nonnull NSArray)urls outputUrl:(nonnull NSURL*)outputUrl; 905 | ``` 906 | 907 | * **功能**:初始化 `INSExportSimplify` 对象,用于指定输入视频文件的 URL 数组和输出视频文件的 URL。 908 | 909 | * **参数**: 910 | * `urls`:输入视频文件的 URL 数组,不能为空。 911 | * `outputUrl`:输出视频文件的 URL,不能为空。 912 | 913 | * **返回值**:返回一个 `INSExportSimplify` 对象。 914 | 915 | * **示例代码**: 916 | 917 | ```objective-c 918 | NSArray *inputUrls = @[[NSURL fileURLWithPath:@"path/to/input1.mp4"], [NSURL fileURLWithPath:@"path/to/input2.mp4"]]; 919 | NSURL *outputUrl = [NSURL fileURLWithPath:@"path/to/output.mp4"]; 920 | INSExportSimplify *exporter = [[INSExportSimplify alloc] initWithURLs:inputUrls outputUrl:outputUrl]; 921 | ``` 922 | 923 | #### 开始导出 924 | 925 | ```objective-c 926 | -(nullable NSError*)start; 927 | ``` 928 | 929 | #### 取消导出 930 | 931 | ```objective-c 932 | -(void)cancel; 933 | ``` 934 | 935 | #### 销毁导出 936 | 937 | 取消导出,导出完成之后,一定要主动调用,否则可能导致crash 938 | 939 | ```objective-c 940 | -(void)shutDown; 941 | ``` 942 | 943 | ### 参数说明 944 | 945 | #### 导出分辨率 946 | 947 | 该接口用于输出图像分辨率,(宽高比必须为2:1) 948 | 949 | ```objective-c 950 | /** 951 | * 默认宽高: 1920 * 960 (导出画面比例需要为2:1) 952 | */ 953 | @property (nonatomic) int width; 954 | @property (nonatomic) int height; 955 | ``` 956 | 957 | #### 拼接模式(opticalFlowType) 958 | 959 | 总共有四种拼接模式,分别表示,模版拼接,动态拼接,光流拼接,Ai拼接(暂不支持)。 960 | - 模板拼接:比较老的拼接算法,对近景拼接效果不好,但是速度快,性能消耗低 961 | - 动态拼接:适合包含近景的场景,或者有运动和快速变化的情况 962 | - 光流拼接:使用场景和动态拼接相同 963 | - AI 拼接:基于影石 Insta360 现有的光流拼接技术的优化算法,提供更优的拼接效果 964 | ```objective-c 965 | typedef NS_ENUM(NSInteger, INSOpticalFlowType) { 966 | // 动态拼接 967 | INSOpticalFlowTypeDynamicStitch = 0, 968 | // 光流拼接 969 | INSOpticalFlowTypeDisflow = 1, 970 | // AI拼接 971 | INSOpticalFlowTypeAiFlow = 2, 972 | }; 973 | ``` 974 | 975 | #### 防抖模式(stabMode) 976 | 977 | 防抖模式总共支持以下几种,常用的有两种,全防和方向锁定 978 | - 全防(Still):无论怎么转动相机,相机画面始终保持不动() 979 | - 方向锁定(FullDirectional):视角始终随着相机的转动而转动 980 | 981 | ```objective-c 982 | /** 983 | * 防抖模式,默认 INSStabilizerStabModeZDirectional 984 | */ 985 | @property (nonatomic)INSStabilizerStabMode stabMode; 986 | ``` 987 | 988 | ```objective-c 989 | typedef NS_ENUM(NSInteger, INSStabilizerStabMode) { 990 | /// 关闭防抖 991 | INSStabilizerStabModeOff = -1, 992 | /// 全防 993 | INSStabilizerStabModeStill, 994 | /// 移除yaw方向的防抖, 用于directional lock, view can only move arround z-axis (pan move) 995 | INSStabilizerStabModeZDirectional, 996 | /// 开防抖、开水平矫正,即full-direcional 997 | INSStabilizerStabModeFullDirectional, 998 | ///不校准地平线, 即free-footage, total free camera mode, camera can move through three axis 999 | INSStabilizerStabModeFreeFootage, 1000 | /// //处理翻转 1001 | INSStabilizerStabModeFlipEffect, 1002 | ///开防抖、平均姿态矫正,即relative-refine 1003 | INSStabilizerStabModeRelativeRefine, 1004 | ///开防抖、开水平矫正,即absulute-refine 1005 | INSStabilizerStabModeAbsoluteRefine, 1006 | ///子弹时间 1007 | INSStabilizerStabModeBulletTime, 1008 | /// Pano Fpv 1009 | INSStabilizerStabModePanoFPV 1010 | }; 1011 | ``` 1012 | 1013 | #### 保护镜 1014 | 1015 | 如果拍摄时佩戴保护镜,需要根据类型配置该参数。(商城中的标准保护镜为A级,高级保护镜为S级) 1016 | 1017 | ```objective-c 1018 | /** 1019 | * 保护镜 1020 | */ 1021 | @property (nonatomic) INSOffsetConvertOptions protectType; 1022 | ``` 1023 | 1024 | ```objective-c 1025 | typedef NS_OPTIONS(NSUInteger, INSOffsetConvertOptions) { 1026 | INSOffsetConvertOptionNone = 0, 1027 | INSOffsetConvertOptionEnableWaterProof = 1 << 0, // ONE X 保护镜 1028 | INSOffsetConvertOptionEnableDivingAir = 1 << 1, // 潜水壳(水上) 1029 | INSOffsetConvertOptionEnableDivingWater = 1 << 2, // 潜水壳(水下) 1030 | INSOffsetConvertOptionEnableDivingAirV2 = 1 << 3, // 新版潜水壳(水上) 1031 | INSOffsetConvertOptionEnableDivingWaterV2 = 1 << 4, // 新版潜水壳(水下) 1032 | INSOffsetConvertOptionEnableBuckleShell = 1 << 5, // 卡扣式弧面镜 1033 | INSOffsetConvertOptionEnableAdhesiveShell = 1 << 6, // 黏贴式球面镜 1034 | INSOffsetConvertOptionEnableGlassShell = 1 << 7, // 玻璃保护镜(S) 1035 | INSOffsetConvertOptionEnablePlasticCement = 1 << 8, // 塑胶保护镜(A) 1036 | INSOffsetConvertOptionEnableAverageShell = 1 << 9 // A/S平均 1037 | }; 1038 | ``` 1039 | 1040 | #### 消色差(colorFusion) 1041 | 1042 | ```objective-c 1043 | /** 1044 | * 消色差: 默认false 1045 | */ 1046 | @property (nonatomic) BOOL colorFusion; 1047 | ``` 1048 | 1049 | 产生色差的原因主要有以下两点: 1050 | 1051 | * 首先,由于两个镜头是分开的,其各自得出的视频曝光可能不太一致。当把它们拼接在一起的时候,会有比较明显的亮度差。这是因为不同镜头在拍摄时的参数设置、感光元件的性能等方面存在差异,从而导致所捕捉到的光线强度有所不同。 1052 | 1053 | * 其次,因为镜头两边的光照不一样,相机曝光不同,有时候前后镜头拍出来的画面也会有明显的亮度差。这种现象在光差比大的地方尤其明显,比如在强光与阴影交界的区域,或者是在室内外光线差异较大的环境中。在这些情况下,相机难以平衡不同区域的光线强度,从而使得拍摄出的画面在亮度上出现较大的差别。 1054 | 1055 | 正是为了解决此类问题,消色差技术得以开发。它通过一系列的算法和图像处理手段,对不同镜头拍摄的画面进行调整和优化,以减少或消除亮度差,从而使拼接后的视频看起来更加自然和连贯。 1056 | 1057 | #### 去紫边(defringeConfig) 1058 | 1059 | 该接口具备消除特定现象的功能,具体而言,其专门用于消除录制过程中因光照因素产生的紫边现象。在实际录制场景中,光照情况复杂多变,该接口能够针对性地解决两类常见光照场景下出现的紫边问题。其一为室外强光场景,在阳光强烈的白天进行录制时,室外高强度光线极易引发紫边现象,此接口可有效消除该场景下的紫边;其二为室内灯光场景,室内诸如白炽灯、荧光灯等不同类型的灯光所发出的光线,也可能致使录制画面出现紫边,该接口同样能够对这种室内灯光场景下的紫边现象进行消除处理。 1060 | 1061 | 使用方法:使用该算法,需要配置对应模型,该模型通过一个json文件来管理(coreml_model_v2_scale6_scale4.json)。需要将这些模型和json文件拷贝到App内。参数配置参考下列代码 1062 | 1063 | 视频 1064 | 1065 | ```javascript 1066 | let jsonFilePath: String = Bundle.main.path(forResource: "coreml_model_v2_scale6_scale4", ofType: "json")! 1067 | let components = jsonFilePath.split(separator: "/") 1068 | let modelFilePath = components.dropLast().joined(separator: "/") 1069 | 1070 | var jsonContent = "" 1071 | do { 1072 | let data = try Data(contentsOf: URL(fileURLWithPath: jsonFilePath)) 1073 | jsonContent = String(data: data, encoding: .utf8) ?? "" 1074 | } catch { 1075 | assertionFailure("\(jsonFilePath)文件无法读取") 1076 | } 1077 | 1078 | let initInfo = INSDePurpleFringeFilterInitInfo.init(imageTransferType: .AUTO, algoAccelType: .AUTO) 1079 | 1080 | let depurpleFringInfo = INSDePurpleFringeFilterInfo() 1081 | depurpleFringInfo.setInit(initInfo) 1082 | depurpleFringInfo.setModelJsonContent(jsonContent) 1083 | depurpleFringInfo.setModelFilePath(modelFilePath) 1084 | ``` 1085 | 1086 | 图片 1087 | 1088 | ```javascript 1089 | let jsonFilePath: String = Bundle.main.path(forResource: "coreml_model_v2_scale6_scale4", ofType: "json")! 1090 | let components = jsonFilePath.split(separator: "/") 1091 | let modelFilePath = components.dropLast().joined(separator: "/") 1092 | var jsonContent = "" 1093 | do { 1094 | let data = try Data(contentsOf: URL(fileURLWithPath: jsonFilePath)) 1095 | jsonContent = String(data: data, encoding: .utf8) ?? "" 1096 | } catch { 1097 | assertionFailure("\(jsonFilePath)文件无法读取") 1098 | } 1099 | 1100 | let depurpleFringInfo = INSExporter2DefringConfiguration.init() 1101 | depurpleFringInfo.modelJsonContent = jsonContent 1102 | depurpleFringInfo.modelFilePath = modelFilePath 1103 | depurpleFringInfo.enableDetect = true 1104 | depurpleFringInfo.useFastInferSpeed = false 1105 | videoExporter?.defringeConfig = depurpleFringInfo 1106 | ``` 1107 | 1108 | #### 进度和状态回调 1109 | 1110 | **开始导出后**,该协议(INSRExporter2ManagerDelegate)会实时回调导出的进度和状态。 1111 | 1112 | ```objective-c 1113 | typedef NS_ENUM(NSInteger, INSExporter2State) { 1114 | INSExporter2StateError = -1, // 表示导出过程中出现错误 1115 | INSExporter2StateComplete = 0, // 表示导出成功完成 1116 | INSExporter2StateCancel = 1, // 表示用户手动取消了导出操作 1117 | INSExporter2StateInterrupt = 2, // 表示导出被意外中断 1118 | INSExporter2StateDisconnect = 3, // 表示与服务器断开连接 1119 | INSExporter2StateInitError = 4, // 表示初始化时出现错误 1120 | }; 1121 | ``` 1122 | 1123 | ```objective-c 1124 | @protocol INSRExporter2ManagerDelegate 1125 | 1126 | - (void)exporter2Manager:(INSExporter2Manager *)manager progress:(float)progress; 1127 | 1128 | - (void)exporter2Manager:(INSExporter2Manager *)manager state:(INSExporter2State)state error:(nullable NSError*)error; 1129 | 1130 | // 用于全景埋点检测(一般用不到) 1131 | - (void)exporter2Manager:(INSExporter2Manager *)manager correctOffset:(NSString*)correctOffset errorNum:(int)errorNum totalNum:(int)totalNum clipIndex:(int)clipIndex type:(NSString*)type; 1132 | @end 1133 | ``` 1134 | 1135 | #### 错误码 1136 | 1137 | 导出错误码 1138 | 1139 | ```Objective-C 1140 | typedef NS_ENUM(NSInteger, INSExporter2State) { 1141 | INSExporter2StateError = -1, // 表示导出过程中出现错误 1142 | INSExporter2StateComplete = 0, // 表示导出成功完成 1143 | INSExporter2StateCancel = 1, // 表示用户手动取消了导出操作 1144 | INSExporter2StateInterrupt = 2, // 表示导出被意外中断 1145 | INSExporter2StateDisconnect = 3, // 表示与服务器断开连接 1146 | INSExporter2StateInitError = 4, // 表示初始化时出现错误 1147 | }; 1148 | ``` 1149 | 1150 | ## 导出(图片) 1151 | 1152 | ### 使用说明 1153 | 1154 | 图片导出:`INSExportImageSimplify` 类属于 `INSCoreMedia` 框架。该类旨在简化图像导出操作,提供了一系列可配置属性和方法,支持导出`普通图像`和 `HDR 图像`,允许开发者根据需求定制导出过程。 1155 | 1156 | #### 导出普通图像 1157 | 1158 | ```objective-c 1159 | - (NSError*)exportImageWithInputUrl:(nonnull NSURL *)inputUrl outputUrl:(nonnull NSURL *)outputUrl; 1160 | ``` 1161 | 1162 | * **功能**:导出普通图像,支持远程或本地图片。支持远程和本地 1163 | 1164 | * **参数**: 1165 | * `inputUrl`:输入图像的 URL,不能为空。 1166 | * `outputUrl`:输出图像的 URL,不能为空。 1167 | 1168 | * **返回值**:如果导出过程中出现错误,返回一个 `NSError` 对象;如果导出成功,返回 `nil`。 1169 | 1170 | * **示例代码**: 1171 | 1172 | ```objective-c 1173 | INSExportImageSimplify *exporter = [[INSExportImageSimplify alloc] init]; 1174 | NSURL *inputUrl = [NSURL fileURLWithPath:@"path/to/input.jpg"]; 1175 | NSURL *outputUrl = [NSURL fileURLWithPath:@"path/to/output.jpg"]; 1176 | NSError *error = [exporter exportImageWithInputUrl:inputUrl outputUrl:outputUrl]; 1177 | if (error) { 1178 | NSLog(@"导出失败:%@", error.localizedDescription); 1179 | } else { 1180 | NSLog(@"导出成功"); 1181 | } 1182 | ``` 1183 | 1184 | #### 导出 HDR 图像方法(仅支持本地HDR图片) 1185 | 1186 | ```objective-c 1187 | - (NSError*)exportHdrImageWithInputUrl:(nonnull NSArray *)inputUrl outputUrl:(nonnull NSURL *)outputUrl; 1188 | ``` 1189 | 1190 | * **功能**: 1191 | * 该功能主要用于导出高动态范围(HDR)图像。它仅支持本地图像,这意味着图像必须存储在本地设备上才能进行导出操作。此外,为了确保导出的质量和效果,要求输入的图像数量至少为 3 张。 1192 | 1193 | * **参数**: 1194 | * `inputUrl`:这是一个输入图像的 URL 数组。该数组不能为空,且其中的元素数量必须大于等于 3。这些 URL 指向的是需要进行 HDR 导出的本地图像。 1195 | * `outputUrl`:指定输出图像的 URL。同样,该参数也不能为空,它用于确定导出后的 HDR 图像的存储位置。 1196 | 1197 | * **返回值**: 1198 | * 在导出过程中,如果出现任何错误,将会返回一个`NSError`对象。这个对象包含了有关错误的详细信息,以便开发者进行错误处理和调试。 1199 | * 如果导出成功,没有任何错误发生,那么返回值将为`nil`,表示操作顺利完成。 1200 | 1201 | * **示例代码**: 1202 | ```objective-c 1203 | INSExportImageSimplify *exporter = [[INSExportImageSimplify alloc] init]; 1204 | NSArray *inputUrls = @[[NSURL fileURLWithPath:@"path/to/input1.jpg"], [NSURL fileURLWithPath:@"path/to/input2.jpg"], [NSURL fileURLWithPath:@"path/to/input3.jpg"]]; 1205 | NSURL *outputUrl = [NSURL fileURLWithPath:@"path/to/output_hdr.jpg"]; 1206 | NSError *error = [exporter exportHdrImageWithInputUrl:inputUrls outputUrl:outputUrl]; 1207 | if (error) { 1208 | NSLog(@"导出失败:%@", error.localizedDescription); 1209 | } else { 1210 | NSLog(@"导出成功"); 1211 | } 1212 | ``` 1213 | 1214 | #### 错误码 1215 | 1216 | ```objective-c 1217 | typedef NS_ENUM(NSInteger, INSExportSimplifyError) { 1218 | INSExportSimplifyErrorSuccess = 0,// 成功 1219 | INSExportSimplifyErrorInitFailed = 3001, // 导出失败 1220 | INSExportSimplifyErrorImageInitFailed = 4001, // 初始化失败 1221 | }; 1222 | ``` 1223 | 1224 | ### 参数说明 1225 | 1226 | 参考视频参数,图片参数是视频参数的子集。区别点:图片导出没有回调方法,直接通过返回值返回错误信息。 1227 | 1228 | ### 其他功能 1229 | 1230 | #### LOG管理 1231 | 1232 | 在 INSCoreMedia 这个库当中,关于日志(log)的管理工作能够借助 INSRegisterLogCallback 类来完成。该类提供了颇为丰富的功能。其一,它支持对日志输出路径进行灵活配置。开发者可以依据自身项目的需求,将日志输出到指定的文件或者存储位置,这样便于后续对日志进行集中查看与分析。其二,该类还具备日志等级过滤的功能。不同等级的日志,例如调试级、信息级、警告级、错误级等,在项目开发和运行的不同阶段有不同的重要性。通过配置过滤等级,可以只输出特定等级及以上的日志,从而减少不必要的日志信息干扰,提高开发和调试的效率。 1233 | 1234 | 除此之外,INSCoreMedia 还支持注册回调。用户能够通过注册回调函数,在回调中实现对日志的自定义处理。比如,可以在回调中将日志信息打印到控制台,方便开发者在调试过程中实时查看日志内容;也可以将日志存储成 log 文件,便于后续对历史日志进行详细的追溯和分析,为项目的维护和优化提供有力的数据支持。 1235 | 1236 | 配置log输出文件: 1237 | 1238 | ```Objective-C 1239 | /** 1240 | 1, 如果配置log包含文件输出,需要设置文件路径 1241 | 2, 设置输出log级别,大于等于该级别的log将会输出 1242 | */ 1243 | - (void)configLogKind:(InsLogKind)kind minLogLevel:(InsLogLevel)level optionalFullFilePath:(NSString * __nullable)fullFilePath; 1244 | ``` 1245 | 1246 | 注册回调 1247 | 1248 | ```objective-c 1249 | /** 1250 | 注册Custom log接收的回调 1251 | */ 1252 | - (void)registerLogCallBack:(void(^)(NSString *_Nonnull tag, InsLogLevel level, NSString * _Nonnull fileName, NSString * _Nonnull funcName, int line, NSString *_Nonnull message))block; 1253 | - (void)registerLogCallBackBmg:(void(^)(InsLogLevel level,NSString *_Nonnull message))block; 1254 | ``` 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | --------------------------------------------------------------------------------