react-native-video-trim 7.1.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="20.574dp"
3
+ android:height="21.997dp"
4
+ android:viewportWidth="20.574"
5
+ android:viewportHeight="21.997">
6
+ <path
7
+ android:fillColor="#FF000000"
8
+ android:pathData="M0,0h20.574v21.997h-20.574z"
9
+ android:strokeAlpha="0"
10
+ android:fillAlpha="0"/>
11
+ <path
12
+ android:pathData="M14.746,18.846C14.618,19.308 14.214,19.617 13.685,19.617C13.236,19.617 12.855,19.431 12.406,19.001L8.246,15.056C8.177,14.998 8.099,14.968 8.002,14.968L5.199,14.968C3.881,14.968 3.158,14.246 3.158,12.83L3.158,9.197C3.158,8.561 3.306,8.063 3.59,7.71ZM14.789,3.543L14.789,13.536L8.231,6.982C8.236,6.978 8.241,6.974 8.246,6.97L12.406,3.064C12.904,2.585 13.217,2.39 13.666,2.39C14.33,2.39 14.789,2.908 14.789,3.543Z"
13
+ android:fillColor="#ffffff"
14
+ android:fillAlpha="0.85"/>
15
+ <path
16
+ android:pathData="M18.158,20.642C18.451,20.935 18.929,20.935 19.222,20.642C19.506,20.339 19.515,19.871 19.222,19.578L2.494,2.859C2.201,2.566 1.713,2.566 1.42,2.859C1.136,3.142 1.136,3.64 1.42,3.923Z"
17
+ android:fillColor="#ffffff"
18
+ android:fillAlpha="0.85"/>
19
+ </vector>
@@ -0,0 +1,23 @@
1
+ <vector xmlns:android="http://schemas.android.com/apk/res/android"
2
+ android:width="22.158dp"
3
+ android:height="17.236dp"
4
+ android:viewportWidth="22.158"
5
+ android:viewportHeight="17.236">
6
+ <path
7
+ android:fillColor="#FF000000"
8
+ android:pathData="M0,0h22.158v17.236h-22.158z"
9
+ android:strokeAlpha="0"
10
+ android:fillAlpha="0"/>
11
+ <path
12
+ android:pathData="M18.74,15.322C19.102,15.566 19.551,15.479 19.815,15.107C21.065,13.389 21.797,11.025 21.797,8.613C21.797,6.201 21.074,3.818 19.815,2.119C19.551,1.748 19.102,1.66 18.74,1.904C18.379,2.148 18.32,2.607 18.604,3.008C19.668,4.512 20.283,6.533 20.283,8.613C20.283,10.693 19.648,12.695 18.604,14.219C18.33,14.619 18.379,15.078 18.74,15.322Z"
13
+ android:fillColor="#ffffff"
14
+ android:fillAlpha="0.85"/>
15
+ <path
16
+ android:pathData="M15.127,12.773C15.449,12.998 15.908,12.93 16.172,12.549C16.924,11.563 17.373,10.107 17.373,8.613C17.373,7.119 16.924,5.674 16.172,4.678C15.908,4.297 15.449,4.219 15.127,4.453C14.727,4.727 14.668,5.215 14.971,5.615C15.537,6.396 15.859,7.48 15.859,8.613C15.859,9.746 15.527,10.82 14.971,11.611C14.678,12.021 14.727,12.49 15.127,12.773Z"
17
+ android:fillColor="#ffffff"
18
+ android:fillAlpha="0.85"/>
19
+ <path
20
+ android:pathData="M10.527,17.236C11.172,17.236 11.631,16.777 11.631,16.143L11.631,1.162C11.631,0.527 11.172,0.01 10.508,0.01C10.049,0.01 9.746,0.215 9.248,0.684L5.078,4.59C5.02,4.648 4.932,4.678 4.834,4.678L2.041,4.678C0.713,4.678 0,5.41 0,6.816L0,10.449C0,11.865 0.713,12.588 2.041,12.588L4.834,12.588C4.932,12.588 5.02,12.617 5.078,12.676L9.248,16.621C9.688,17.051 10.068,17.236 10.527,17.236Z"
21
+ android:fillColor="#ffffff"
22
+ android:fillAlpha="0.85"/>
23
+ </vector>
@@ -79,6 +79,28 @@
79
79
  android:tint="#80FFFFFF"
