Skip to content

Commit

Permalink
feat(Processing): Provided standalone APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
Shahen Hovhannisyan committed Mar 17, 2017
1 parent 18d015c commit c853b2e
Show file tree
Hide file tree
Showing 10 changed files with 290 additions and 22 deletions.
7 changes: 7 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[ignore]
./node_modules
[include]
./lib
[libs]

[options]
35 changes: 17 additions & 18 deletions android/react-native-video-processing.iml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<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">
<component name="FacetManager">
<facet type="android-gradle" name="Android-Gradle">
<configuration>
Expand Down Expand Up @@ -32,12 +32,14 @@
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/apt/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
Expand All @@ -64,14 +66,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
Expand All @@ -80,12 +74,16 @@
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/annotations" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/23.0.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
Expand All @@ -95,17 +93,17 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline-okhttp/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.fresco/imagepipeline/0.8.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.facebook.react/react-native/0.20.1/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.github.wseemann/FFmpegMediaMetadataRetriever/1.0.14/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.yqritc/android-scalablevideoview/1.0.4/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/org.webkit/android-jsc/r174650/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 23 Platform (1)" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
Expand All @@ -116,8 +114,8 @@
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jsr305-3.0.0" level="project" />
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
Expand All @@ -127,6 +125,7 @@
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
<orderEntry type="library" exported="" name="FFmpegMediaMetadataRetriever-1.0.14" level="project" />
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
<orderEntry type="library" exported="" name="react-native-0.20.1" level="project" />
Expand Down
81 changes: 81 additions & 0 deletions android/src/main/java/com/shahenlibrary/Trimmer/Trimmer.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,25 @@
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.events.Event;
import com.shahenlibrary.Events.Events;
import com.shahenlibrary.Events.EventsEnum;
import com.shahenlibrary.interfaces.OnTrimVideoListener;
import com.shahenlibrary.utils.VideoEdit;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

import wseemann.media.FFmpegMediaMetadataRetriever;

