├── 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 |
--------------------------------------------------------------------------------