80
80
  android:scaleType="fitCenter"
81
81
  android:contentDescription="Crop" />
82
+
83
+ <ImageView
84
+ android:id="@+id/muteBtn"
85
+ android:layout_width="22dp"
86
+ android:layout_height="22dp"
87
+ android:src="@drawable/speaker_wave_2_fill"
88
+ android:tint="@android:color/white"
89
+ android:scaleType="fitCenter"
90
+ android:layout_marginStart="12dp"
91
+ android:contentDescription="Mute" />
92
+
93
+ <TextView
94
+ android:id="@+id/speedBtn"
95
+ android:layout_width="wrap_content"
96
+ android:layout_height="22dp"
97
+ android:text="1x"
98
+ android:textColor="@android:color/white"
99
+ android:textSize="13sp"
100
+ android:textStyle="bold"
101
+ android:gravity="center"
102
+ android:layout_marginStart="12dp"
103
+ android:contentDescription="Speed" />
82
104
  </LinearLayout>
83
105
 
84
106
  <View
@@ -3,6 +3,7 @@ package com.videotrim
3
3
  import android.util.Log
4
4
  import com.facebook.react.bridge.Promise
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.ReadableArray
6
7
  import com.facebook.react.bridge.ReadableMap
7
8
  import com.facebook.react.bridge.WritableMap
8
9
 
@@ -69,6 +70,38 @@ class VideoTrimModule(
69
70
  base.trim(url, options, promise)
70
71
  }
71
72
 
73
+ override fun getFrameAt(url: String, options: ReadableMap, promise: Promise) {
74
+ base.getFrameAt(url, options, promise)
75
+ }
76
+
77
+ override fun extractAudio(url: String, options: ReadableMap, promise: Promise) {
78
+ base.extractAudio(url, options, promise)
79
+ }
80
+
81
+ override fun compress(url: String, options: ReadableMap, promise: Promise) {
82
+ base.compress(url, options, promise)
83
+ }
84
+
85
+ override fun toGif(url: String, options: ReadableMap, promise: Promise) {
86
+ base.toGif(url, options, promise)
87
+ }
88
+
89
+ override fun merge(urls: ReadableArray, options: ReadableMap, promise: Promise) {
90
+ base.merge(urls, options, promise)
91
+ }
92
+
93
+ override fun saveToPhoto(filePath: String, promise: Promise) {
94
+ base.saveToPhoto(filePath, promise)
95
+ }
96
+
97
+ override fun saveToDocuments(filePath: String, promise: Promise) {
98
+ base.saveToDocuments(filePath, promise)
99
+ }
100
+
101
+ override fun share(filePath: String, promise: Promise) {
102
+ base.share(filePath, promise)
103
+ }
104
+
72
105
  companion object {
73
106
  const val NAME = "VideoTrim"
74
107
  }
@@ -3,6 +3,7 @@ package com.videotrim
3
3
  import com.facebook.react.bridge.ReactApplicationContext
4
4
  import com.facebook.react.bridge.Arguments
5
5
  import com.facebook.react.bridge.WritableMap
6
+ import com.facebook.react.bridge.ReadableArray
6
7
 
7
8
  import com.facebook.react.bridge.*
8
9
  import com.facebook.react.module.annotations.ReactModule
@@ -69,6 +70,46 @@ class VideoTrimModule internal constructor(context: ReactApplicationContext) : V
69
70
  base.trim(url, options, promise)
70
71
  }
71
72
 
