Skip to content

Commit c853b2e

Browse files
author
Shahen Hovhannisyan
committed
feat(Processing): Provided standalone APIs
1 parent 18d015c commit c853b2e

File tree

10 files changed

+290
-22
lines changed

10 files changed

+290
-22
lines changed

.flowconfig

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[ignore]
2+
./node_modules
3+
[include]
4+
./lib
5+
[libs]
6+
7+
[options]

android/react-native-video-processing.iml

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<module external.linked.project.id=":react-native-video-processing" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../../android" external.system.id="GRADLE" external.system.module.group="vp" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
2+
<module external.linked.project.id=":react-native-video-processing" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/../../android" external.system.id="GRADLE" external.system.module.group="vp" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
33
<component name="FacetManager">
44
<facet type="android-gradle" name="Android-Gradle">
55
<configuration>
@@ -32,12 +32,14 @@
3232
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
3333
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
3434
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
35+
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
3536
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
3637
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
3738
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
3839
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
3940
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
4041
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
42+
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
4143
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
4244
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
4345
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
@@ -64,14 +66,6 @@
6466
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
6567
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
6668
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
67-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
68-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
69-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
70-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
71-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
72-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
73-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
74-
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
7569
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
7670
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
7771
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
@@ -80,12 +74,16 @@
8074
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
8175
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
8276
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
83-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" />
84-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
77+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
78+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
79+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
80+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
81+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
82+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
83+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
84+
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
8585
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
8686
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
87-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
88-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
8987
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
9088
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
9189
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
@@ -95,17 +93,17 @@
9593
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
9694
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
9795
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.20.1/jars" />
96+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.github.wseemann/FFmpegMediaMetadataRetriever/1.0.14/jars" />
97+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.yqritc/android-scalablevideoview/1.0.4/jars" />
98+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
9899
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
99-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
100-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
101100
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
101+
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
102102
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
103103
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
104104
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
105105
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
106-
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
107106
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
108-
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
109107
</content>
110108
<orderEntry type="jdk" jdkName="Android API 23 Platform (1)" jdkType="Android SDK" />
111109
<orderEntry type="sourceFolder" forTests="false" />
@@ -116,8 +114,8 @@
116114
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
117115
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
118116
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
119-
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
120117
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
118+
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
121119
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
122120
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
123121
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
@@ -127,6 +125,7 @@
127125
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
128126
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
129127
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
128+
<orderEntry type="library" exported="" name="FFmpegMediaMetadataRetriever-1.0.14" level="project" />
130129
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
131130
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
132131
<orderEntry type="library" exported="" name="react-native-0.20.1" level="project" />

android/src/main/java/com/shahenlibrary/Trimmer/Trimmer.java

+81
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,25 @@
3636
import com.facebook.react.bridge.Arguments;
3737
import com.facebook.react.bridge.Promise;
3838
import com.facebook.react.bridge.ReactApplicationContext;
39+
import com.facebook.react.bridge.ReadableMap;
3940
import com.facebook.react.bridge.WritableArray;
4041
import com.facebook.react.bridge.WritableMap;
4142
import com.facebook.react.uimanager.events.Event;
4243
import com.shahenlibrary.Events.Events;
44+
import com.shahenlibrary.Events.EventsEnum;
45+
import com.shahenlibrary.interfaces.OnTrimVideoListener;
4346
import com.shahenlibrary.utils.VideoEdit;
4447

4548
import java.io.ByteArrayOutputStream;
49+
import java.io.File;
50+
import java.io.IOException;
4651

4752
import wseemann.media.FFmpegMediaMetadataRetriever;
4853