public class Trimmer {

private static final String LOG_TAG = "RNTrimmerManager";

public static void getPreviewImages(String path, Promise promise, ReactApplicationContext ctx) {
FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
if (VideoEdit.shouldUseURI(path)) {
Expand Down Expand Up @@ -129,4 +136,78 @@ public static void getVideoInfo(String path, Promise promise, ReactApplicationCo

mmr.release();
}

static void trim(ReadableMap options, final Promise promise) {
double startMs = options.getDouble("startTime");
double endMs = options.getDouble("endTime");
String mediaSource = options.getString("source");

OnTrimVideoListener trimVideoListener = new OnTrimVideoListener() {
@Override
public void onError(String message) {
Log.d(LOG_TAG, "Trimmed onError: " + message);
WritableMap event = Arguments.createMap();
event.putString(Events.ERROR_TRIM, message);

promise.reject("trim error", message);
}

@Override
public void onTrimStarted() {
Log.d(LOG_TAG, "Trimmed onTrimStarted");
}

@Override
public void getResult(Uri uri) {
Log.d(LOG_TAG, "getResult: " + uri.toString());
WritableMap event = Arguments.createMap();
event.putString("source", uri.toString());
promise.resolve(event);
}

@Override
public void cancelAction() {
Log.d(LOG_TAG, "Trimmed cancelAction");
}
};
Log.d(LOG_TAG, "trimMedia at : startAt -> " + startMs + " : endAt -> " + endMs);
File mediaFile = new File(mediaSource.replace("file:///", "/"));
long startTrimFromPos = (long) startMs * 1000;
long endTrimFromPos = (long) endMs * 1000;
String[] dPath = mediaSource.split("/");
StringBuilder builder = new StringBuilder();
for (int i = 0; i < dPath.length; ++i) {
if (i == dPath.length - 1) {
continue;
}
builder.append(dPath[i]);
builder.append(File.separator);
}
String path = builder.toString().replace("file:///", "/");

Log.d(LOG_TAG, "trimMedia: " + mediaFile.toString() + " isExists: " + mediaFile.exists());
try {
VideoEdit.startTrim(mediaFile, path, startTrimFromPos, endTrimFromPos, trimVideoListener);
} catch (IOException e) {
trimVideoListener.onError(e.toString());
e.printStackTrace();
Log.d(LOG_TAG, "trimMedia: error -> " + e.toString());
}
}

static void getPreviewAtPosition(String source, double sec, final Promise promise) {
FFmpegMediaMetadataRetriever metadataRetriever = new FFmpegMediaMetadataRetriever();
metadataRetriever.setDataSource(source);

Bitmap bmp = metadataRetriever.getFrameAtTime((long) (sec * 1000000));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);

WritableMap event = Arguments.createMap();
event.putString("image", encoded);

promise.resolve(event);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;

public class TrimmerManager extends ReactContextBaseJavaModule {
public static final String REACT_PACKAGE = "RNTrimmerManager";
static final String REACT_PACKAGE = "RNTrimmerManager";

private final ReactApplicationContext reactContext;

Expand All @@ -57,4 +58,22 @@ public void getVideoInfo(String path, Promise promise) {
Log.d(REACT_PACKAGE, "getVideoInfo: " + path);
Trimmer.getVideoInfo(path, promise, reactContext);
}

@ReactMethod
public void trim(ReadableMap options, Promise promise) {
Log.d(REACT_PACKAGE, options.toString());
Trimmer.trim(options, promise);
}
@ReactMethod
public void compress(ReadableMap options, Promise promise) {
Log.d(REACT_PACKAGE, "compress: not supported");
promise.reject("not supported on android", "");
}

@ReactMethod
public void getPreviewImageAtPosition(ReadableMap options, Promise promise) {
String source = options.getString("source");
double sec = options.getDouble("second");
Trimmer.getPreviewAtPosition(source, sec, promise);
}
}
36 changes: 36 additions & 0 deletions lib/ProcessingManager/ProcessingManager.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// @flow

import { NativeModules } from 'react-native';
import type {
sourceType,
trimOptions
} from './types';

import { getActualSource } from '../utils';

const { RNTrimmerManager: TrimmerManager } = NativeModules;
class ProcessingManager {
static trim(source: sourceType, options: trimOptions): Promise<string> {
const actualSource: string = getActualSource(source);
const mData = { source: actualSource, ...options };
return TrimmerManager.trim(mData)
.then((res) => res.source);
}
static compress(source: sourceType, options: any): Promise<*> {
const actualSource: string = getActualSource(source);
const mData = { source: actualSource, ...options };
return TrimmerManager.compress(mData);
}
static getVideoInfo(source: sourceType): Promise<*> {
const actualSource: string = getActualSource(source);
return TrimmerManager.getVideoInfo(actualSource);
}
static getPreviewForSecond(source: sourceType, second: number): Promise<*> {
const actualSource: string = getActualSource(source);
const mData = { source: actualSource, second };
return TrimmerManager.getPreviewImageAtPosition(mData)
.then((res) => res.image);
}
}

export default ProcessingManager;
67 changes: 67 additions & 0 deletions lib/ProcessingManager/ProcessingManager.ios.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// @flow


import { NativeModules } from 'react-native';
import { getActualSource } from '../utils';
const { RNVideoTrimmer } = NativeModules;
import type {
compressOptions,
previewMaxSize,
sourceType,
trimOptions,
} from './types';

export class ProcessingManager {
static trim(source: sourceType, options: trimOptions = {}) {
const actualSource: string = getActualSource(source);
return new Promise((resolve, reject) => {
RNVideoTrimmer.trim(actualSource, options, (err: Object<*>, output: string) => {
if (err) {
return reject(err);
}
return resolve(output);
});
});
};
static getPreviewForSecond(
source: sourceType,
forSecond: ?number = 0,
maximumSize: previewMaxSize
) {
const actualSource: string = getActualSource(source);
return new Promise((resolve, reject) => {
RNVideoTrimmer.getPreviewImageAtPosition(actualSource, forSecond, maximumSize,
(err: Object<*>, base64: string) => {
if (err) {
return reject(err);
}
return resolve(base64);
});
});
}
static getVideoInfo(source: sourceType) {
const actualSource: string = getActualSource(source);
return new Promise((resolve, reject) => {
RNVideoTrimmer.getAssetInfo(actualSource, (err, info) => {
if (err) {
return reject(err);
}
return resolve(info);
});
});
}
static compress(source: sourceType, _options: compressOptions) {
const options = { ..._options };
const actualSource = getActualSource(source);
return new Promise((resolve, reject) => {
RNVideoTrimmer.compress(actualSource, options, (err, output) => {
if (err) {
return reject(err);
}
return resolve(output);
});
});
}
}

export default ProcessingManager;
1 change: 1 addition & 0 deletions lib/ProcessingManager/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export ProcessingManager from './ProcessingManager';
17 changes: 17 additions & 0 deletions lib/ProcessingManager/types.android.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @flow

export type sourceType = string
| { uri: string };

export type trimOptions = {
startTime: number,
endTime: number
};

declare class RNTrimmerManager {
static trim(source: string, options: trimOptions): Promise<{ source: string }>;
static compress(source: string, options: any): Promise<*>;
static getVideoInfo(source: string): Promise<*>;
static getPreviewImages(source: string): Promise<*>;
static getPreviewImageAtPosition(source: string, second: number): Promise<{ image: string }>;
}
Loading

0 comments on commit c853b2e

Please sign in to comment.