73
+ @ReactMethod
74
+ override fun getFrameAt(url: String, options: ReadableMap?, promise: Promise) {
75
+ base.getFrameAt(url, options, promise)
76
+ }
77
+
78
+ @ReactMethod
79
+ override fun extractAudio(url: String, options: ReadableMap?, promise: Promise) {
80
+ base.extractAudio(url, options, promise)
81
+ }
82
+
83
+ @ReactMethod
84
+ override fun compress(url: String, options: ReadableMap?, promise: Promise) {
85
+ base.compress(url, options, promise)
86
+ }
87
+
88
+ @ReactMethod
89
+ override fun toGif(url: String, options: ReadableMap?, promise: Promise) {
90
+ base.toGif(url, options, promise)
91
+ }
92
+
93
+ @ReactMethod
94
+ override fun merge(urls: ReadableArray, options: ReadableMap?, promise: Promise) {
95
+ base.merge(urls, options, promise)
96
+ }
97
+
98
+ @ReactMethod
99
+ override fun saveToPhoto(filePath: String, promise: Promise) {
100
+ base.saveToPhoto(filePath, promise)
101
+ }
102
+
103
+ @ReactMethod
104
+ override fun saveToDocuments(filePath: String, promise: Promise) {
105
+ base.saveToDocuments(filePath, promise)
106
+ }
107
+
108
+ @ReactMethod
109
+ override fun share(filePath: String, promise: Promise) {
110
+ base.share(filePath, promise)
111
+ }
112
+
72
113
  companion object {
73
114
  const val NAME = "VideoTrim"
74
115
  }
@@ -3,6 +3,7 @@ package com.videotrim
3
3
  import com.facebook.react.bridge.Promise
4
4
  import com.facebook.react.bridge.ReactApplicationContext
5
5
  import com.facebook.react.bridge.ReactContextBaseJavaModule
6
+ import com.facebook.react.bridge.ReadableArray
6
7
  import com.facebook.react.bridge.ReadableMap
7
8
 
8
9
  abstract class VideoTrimSpec internal constructor(context: ReactApplicationContext) :
@@ -21,4 +22,20 @@ abstract class VideoTrimSpec internal constructor(context: ReactApplicationConte
21
22
  abstract fun isValidFile(url: String, promise: Promise)
22
23
 
23
24
  abstract fun trim(url: String, options: ReadableMap?, promise: Promise)
25
+
26
+ abstract fun getFrameAt(url: String, options: ReadableMap?, promise: Promise)
27
+
28
+ abstract fun extractAudio(url: String, options: ReadableMap?, promise: Promise)
29
+
30
+ abstract fun compress(url: String, options: ReadableMap?, promise: Promise)
31
+
32
+ abstract fun toGif(url: String, options: ReadableMap?, promise: Promise)
33
+
34
+ abstract fun merge(urls: ReadableArray, options: ReadableMap?, promise: Promise)
35
+
36
+ abstract fun saveToPhoto(filePath: String, promise: Promise)
37
+
38
+ abstract fun saveToDocuments(filePath: String, promise: Promise)
39
+
40
+ abstract fun share(filePath: String, promise: Promise)
24
41
  }
@@ -0,0 +1,75 @@
1
+ import UIKit
2
+
3
+ /// Custom UIView that draws an audio waveform as a row of vertical rounded-rect bars.
4
+ ///
5
+ /// Each bar's height is driven by a normalized amplitude value in [0, 1].
6
+ /// The view recalculates bar count from its own width and maps the amplitudes
7
+ /// array proportionally, so it works correctly regardless of whether the
8
+ /// amplitudes array has more or fewer entries than the visible bar count.
9
+ ///
10
+ /// The `backgroundColor` provides the waveform track color; bars are drawn
11
+ /// on top with `barColor`.
12
+ class AudioWaveformView: UIView {
13
+ var amplitudes: [CGFloat] = [] {
14
+ didSet { setNeedsDisplay() }
15
+ }
16
+
17
+ var barColor: UIColor = .white {
18
+ didSet { setNeedsDisplay() }
19
+ }
20
+
21
+ var barWidth: CGFloat = 3 {
22
+ didSet { setNeedsDisplay() }
23
+ }
24
+
25
+ var barGap: CGFloat = 2 {
26
+ didSet { setNeedsDisplay() }
27
+ }
28
+
29
+ var barCornerRadius: CGFloat = 1.5 {
30
+ didSet { setNeedsDisplay() }
31
+ }
32
+
33
+ override init(frame: CGRect) {
34
+ super.init(frame: frame)
35
+ isOpaque = false
36
+ contentMode = .redraw
37
+ }
38
+
39
+ required init?(coder: NSCoder) {
40
+ super.init(coder: coder)
41
+ isOpaque = false
42
+ contentMode = .redraw
43
+ }
44
+
45
+ override func draw(_ rect: CGRect) {
46
+ guard !amplitudes.isEmpty else { return }
47
+ guard let ctx = UIGraphicsGetCurrentContext() else { return }
48
+
49
+ let totalHeight = rect.height
50
+ let step = barWidth + barGap
51
+ let barCount = Int(floor(rect.width / step))
52
+ guard barCount > 0 else { return }
53
+
54
+ // Keep bars from touching the container edges
55
+ let verticalPadding = barWidth * 1.5
56
+ let drawableHeight = totalHeight - verticalPadding * 2
57
+ guard drawableHeight > 0 else { return }
58
+ let minBarHeight = barWidth
59
+
60
+ ctx.setFillColor(barColor.cgColor)
61
+
62
+ for i in 0..<barCount {
63
+ let ampIndex = i * amplitudes.count / barCount
64
+ let amp = amplitudes[min(ampIndex, amplitudes.count - 1)]
65
+ let barHeight = max(minBarHeight, amp * drawableHeight)
66
+ let x = CGFloat(i) * step
67
+ let y = verticalPadding + (drawableHeight - barHeight) / 2.0
68
+ let barRect = CGRect(x: x, y: y, width: barWidth, height: barHeight)
69
+ let path = UIBezierPath(roundedRect: barRect, cornerRadius: barCornerRadius)
70
+ ctx.addPath(path.cgPath)
71
+ }
72
+
73
+ ctx.fillPath()
74
+ }
75
+ }
package/ios/VideoTrim.mm CHANGED
@@ -73,8 +73,10 @@ RCT_EXPORT_MODULE()
73
73
  dict[@"startTime"] = @(options.startTime());