4954
public class Trimmer {
5055

56+
private static final String LOG_TAG = "RNTrimmerManager";
57+
5158
public static void getPreviewImages(String path, Promise promise, ReactApplicationContext ctx) {
5259
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
5360
if (VideoEdit.shouldUseURI(path)) {
@@ -129,4 +136,78 @@ public static void getVideoInfo(String path, Promise promise, ReactApplicationCo
129136

130137
mmr.release();
131138
}
139+
140+
static void trim(ReadableMap options, final Promise promise) {
141+
double startMs = options.getDouble("startTime");
142+
double endMs = options.getDouble("endTime");
143+
String mediaSource = options.getString("source");
144+
145+
OnTrimVideoListener trimVideoListener = new OnTrimVideoListener() {
146+
@Override
147+
public void onError(String message) {
148+
Log.d(LOG_TAG, "Trimmed onError: " + message);
149+
WritableMap event = Arguments.createMap();
150+
event.putString(Events.ERROR_TRIM, message);
151+
152+
promise.reject("trim error", message);
153+
}
154+
155+
@Override
156+
public void onTrimStarted() {
157+
Log.d(LOG_TAG, "Trimmed onTrimStarted");
158+
}
159+
160+
@Override
161+
public void getResult(Uri uri) {
162+
Log.d(LOG_TAG, "getResult: " + uri.toString());
163+
WritableMap event = Arguments.createMap();
164+
event.putString("source", uri.toString());
165+
promise.resolve(event);
166+
}
167+
168+
@Override
169+
public void cancelAction() {
170+
Log.d(LOG_TAG, "Trimmed cancelAction");
171+
}
172+
};
173+
Log.d(LOG_TAG, "trimMedia at : startAt -> " + startMs + " : endAt -> " + endMs);
174+
File mediaFile = new File(mediaSource.replace("file:///", "/"));
175+
long startTrimFromPos = (long) startMs * 1000;
176+
long endTrimFromPos = (long) endMs * 1000;
177+
String[] dPath = mediaSource.split("/");
178+
StringBuilder builder = new StringBuilder();
179+
for (int i = 0; i < dPath.length; ++i) {
180+
if (i == dPath.length - 1) {
181+
continue;
182+
}
183+
builder.append(dPath[i]);
184+
builder.append(File.separator);
185+
}
186+
String path = builder.toString().replace("file:///", "/");
187+
188+
Log.d(LOG_TAG, "trimMedia: " + mediaFile.toString() + " isExists: " + mediaFile.exists());
189+
try {
190+
VideoEdit.startTrim(mediaFile, path, startTrimFromPos, endTrimFromPos, trimVideoListener);
191+
} catch (IOException e) {
192+
trimVideoListener.onError(e.toString());
193+
e.printStackTrace();
194+
Log.d(LOG_TAG, "trimMedia: error -> " + e.toString());
195+
}
196+
}
197+
198+
static void getPreviewAtPosition(String source, double sec, final Promise promise) {
199+
FFmpegMediaMetadataRetriever metadataRetriever = new FFmpegMediaMetadataRetriever();
200+
metadataRetriever.setDataSource(source);
201+
202+
Bitmap bmp = metadataRetriever.getFrameAtTime((long) (sec * 1000000));
203+
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
204+
bmp.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
205+
byte[] byteArray = byteArrayOutputStream .toByteArray();
206+
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
207+
208+
WritableMap event = Arguments.createMap();
209+
event.putString("image", encoded);
210+
211+
promise.resolve(event);
212+
}
132213
}

android/src/main/java/com/shahenlibrary/Trimmer/TrimmerManager.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030
import com.facebook.react.bridge.ReactApplicationContext;
3131
import com.facebook.react.bridge.ReactContextBaseJavaModule;
3232
import com.facebook.react.bridge.ReactMethod;
33+
import com.facebook.react.bridge.ReadableMap;
3334

3435
public class TrimmerManager extends ReactContextBaseJavaModule {
35-
public static final String REACT_PACKAGE = "RNTrimmerManager";
36+
static final String REACT_PACKAGE = "RNTrimmerManager";
3637

3738
private final ReactApplicationContext reactContext;
3839

@@ -57,4 +58,22 @@ public void getVideoInfo(String path, Promise promise) {
5758
Log.d(REACT_PACKAGE, "getVideoInfo: " + path);
5859
Trimmer.getVideoInfo(path, promise, reactContext);
5960
}
61+
62+
@ReactMethod
63+
public void trim(ReadableMap options, Promise promise) {
64+
Log.d(REACT_PACKAGE, options.toString());
65+
Trimmer.trim(options, promise);
66+
}
67+
@ReactMethod
68+
public void compress(ReadableMap options, Promise promise) {
69+
Log.d(REACT_PACKAGE, "compress: not supported");
70+
promise.reject("not supported on android", "");
71+
}
72+
73+
@ReactMethod
74+
public void getPreviewImageAtPosition(ReadableMap options, Promise promise) {
75+
String source = options.getString("source");
76+
double sec = options.getDouble("second");
77+
Trimmer.getPreviewAtPosition(source, sec, promise);
78+
}
6079
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// @flow
2+
3+
import { NativeModules } from 'react-native';
4+
import type {
5+
sourceType,
6+
trimOptions
7+
} from './types';
8+
9+
import { getActualSource } from '../utils';
10+
11+
const { RNTrimmerManager: TrimmerManager } = NativeModules;
12+
class ProcessingManager {
13+
static trim(source: sourceType, options: trimOptions): Promise<string> {
14+
const actualSource: string = getActualSource(source);
15+
const mData = { source: actualSource, ...options };
16+
return TrimmerManager.trim(mData)
17+
.then((res) => res.source);
18+
}
19+
static compress(source: sourceType, options: any): Promise<*> {
20+
const actualSource: string = getActualSource(source);
21+
const mData = { source: actualSource, ...options };
22+
return TrimmerManager.compress(mData);
23+
}
24+
static getVideoInfo(source: sourceType): Promise<*> {
25+
const actualSource: string = getActualSource(source);
26+
return TrimmerManager.getVideoInfo(actualSource);
27+
}
28+
static getPreviewForSecond(source: sourceType, second: number): Promise<*> {
29+
const actualSource: string = getActualSource(source);
30+
const mData = { source: actualSource, second };
31+
return TrimmerManager.getPreviewImageAtPosition(mData)
32+
.then((res) => res.image);
33+
}
34+
}
35+
36+
export default ProcessingManager;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// @flow
2+
3+
4+
import { NativeModules } from 'react-native';
5+
import { getActualSource } from '../utils';
6+
const { RNVideoTrimmer } = NativeModules;
7+
import type {
8+
compressOptions,
9+
previewMaxSize,
10+
sourceType,
11+
trimOptions,
12+
} from './types';
13+
14+
export class ProcessingManager {
15+
static trim(source: sourceType, options: trimOptions = {}) {
16+
const actualSource: string = getActualSource(source);
17+
return new Promise((resolve, reject) => {
18+
RNVideoTrimmer.trim(actualSource, options, (err: Object<*>, output: string) => {
19+
if (err) {
20+
return reject(err);
21+
}
22+
return resolve(output);
23+
});
24+
});
25+
};
26+
static getPreviewForSecond(
27+
source: sourceType,
28+
forSecond: ?number = 0,
29+
maximumSize: previewMaxSize
30+
) {
31+
const actualSource: string = getActualSource(source);
32+
return new Promise((resolve, reject) => {
33+
RNVideoTrimmer.getPreviewImageAtPosition(actualSource, forSecond, maximumSize,
34+
(err: Object<*>, base64: string) => {
35+
if (err) {
36+
return reject(err);
37+
}
38+
return resolve(base64);
39+
});
40+
});
41+
}
42+
static getVideoInfo(source: sourceType) {
43+
const actualSource: string = getActualSource(source);
44+
return new Promise((resolve, reject) => {
45+
RNVideoTrimmer.getAssetInfo(actualSource, (err, info) => {
46+
if (err) {
47+
return reject(err);
48+
}
49+
return resolve(info);
50+
});
51+
});
52+
}
53+
static compress(source: sourceType, _options: compressOptions) {
54+
const options = { ..._options };
55+
const actualSource = getActualSource(source);
56+
return new Promise((resolve, reject) => {
57+
RNVideoTrimmer.compress(actualSource, options, (err, output) => {
58+
if (err) {
59+
return reject(err);
60+
}
61+
return resolve(output);
62+
});
63+
});
64+
}
65+
}
66+
67+
export default ProcessingManager;

lib/ProcessingManager/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export ProcessingManager from './ProcessingManager';
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// @flow
2+
3+
export type sourceType = string
4+
| { uri: string };
5+
6+
export type trimOptions = {
7+
startTime: number,
8+
endTime: number
9+
};
10+
11+
declare class RNTrimmerManager {
12+
static trim(source: string, options: trimOptions): Promise<{ source: string }>;
13+
static compress(source: string, options: any): Promise<*>;
14+
static getVideoInfo(source: string): Promise<*>;
15+
static getPreviewImages(source: string): Promise<*>;
16+
static getPreviewImageAtPosition(source: string, second: number): Promise<{ image: string }>;
17+
}

0 commit comments

Comments
 (0)