74
74
  dict[@"endTime"] = @(options.endTime());
75
75
  dict[@"enablePreciseTrimming"] = @(options.enablePreciseTrimming());
76
+ dict[@"removeAudio"] = @(options.removeAudio());
77
+ dict[@"speed"] = @(options.speed());
76
78
 
77
- [self->videoTrim trim:url url:dict config:^(NSDictionary<NSString *,id> * _Nonnull result) {
79
+ [self->videoTrim trimWithInputFile:url config:dict completion:^(NSDictionary<NSString *,id> * _Nonnull result) {
78
80
  BOOL success = [result[@"success"] boolValue];
79
81
  if (success) {
80
82
  resolve(result);
@@ -143,6 +145,8 @@ RCT_EXPORT_MODULE()
143
145
  dict[@"alertOnFailMessage"] = config.alertOnFailMessage();
144
146
  dict[@"alertOnFailCloseText"] = config.alertOnFailCloseText();
145
147
  dict[@"enablePreciseTrimming"] = @(config.enablePreciseTrimming());
148
+ dict[@"removeAudio"] = @(config.removeAudio());
149
+ dict[@"speed"] = @(config.speed());
146
150
 
147
151
  // Handle optional color values
148
152
  auto trimmerColorOpt = config.trimmerColor();
@@ -155,6 +159,31 @@ RCT_EXPORT_MODULE()
155
159
  dict[@"handleIconColor"] = @(handleIconColorOpt.value());
156
160
  }
157
161
 
162
+ auto waveformColorOpt = config.waveformColor();
163
+ if (waveformColorOpt.has_value()) {
164
+ dict[@"waveformColor"] = @(waveformColorOpt.value());
165
+ }
166
+
167
+ auto waveformBackgroundColorOpt = config.waveformBackgroundColor();
168
+ if (waveformBackgroundColorOpt.has_value()) {
169
+ dict[@"waveformBackgroundColor"] = @(waveformBackgroundColorOpt.value());
170
+ }
171
+
172
+ auto waveformBarWidthOpt = config.waveformBarWidth();
173
+ if (waveformBarWidthOpt.has_value()) {
174
+ dict[@"waveformBarWidth"] = @(waveformBarWidthOpt.value());
175
+ }
176
+
177
+ auto waveformBarGapOpt = config.waveformBarGap();
178
+ if (waveformBarGapOpt.has_value()) {
179
+ dict[@"waveformBarGap"] = @(waveformBarGapOpt.value());
180
+ }
181
+
182
+ auto waveformBarCornerRadiusOpt = config.waveformBarCornerRadius();
183
+ if (waveformBarCornerRadiusOpt.has_value()) {
184
+ dict[@"waveformBarCornerRadius"] = @(waveformBarCornerRadiusOpt.value());
185
+ }
186
+
158
187
  auto zoomOnWaitingDurationOpt = config.zoomOnWaitingDuration();
159
188
  if (zoomOnWaitingDurationOpt.has_value()) {
160
189
  dict[@"zoomOnWaitingDuration"] = @(zoomOnWaitingDurationOpt.value());
@@ -168,6 +197,135 @@ RCT_EXPORT_MODULE()
168
197
  [self->videoTrim showEditor:filePath withConfig:dict];
169
198
  }
170
199
 
200
+ - (void)getFrameAt:(nonnull NSString *)url
201
+ options:(JS::NativeVideoTrim::FrameExtractionOptions &)options
202
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
203
+ reject:(nonnull RCTPromiseRejectBlock)reject {
204
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
205
+ dict[@"time"] = @(options.time());
206
+ dict[@"format"] = options.format();
207
+ dict[@"quality"] = @(options.quality());
208
+ dict[@"maxWidth"] = @(options.maxWidth());
209
+ dict[@"maxHeight"] = @(options.maxHeight());
210
+
211
+ [VideoTrimSwift getFrameAt:url options:dict completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
212
+ if (result[@"error"]) {
213
+ reject(@"ERR_FRAME_EXTRACTION", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
214
+ } else {
215
+ resolve(result);
216
+ }
217
+ }];
218
+ }
219
+
220
+ - (void)extractAudio:(nonnull NSString *)url
221
+ options:(JS::NativeVideoTrim::ExtractAudioOptions &)options
222
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
223
+ reject:(nonnull RCTPromiseRejectBlock)reject {
224
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
225
+ dict[@"outputExt"] = options.outputExt();
226
+
227
+ [VideoTrimSwift extractAudio:url options:dict completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
228
+ if (result[@"error"]) {
229
+ reject(@"ERR_EXTRACT_AUDIO", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
230
+ } else {
231
+ resolve(result);
232
+ }
233
+ }];
234
+ }
235
+
236
+ - (void)compress:(nonnull NSString *)url
237
+ options:(JS::NativeVideoTrim::CompressOptions &)options
238
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
239
+ reject:(nonnull RCTPromiseRejectBlock)reject {
240
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
241
+ dict[@"quality"] = options.quality();
242
+ dict[@"bitrate"] = @(options.bitrate());
243
+ dict[@"width"] = @(options.width());
244
+ dict[@"height"] = @(options.height());
245
+ dict[@"frameRate"] = @(options.frameRate());
246
+ dict[@"outputExt"] = options.outputExt();
247
+ dict[@"removeAudio"] = @(options.removeAudio());
248
+
249
+ [VideoTrimSwift compress:url options:dict completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
250
+ if (result[@"error"]) {
251
+ reject(@"ERR_COMPRESS", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
252
+ } else {
253
+ resolve(result);
254
+ }
255
+ }];
256
+ }
257
+
258
+ - (void)toGif:(nonnull NSString *)url
259
+ options:(JS::NativeVideoTrim::GifOptions &)options
260
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
261
+ reject:(nonnull RCTPromiseRejectBlock)reject {
262
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
263
+ dict[@"startTime"] = @(options.startTime());
264
+ dict[@"endTime"] = @(options.endTime());
265
+ dict[@"fps"] = @(options.fps());
266
+ dict[@"width"] = @(options.width());
267
+
268
+ [VideoTrimSwift toGif:url options:dict completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
269
+ if (result[@"error"]) {
270
+ reject(@"ERR_GIF", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
271
+ } else {
272
+ resolve(result);
273
+ }
274
+ }];
275
+ }
276
+
277
+ - (void)merge:(nonnull NSArray<NSString *> *)urls
278
+ options:(JS::NativeVideoTrim::MergeOptions &)options
279
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
280
+ reject:(nonnull RCTPromiseRejectBlock)reject {
281
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
282
+ dict[@"outputExt"] = options.outputExt();
283
+
284
+ [VideoTrimSwift merge:urls options:dict completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
285
+ if (result[@"error"]) {
286
+ reject(@"ERR_MERGE", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
287
+ } else {
288
+ resolve(result);
289
+ }
290
+ }];
291
+ }
292
+
293
+ - (void)saveToPhoto:(nonnull NSString *)filePath
294
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
295
+ reject:(nonnull RCTPromiseRejectBlock)reject {
296
+ [VideoTrimSwift saveToPhoto:filePath completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
297
+ if (result[@"error"]) {
298
+ reject(@"ERR_SAVE_TO_PHOTO", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
299
+ } else {
300
+ resolve(result);
301
+ }
302
+ }];
303
+ }
304
+
305
+ - (void)saveToDocuments:(nonnull NSString *)filePath
306
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
307
+ reject:(nonnull RCTPromiseRejectBlock)reject {
308
+ [VideoTrimSwift saveToDocuments:filePath completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
309
+ if (result[@"error"]) {
310
+ reject(@"ERR_SAVE_TO_DOCUMENTS", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
311
+ } else {
312
+ resolve(result);
313
+ }
314
+ }];
315
+ }
316
+
317
+ - (void)share:(nonnull NSString *)filePath
318
+ resolve:(nonnull RCTPromiseResolveBlock)resolve
319
+ reject:(nonnull RCTPromiseRejectBlock)reject {
320
+ [VideoTrimSwift share:filePath completion:^(NSDictionary<NSString *, id> * _Nonnull result) {
321
+ if (result[@"error"]) {
322
+ reject(@"ERR_SHARE", result[@"error"], [NSError errorWithDomain:@"" code:200 userInfo:nil]);
323
+ } else {
324
+ resolve(result);
325
+ }
326
+ }];
327
+ }
328
+
171
329
  - (void)closeEditor {
172
330
  if (self->videoTrim) {
173
331
  [self->videoTrim closeEditor:0];
@@ -228,6 +386,27 @@ RCT_EXTERN_METHOD(isValidFile:(NSString*)uri withResolver:(RCTPromiseResolveBloc
228
386
  RCT_EXTERN_METHOD(trim:(NSString*)uri withConfig:(NSDictionary *)config
229
387
  withResolver:(RCTPromiseResolveBlock)resolve
230
388
  withRejecter:(RCTPromiseRejectBlock)reject)
389
+ RCT_EXTERN_METHOD(getFrameAt:(NSString*)url withOptions:(NSDictionary *)options
390
+ withResolver:(RCTPromiseResolveBlock)resolve
391
+ withRejecter:(RCTPromiseRejectBlock)reject)
392
+ RCT_EXTERN_METHOD(extractAudio:(NSString*)url withOptions:(NSDictionary *)options
393
+ withResolver:(RCTPromiseResolveBlock)resolve
394
+ withRejecter:(RCTPromiseRejectBlock)reject)
395
+ RCT_EXTERN_METHOD(compress:(NSString*)url withOptions:(NSDictionary *)options
396
+ withResolver:(RCTPromiseResolveBlock)resolve
397
+ withRejecter:(RCTPromiseRejectBlock)reject)
398
+ RCT_EXTERN_METHOD(toGif:(NSString*)url withOptions:(NSDictionary *)options
399
+ withResolver:(RCTPromiseResolveBlock)resolve
400
+ withRejecter:(RCTPromiseRejectBlock)reject)
401
+ RCT_EXTERN_METHOD(merge:(NSArray *)urls withOptions:(NSDictionary *)options
402
+ withResolver:(RCTPromiseResolveBlock)resolve
403
+ withRejecter:(RCTPromiseRejectBlock)reject)
404
+ RCT_EXTERN_METHOD(saveToPhoto:(NSString*)filePath withResolver:(RCTPromiseResolveBlock)resolve
405
+ withRejecter:(RCTPromiseRejectBlock)reject)
406
+ RCT_EXTERN_METHOD(saveToDocuments:(NSString*)filePath withResolver:(RCTPromiseResolveBlock)resolve
407
+ withRejecter:(RCTPromiseRejectBlock)reject)
408
+ RCT_EXTERN_METHOD(share:(NSString*)filePath withResolver:(RCTPromiseResolveBlock)resolve
409
+ withRejecter:(RCTPromiseRejectBlock)reject)
231
410
  @end
232
411
 
233
412
  #endif