react-native-compressor 1.1.0 → 1.3.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.
- package/README.md +72 -2
- package/android/.gradle/6.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/{6.1.1 → 6.9}/fileChanges/last-build.bin +0 -0
- package/android/.gradle/6.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/{6.1.1 → 6.9}/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -2
- package/android/.gradle/checksums/checksums.lock +0 -0
- package/android/.gradle/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/checksums/sha1-checksums.bin +0 -0
- package/android/build.gradle +0 -1
- package/android/src/main/java/com/reactnativecompressor/.DS_Store +0 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.java +3 -3
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.java +5 -1
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.java +74 -0
- package/android/src/main/java/com/reactnativecompressor/Video/.DS_Store +0 -0
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression/AutoVideoCompression.java +3 -37
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.java +2 -38
- package/android/src/main/java/com/reactnativecompressor/Video/VideoModule.java +9 -7
- package/android/src/main/java/com/reactnativecompressor/Video/videoslimmer/VideoSlimEncoder.java +629 -0
- package/android/src/main/java/com/reactnativecompressor/Video/videoslimmer/VideoSlimTask.java +59 -0
- package/android/src/main/java/com/reactnativecompressor/Video/videoslimmer/VideoSlimmer.java +20 -0
- package/android/src/main/java/com/reactnativecompressor/Video/videoslimmer/listner/SlimProgressListener.java +6 -0
- package/android/src/main/java/com/reactnativecompressor/Video/videoslimmer/muxer/CodecInputSurface.java +202 -0
- package/android/src/main/java/com/reactnativecompressor/Video/videoslimmer/render/TextureRenderer.java +196 -0
- package/app.plugin.js +1 -0
- package/ios/Compressor.m +2 -0
- package/ios/Video/VideoCompressor.swift +23 -14
- package/lib/commonjs/Video/index.js +15 -6
- package/lib/commonjs/Video/index.js.map +1 -1
- package/lib/commonjs/expo-plugin/compressor.js +17 -0
- package/lib/commonjs/expo-plugin/compressor.js.map +1 -0
- package/lib/commonjs/index.js +8 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/index.js +13 -1
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/Video/index.js +9 -2
- package/lib/module/Video/index.js.map +1 -1
- package/lib/module/expo-plugin/compressor.js +8 -0
- package/lib/module/expo-plugin/compressor.js.map +1 -0
- package/lib/module/index.js +4 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/index.js +9 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/Video/index.d.ts +3 -1
- package/lib/typescript/expo-plugin/compressor.d.ts +4 -0
- package/lib/typescript/index.d.ts +3 -2
- package/lib/typescript/utils/index.d.ts +1 -0
- package/package.json +4 -7
- package/src/Video/index.tsx +12 -8
- package/src/expo-plugin/compressor.ts +8 -0
- package/src/index.tsx +3 -1
- package/src/utils/index.tsx +17 -0
- package/android/.gradle/6.1.1/executionHistory/executionHistory.bin +0 -0
- package/android/.gradle/6.1.1/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/6.1.1/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/6.1.1/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video.videoslimmer;
|
|
2
|
+
|
|
3
|
+
public class VideoSlimmer {
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
public static VideoSlimTask convertVideo(String srcPath, String destPath, int outputWidth, int outputHeight, int bitrate, ProgressListener listener) {
|
|
7
|
+
VideoSlimTask task = new VideoSlimTask(listener);
|
|
8
|
+
task.execute(srcPath, destPath, outputWidth, outputHeight, bitrate);
|
|
9
|
+
return task;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public static interface ProgressListener {
|
|
13
|
+
|
|
14
|
+
void onStart();
|
|
15
|
+
void onFinish(boolean result);
|
|
16
|
+
void onProgress(float progress);
|
|
17
|
+
void onError(String errorMessage);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video.videoslimmer.muxer;
|
|
2
|
+
|
|
3
|
+
import android.graphics.SurfaceTexture;
|
|
4
|
+
import android.opengl.EGL14;
|
|
5
|
+
import android.opengl.EGLConfig;
|
|
6
|
+
import android.opengl.EGLContext;
|
|
7
|
+
import android.opengl.EGLDisplay;
|
|
8
|
+
import android.opengl.EGLExt;
|
|
9
|
+
import android.opengl.EGLSurface;
|
|
10
|
+
import android.view.Surface;
|
|
11
|
+
|
|
12
|
+
import com.reactnativecompressor.Video.videoslimmer.render.TextureRenderer;
|
|
13
|
+
|
|
14
|
+
import java.nio.ByteBuffer;
|
|
15
|
+
|
|
16
|
+
public class CodecInputSurface implements SurfaceTexture.OnFrameAvailableListener {
|
|
17
|
+
private static final int EGL_RECORDABLE_ANDROID = 0x3142;
|
|
18
|
+
|
|
19
|
+
private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
|
|
20
|
+
private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
|
|
21
|
+
private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
|
|
22
|
+
private SurfaceTexture mSurfaceTexture;
|
|
23
|
+
private Surface mSurface;
|
|
24
|
+
private Surface mDrawSurface;
|
|
25
|
+
private final Object mFrameSyncObject = new Object();
|
|
26
|
+
private boolean mFrameAvailable;
|
|
27
|
+
private ByteBuffer mPixelBuf;
|
|
28
|
+
private TextureRenderer mTextureRender;
|
|
29
|
+
/**
|
|
30
|
+
* Creates a CodecInputSurface from a Surface.
|
|
31
|
+
*/
|
|
32
|
+
public CodecInputSurface(Surface surface) {
|
|
33
|
+
if (surface == null) {
|
|
34
|
+
throw new NullPointerException();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
mSurface = surface;
|
|
38
|
+
eglSetup();
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public void createRender() {
|
|
43
|
+
mTextureRender = new TextureRenderer();
|
|
44
|
+
mTextureRender.surfaceCreated();
|
|
45
|
+
mSurfaceTexture = new SurfaceTexture(mTextureRender.getTextureId());
|
|
46
|
+
mSurfaceTexture.setOnFrameAvailableListener(this);
|
|
47
|
+
mDrawSurface = new Surface(mSurfaceTexture);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Prepares EGL. We want a GLES 2.0 context and a surface that supports recording.
|
|
52
|
+
*/
|
|
53
|
+
private void eglSetup() {
|
|
54
|
+
mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
|
|
55
|
+
if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
|
|
56
|
+
throw new RuntimeException("unable to get EGL14 display");
|
|
57
|
+
}
|
|
58
|
+
int[] version = new int[2];
|
|
59
|
+
if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
|
|
60
|
+
throw new RuntimeException("unable to initialize EGL14");
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Configure EGL for recording and OpenGL ES 2.0.
|
|
64
|
+
int[] attribList = {
|
|
65
|
+
EGL14.EGL_RED_SIZE, 8,
|
|
66
|
+
EGL14.EGL_GREEN_SIZE, 8,
|
|
67
|
+
EGL14.EGL_BLUE_SIZE, 8,
|
|
68
|
+
EGL14.EGL_ALPHA_SIZE, 8,
|
|
69
|
+
EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
|
70
|
+
EGL_RECORDABLE_ANDROID, 1,
|
|
71
|
+
EGL14.EGL_NONE
|
|
72
|
+
};
|
|
73
|
+
EGLConfig[] configs = new EGLConfig[1];
|
|
74
|
+
int[] numConfigs = new int[1];
|
|
75
|
+
EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
|
|
76
|
+
numConfigs, 0);
|
|
77
|
+
checkEglError("eglCreateContext RGB888+recordable ES2");
|
|
78
|
+
|
|
79
|
+
// Configure context for OpenGL ES 2.0.
|
|
80
|
+
int[] attrib_list = {
|
|
81
|
+
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
|
|
82
|
+
EGL14.EGL_NONE
|
|
83
|
+
};
|
|
84
|
+
mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
|
|
85
|
+
attrib_list, 0);
|
|
86
|
+
checkEglError("eglCreateContext");
|
|
87
|
+
|
|
88
|
+
// Create a window surface, and attach it to the Surface we received.
|
|
89
|
+
int[] surfaceAttribs = {
|
|
90
|
+
EGL14.EGL_NONE
|
|
91
|
+
};
|
|
92
|
+
mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
|
|
93
|
+
surfaceAttribs, 0);
|
|
94
|
+
checkEglError("eglCreateWindowSurface");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public SurfaceTexture getSurfaceTexture() {
|
|
98
|
+
return mSurfaceTexture;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public void changeFragmentShader(String fragmentShader) {
|
|
102
|
+
mTextureRender.changeFragmentShader(fragmentShader);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
public void awaitNewImage() {
|
|
108
|
+
final int TIMEOUT_MS = 5000;
|
|
109
|
+
synchronized (mFrameSyncObject) {
|
|
110
|
+
while (!mFrameAvailable) {
|
|
111
|
+
try {
|
|
112
|
+
mFrameSyncObject.wait(TIMEOUT_MS);
|
|
113
|
+
if (!mFrameAvailable) {
|
|
114
|
+
throw new RuntimeException("Surface frame wait timed out");
|
|
115
|
+
}
|
|
116
|
+
} catch (InterruptedException ie) {
|
|
117
|
+
throw new RuntimeException(ie);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
mFrameAvailable = false;
|
|
121
|
+
}
|
|
122
|
+
mTextureRender.checkGlError("before updateTexImage");
|
|
123
|
+
mSurfaceTexture.updateTexImage();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public void drawImage() {
|
|
127
|
+
mTextureRender.drawFrame(mSurfaceTexture);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@Override
|
|
131
|
+
public void onFrameAvailable(SurfaceTexture st) {
|
|
132
|
+
synchronized (mFrameSyncObject) {
|
|
133
|
+
if (mFrameAvailable) {
|
|
134
|
+
throw new RuntimeException("mFrameAvailable already set, frame could be dropped");
|
|
135
|
+
}
|
|
136
|
+
mFrameAvailable = true;
|
|
137
|
+
mFrameSyncObject.notifyAll();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public Surface getSurface() {
|
|
142
|
+
return mDrawSurface;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Discards all resources held by this class, notably the EGL context. Also releases the
|
|
147
|
+
* Surface that was passed to our constructor.
|
|
148
|
+
*/
|
|
149
|
+
public void release() {
|
|
150
|
+
if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
|
|
151
|
+
EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
|
|
152
|
+
EGL14.EGL_NO_CONTEXT);
|
|
153
|
+
EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
|
|
154
|
+
EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
|
|
155
|
+
EGL14.eglReleaseThread();
|
|
156
|
+
EGL14.eglTerminate(mEGLDisplay);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
mSurface.release();
|
|
160
|
+
|
|
161
|
+
mEGLDisplay = EGL14.EGL_NO_DISPLAY;
|
|
162
|
+
mEGLContext = EGL14.EGL_NO_CONTEXT;
|
|
163
|
+
mEGLSurface = EGL14.EGL_NO_SURFACE;
|
|
164
|
+
|
|
165
|
+
mSurface = null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Makes our EGL context and surface current.
|
|
170
|
+
*/
|
|
171
|
+
public void makeCurrent() {
|
|
172
|
+
EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
|
|
173
|
+
checkEglError("eglMakeCurrent");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Calls eglSwapBuffers. Use this to "publish" the current frame.
|
|
178
|
+
*/
|
|
179
|
+
public boolean swapBuffers() {
|
|
180
|
+
boolean result = EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
|
|
181
|
+
checkEglError("eglSwapBuffers");
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Sends the presentation time stamp to EGL. Time is expressed in nanoseconds.
|
|
187
|
+
*/
|
|
188
|
+
public void setPresentationTime(long nsecs) {
|
|
189
|
+
EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
|
|
190
|
+
checkEglError("eglPresentationTimeANDROID");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Checks for EGL errors. Throws an exception if one is found.
|
|
195
|
+
*/
|
|
196
|
+
private void checkEglError(String msg) {
|
|
197
|
+
int error;
|
|
198
|
+
if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
|
|
199
|
+
throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video.videoslimmer.render;
|
|
2
|
+
|
|
3
|
+
import android.graphics.SurfaceTexture;
|
|
4
|
+
import android.opengl.GLES11Ext;
|
|
5
|
+
import android.opengl.GLES20;
|
|
6
|
+
import android.opengl.Matrix;
|
|
7
|
+
|
|
8
|
+
import java.nio.ByteBuffer;
|
|
9
|
+
import java.nio.ByteOrder;
|
|
10
|
+
import java.nio.FloatBuffer;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
public class TextureRenderer {
|
|
14
|
+
|
|
15
|
+
private static final int FLOAT_SIZE_BYTES = 4;
|
|
16
|
+
private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
|
|
17
|
+
private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
|
|
18
|
+
private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
|
|
19
|
+
private static final float[] mTriangleVerticesData = {
|
|
20
|
+
-1.0f, -1.0f, 0, 0.f, 0.f,
|
|
21
|
+
1.0f, -1.0f, 0, 1.f, 0.f,
|
|
22
|
+
-1.0f, 1.0f, 0, 0.f, 1.f,
|
|
23
|
+
1.0f, 1.0f, 0, 1.f, 1.f,
|
|
24
|
+
};
|
|
25
|
+
private FloatBuffer mTriangleVertices;
|
|
26
|
+
|
|
27
|
+
private static final String VERTEX_SHADER =
|
|
28
|
+
"uniform mat4 uMVPMatrix;\n" +
|
|
29
|
+
"uniform mat4 uSTMatrix;\n" +
|
|
30
|
+
"attribute vec4 aPosition;\n" +
|
|
31
|
+
"attribute vec4 aTextureCoord;\n" +
|
|
32
|
+
"varying vec2 vTextureCoord;\n" +
|
|
33
|
+
"void main() {\n" +
|
|
34
|
+
" gl_Position = uMVPMatrix * aPosition;\n" +
|
|
35
|
+
" vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
|
|
36
|
+
"}\n";
|
|
37
|
+
|
|
38
|
+
private static final String FRAGMENT_SHADER =
|
|
39
|
+
"#extension GL_OES_EGL_image_external : require\n" +
|
|
40
|
+
"precision mediump float;\n" +
|
|
41
|
+
"varying vec2 vTextureCoord;\n" +
|
|
42
|
+
"uniform samplerExternalOES sTexture;\n" +
|
|
43
|
+
"void main() {\n" +
|
|
44
|
+
" gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
|
|
45
|
+
"}\n";
|
|
46
|
+
|
|
47
|
+
private float[] mMVPMatrix = new float[16];
|
|
48
|
+
private float[] mSTMatrix = new float[16];
|
|
49
|
+
private int mProgram;
|
|
50
|
+
private int mTextureID = -1234567;
|
|
51
|
+
private int muMVPMatrixHandle;
|
|
52
|
+
private int muSTMatrixHandle;
|
|
53
|
+
private int maPositionHandle;
|
|
54
|
+
private int maTextureHandle;
|
|
55
|
+
private int rotationAngle = 0;
|
|
56
|
+
|
|
57
|
+
public TextureRenderer() {
|
|
58
|
+
|
|
59
|
+
mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
|
|
60
|
+
mTriangleVertices.put(mTriangleVerticesData).position(0);
|
|
61
|
+
Matrix.setIdentityM(mSTMatrix, 0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public int getTextureId() {
|
|
65
|
+
return mTextureID;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public void drawFrame(SurfaceTexture st) {
|
|
69
|
+
checkGlError("onDrawFrame start");
|
|
70
|
+
st.getTransformMatrix(mSTMatrix);
|
|
71
|
+
|
|
72
|
+
// if (invert) {
|
|
73
|
+
// mSTMatrix[5] = -mSTMatrix[5];
|
|
74
|
+
// mSTMatrix[13] = 1.0f - mSTMatrix[13];
|
|
75
|
+
// }
|
|
76
|
+
|
|
77
|
+
GLES20.glUseProgram(mProgram);
|
|
78
|
+
checkGlError("glUseProgram");
|
|
79
|
+
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
|
|
80
|
+
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
|
|
81
|
+
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
|
|
82
|
+
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
|
|
83
|
+
checkGlError("glVertexAttribPointer maPosition");
|
|
84
|
+
GLES20.glEnableVertexAttribArray(maPositionHandle);
|
|
85
|
+
checkGlError("glEnableVertexAttribArray maPositionHandle");
|
|
86
|
+
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
|
|
87
|
+
GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
|
|
88
|
+
checkGlError("glVertexAttribPointer maTextureHandle");
|
|
89
|
+
GLES20.glEnableVertexAttribArray(maTextureHandle);
|
|
90
|
+
checkGlError("glEnableVertexAttribArray maTextureHandle");
|
|
91
|
+
GLES20.glUniformMatrix4fv(muSTMatrixHandle, 1, false, mSTMatrix, 0);
|
|
92
|
+
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
|
|
93
|
+
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
|
|
94
|
+
checkGlError("glDrawArrays");
|
|
95
|
+
GLES20.glFinish();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public void surfaceCreated() {
|
|
99
|
+
mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
|
|
100
|
+
if (mProgram == 0) {
|
|
101
|
+
throw new RuntimeException("failed creating program");
|
|
102
|
+
}
|
|
103
|
+
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
|
|
104
|
+
checkGlError("glGetAttribLocation aPosition");
|
|
105
|
+
if (maPositionHandle == -1) {
|
|
106
|
+
throw new RuntimeException("Could not get attrib location for aPosition");
|
|
107
|
+
}
|
|
108
|
+
maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
|
|
109
|
+
checkGlError("glGetAttribLocation aTextureCoord");
|
|
110
|
+
if (maTextureHandle == -1) {
|
|
111
|
+
throw new RuntimeException("Could not get attrib location for aTextureCoord");
|
|
112
|
+
}
|
|
113
|
+
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
|
|
114
|
+
checkGlError("glGetUniformLocation uMVPMatrix");
|
|
115
|
+
if (muMVPMatrixHandle == -1) {
|
|
116
|
+
throw new RuntimeException("Could not get attrib location for uMVPMatrix");
|
|
117
|
+
}
|
|
118
|
+
muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
|
|
119
|
+
checkGlError("glGetUniformLocation uSTMatrix");
|
|
120
|
+
if (muSTMatrixHandle == -1) {
|
|
121
|
+
throw new RuntimeException("Could not get attrib location for uSTMatrix");
|
|
122
|
+
}
|
|
123
|
+
int[] textures = new int[1];
|
|
124
|
+
GLES20.glGenTextures(1, textures, 0);
|
|
125
|
+
mTextureID = textures[0];
|
|
126
|
+
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
|
|
127
|
+
checkGlError("glBindTexture mTextureID");
|
|
128
|
+
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
|
|
129
|
+
GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
|
|
130
|
+
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
|
|
131
|
+
GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
|
|
132
|
+
checkGlError("glTexParameter");
|
|
133
|
+
|
|
134
|
+
Matrix.setIdentityM(mMVPMatrix, 0);
|
|
135
|
+
if (rotationAngle != 0) {
|
|
136
|
+
Matrix.rotateM(mMVPMatrix, 0, rotationAngle, 0, 0, 1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public void changeFragmentShader(String fragmentShader) {
|
|
141
|
+
GLES20.glDeleteProgram(mProgram);
|
|
142
|
+
mProgram = createProgram(VERTEX_SHADER, fragmentShader);
|
|
143
|
+
if (mProgram == 0) {
|
|
144
|
+
throw new RuntimeException("failed creating program");
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private int loadShader(int shaderType, String source) {
|
|
149
|
+
int shader = GLES20.glCreateShader(shaderType);
|
|
150
|
+
checkGlError("glCreateShader type=" + shaderType);
|
|
151
|
+
GLES20.glShaderSource(shader, source);
|
|
152
|
+
GLES20.glCompileShader(shader);
|
|
153
|
+
int[] compiled = new int[1];
|
|
154
|
+
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
|
|
155
|
+
if (compiled[0] == 0) {
|
|
156
|
+
GLES20.glDeleteShader(shader);
|
|
157
|
+
shader = 0;
|
|
158
|
+
}
|
|
159
|
+
return shader;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private int createProgram(String vertexSource, String fragmentSource) {
|
|
163
|
+
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
|
|
164
|
+
if (vertexShader == 0) {
|
|
165
|
+
return 0;
|
|
166
|
+
}
|
|
167
|
+
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
|
|
168
|
+
if (pixelShader == 0) {
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
int program = GLES20.glCreateProgram();
|
|
172
|
+
checkGlError("glCreateProgram");
|
|
173
|
+
if (program == 0) {
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
GLES20.glAttachShader(program, vertexShader);
|
|
177
|
+
checkGlError("glAttachShader");
|
|
178
|
+
GLES20.glAttachShader(program, pixelShader);
|
|
179
|
+
checkGlError("glAttachShader");
|
|
180
|
+
GLES20.glLinkProgram(program);
|
|
181
|
+
int[] linkStatus = new int[1];
|
|
182
|
+
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
|
|
183
|
+
if (linkStatus[0] != GLES20.GL_TRUE) {
|
|
184
|
+
GLES20.glDeleteProgram(program);
|
|
185
|
+
program = 0;
|
|
186
|
+
}
|
|
187
|
+
return program;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
public void checkGlError(String op) {
|
|
191
|
+
int error;
|
|
192
|
+
if ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
|
|
193
|
+
throw new RuntimeException(op + ": glError " + error);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./lib/commonjs/expo-plugin/compressor');
|
package/ios/Compressor.m
CHANGED
|
@@ -34,6 +34,7 @@ class VideoCompressor: RCTEventEmitter, URLSessionTaskDelegate {
|
|
|
34
34
|
var hasListener: Bool=false
|
|
35
35
|
var uploadResolvers: [String: RCTPromiseResolveBlock] = [:]
|
|
36
36
|
var uploadRejectors: [String: RCTPromiseRejectBlock] = [:]
|
|
37
|
+
var compressorExports: [String: NextLevelSessionExporter] = [:]
|
|
37
38
|
let videoCompressionThreshold:Int=7
|
|
38
39
|
var videoCompressionCounter:Int=0
|
|
39
40
|
|
|
@@ -83,6 +84,11 @@ class VideoCompressor: RCTEventEmitter, URLSessionTaskDelegate {
|
|
|
83
84
|
})
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
@objc(cancelCompression:)
|
|
88
|
+
func cancelCompression(uuid: String) -> Void {
|
|
89
|
+
compressorExports[uuid]?.cancelExport()
|
|
90
|
+
}
|
|
91
|
+
|
|
86
92
|
func makeValidUri(filePath: String) -> String {
|
|
87
93
|
let fileWithUrl = URL(fileURLWithPath: filePath)
|
|
88
94
|
let absoluteUrl = fileWithUrl.deletingLastPathComponent()
|
|
@@ -219,7 +225,7 @@ func makeValidUri(filePath: String) -> String {
|
|
|
219
225
|
}
|
|
220
226
|
else
|
|
221
227
|
{
|
|
222
|
-
manualCompressionHelper(url: url,
|
|
228
|
+
manualCompressionHelper(url: url, options:options) { progress in
|
|
223
229
|
onProgress(progress)
|
|
224
230
|
} onCompletion: { outputURL in
|
|
225
231
|
onCompletion(outputURL)
|
|
@@ -245,9 +251,9 @@ func makeValidUri(filePath: String) -> String {
|
|
|
245
251
|
let compressFactor:Float = 0.8
|
|
246
252
|
let minCompressFactor:Float = 0.8
|
|
247
253
|
let maxBitrate:Int = 1669000
|
|
248
|
-
|
|
249
|
-
var remeasuredBitrate:Int = originalBitrate /
|
|
250
|
-
remeasuredBitrate = remeasuredBitrate*
|
|
254
|
+
let minValue:Float=min(Float(originalHeight)/Float(height),Float(originalWidth)/Float(width))
|
|
255
|
+
var remeasuredBitrate:Int = Int(Float(originalBitrate) / minValue)
|
|
256
|
+
remeasuredBitrate = Int(Float(remeasuredBitrate)*compressFactor)
|
|
251
257
|
let minBitrate:Int = self.getVideoBitrateWithFactor(f: minCompressFactor) / (1280 * 720 / (width * height))
|
|
252
258
|
if (originalBitrate < minBitrate) {
|
|
253
259
|
return remeasuredBitrate;
|
|
@@ -263,6 +269,7 @@ func makeValidUri(filePath: String) -> String {
|
|
|
263
269
|
|
|
264
270
|
func autoCompressionHelper(url: URL, options: [String: Any], onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
|
|
265
271
|
let maxSize:Float = options["maxSize"] as! Float;
|
|
272
|
+
let uuid:String = options["uuid"] as! String
|
|
266
273
|
|
|
267
274
|
let asset = AVAsset(url: url)
|
|
268
275
|
guard asset.tracks.count >= 1 else {
|
|
@@ -286,8 +293,8 @@ func makeValidUri(filePath: String) -> String {
|
|
|
286
293
|
originalBitrate: Int(bitrate),
|
|
287
294
|
height: Int(resultHeight), width: Int(resultWidth)
|
|
288
295
|
);
|
|
289
|
-
|
|
290
|
-
exportVideoHelper(url: url, asset: asset, bitRate: videoBitRate, resultWidth: resultWidth, resultHeight: resultHeight) { progress in
|
|
296
|
+
|
|
297
|
+
exportVideoHelper(url: url, asset: asset, bitRate: videoBitRate, resultWidth: resultWidth, resultHeight: resultHeight,uuid: uuid) { progress in
|
|
291
298
|
onProgress(progress)
|
|
292
299
|
} onCompletion: { outputURL in
|
|
293
300
|
onCompletion(outputURL)
|
|
@@ -296,9 +303,9 @@ func makeValidUri(filePath: String) -> String {
|
|
|
296
303
|
}
|
|
297
304
|
}
|
|
298
305
|
|
|
299
|
-
func manualCompressionHelper(url: URL,
|
|
300
|
-
|
|
301
|
-
var
|
|
306
|
+
func manualCompressionHelper(url: URL, options: [String: Any], onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
|
|
307
|
+
let uuid:String = options["uuid"] as! String
|
|
308
|
+
var bitRate=options["bitrate"] as! Float?;
|
|
302
309
|
let asset = AVAsset(url: url)
|
|
303
310
|
guard asset.tracks.count >= 1 else {
|
|
304
311
|
let error = CompressionError(message: "Invalid video URL, no track found")
|
|
@@ -321,12 +328,12 @@ func makeValidUri(filePath: String) -> String {
|
|
|
321
328
|
}
|
|
322
329
|
else
|
|
323
330
|
{
|
|
324
|
-
|
|
331
|
+
bitRate=bitRate ?? Float(abs(track.estimatedDataRate))*0.8
|
|
325
332
|
}
|
|
326
333
|
|
|
327
|
-
let videoBitRate =
|
|
334
|
+
let videoBitRate = bitRate ?? height*width*1.5
|
|
328
335
|
|
|
329
|
-
exportVideoHelper(url: url, asset: asset, bitRate: Int(videoBitRate), resultWidth: width, resultHeight: height) { progress in
|
|
336
|
+
exportVideoHelper(url: url, asset: asset, bitRate: Int(videoBitRate), resultWidth: width, resultHeight: height,uuid: uuid) { progress in
|
|
330
337
|
onProgress(progress)
|
|
331
338
|
} onCompletion: { outputURL in
|
|
332
339
|
onCompletion(outputURL)
|
|
@@ -335,7 +342,7 @@ func makeValidUri(filePath: String) -> String {
|
|
|
335
342
|
}
|
|
336
343
|
}
|
|
337
344
|
|
|
338
|
-
func exportVideoHelper(url: URL,asset: AVAsset, bitRate: Int,resultWidth:Float,resultHeight:Float, onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
|
|
345
|
+
func exportVideoHelper(url: URL,asset: AVAsset, bitRate: Int,resultWidth:Float,resultHeight:Float,uuid:String, onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
|
|
339
346
|
var tmpURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
340
347
|
.appendingPathComponent(ProcessInfo().globallyUniqueString)
|
|
341
348
|
.appendingPathExtension("mp4")
|
|
@@ -364,7 +371,7 @@ func makeValidUri(filePath: String) -> String {
|
|
|
364
371
|
AVSampleRateKey: NSNumber(value: Float(44100))
|
|
365
372
|
]
|
|
366
373
|
|
|
367
|
-
|
|
374
|
+
compressorExports[uuid] = exporter
|
|
368
375
|
exporter.export(progressHandler: { (progress) in
|
|
369
376
|
let _progress:Float=progress*100;
|
|
370
377
|
if(Int(_progress)==self.videoCompressionCounter)
|
|
@@ -406,4 +413,6 @@ func makeValidUri(filePath: String) -> String {
|
|
|
406
413
|
let track = asset.tracks[videoTrackIndex];
|
|
407
414
|
return track;
|
|
408
415
|
}
|
|
416
|
+
|
|
417
|
+
|
|
409
418
|
}
|
|
@@ -3,19 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.default = exports.backgroundUpload = void 0;
|
|
6
|
+
exports.default = exports.cancelCompression = exports.backgroundUpload = void 0;
|
|
7
7
|
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
|
|
10
|
-
require("
|
|
11
|
-
|
|
12
|
-
var _uuid = require("uuid");
|
|
10
|
+
var _utils = require("../utils");
|
|
13
11
|
|
|
14
12
|
const VideoCompressEventEmitter = new _reactNative.NativeEventEmitter(_reactNative.NativeModules.VideoCompressor);
|
|
15
13
|
const NativeVideoCompressor = _reactNative.NativeModules.VideoCompressor;
|
|
16
14
|
|
|
17
15
|
const backgroundUpload = async (url, fileUrl, options, onProgress) => {
|
|
18
|
-
const uuid = (0,
|
|
16
|
+
const uuid = (0, _utils.uuidv4)();
|
|
19
17
|
let subscription;
|
|
20
18
|
|
|
21
19
|
try {
|
|
@@ -47,9 +45,15 @@ const backgroundUpload = async (url, fileUrl, options, onProgress) => {
|
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
exports.backgroundUpload = backgroundUpload;
|
|
48
|
+
|
|
49
|
+
const cancelCompression = cancellationId => {
|
|
50
|
+
return NativeVideoCompressor.cancelCompression(cancellationId);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
exports.cancelCompression = cancelCompression;
|
|
50
54
|
const Video = {
|
|
51
55
|
compress: async (fileUrl, options, onProgress) => {
|
|
52
|
-
const uuid = (0,
|
|
56
|
+
const uuid = (0, _utils.uuidv4)();
|
|
53
57
|
let subscription;
|
|
54
58
|
|
|
55
59
|
try {
|
|
@@ -82,6 +86,10 @@ const Video = {
|
|
|
82
86
|
modifiedOptions.minimumFileSizeForCompress = options === null || options === void 0 ? void 0 : options.minimumFileSizeForCompress;
|
|
83
87
|
}
|
|
84
88
|
|
|
89
|
+
if (options !== null && options !== void 0 && options.getCancellationId) {
|
|
90
|
+
options === null || options === void 0 ? void 0 : options.getCancellationId(uuid);
|
|
91
|
+
}
|
|
92
|
+
|
|
85
93
|
const result = await NativeVideoCompressor.compress(fileUrl, modifiedOptions);
|
|
86
94
|
return result;
|
|
87
95
|
} finally {
|
|
@@ -92,6 +100,7 @@ const Video = {
|
|
|
92
100
|
}
|
|
93
101
|
},
|
|
94
102
|
backgroundUpload,
|
|
103
|
+
cancelCompression,
|
|
95
104
|
|
|
96
105
|
activateBackgroundTask(onExpired) {
|
|
97
106
|
if (onExpired) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["index.tsx"],"names":["VideoCompressEventEmitter","NativeEventEmitter","NativeModules","VideoCompressor","NativeVideoCompressor","backgroundUpload","url","fileUrl","options","onProgress","uuid","subscription","addListener","event","data","written","total","Platform","OS","includes","replace","result","upload","method","httpMethod","headers","remove","Video","compress","progress","modifiedOptions","bitrate","compressionMethod","maxSize","minimumFileSizeForCompress","activateBackgroundTask","onExpired","deactivateBackgroundTask","removeAllListeners"],"mappings":";;;;;;;AAAA;;AAMA;;
|
|
1
|
+
{"version":3,"sources":["index.tsx"],"names":["VideoCompressEventEmitter","NativeEventEmitter","NativeModules","VideoCompressor","NativeVideoCompressor","backgroundUpload","url","fileUrl","options","onProgress","uuid","subscription","addListener","event","data","written","total","Platform","OS","includes","replace","result","upload","method","httpMethod","headers","remove","cancelCompression","cancellationId","Video","compress","progress","modifiedOptions","bitrate","compressionMethod","maxSize","minimumFileSizeForCompress","getCancellationId","activateBackgroundTask","onExpired","deactivateBackgroundTask","removeAllListeners"],"mappings":"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","sourcesContent":["import {\n NativeModules,\n NativeEventEmitter,\n Platform,\n NativeEventSubscription,\n} from 'react-native';\nimport { uuidv4 } from '../utils';\n\nexport declare enum FileSystemUploadType {\n BINARY_CONTENT = 0,\n MULTIPART = 1,\n}\n\nexport declare type FileSystemAcceptedUploadHttpMethod =\n | 'POST'\n | 'PUT'\n | 'PATCH';\nexport type compressionMethod = 'auto' | 'manual';\ntype videoCompresssionType = {\n bitrate?: number;\n maxSize?: number;\n compressionMethod?: compressionMethod;\n minimumFileSizeForCompress?: number;\n getCancellationId?: (cancellationId: string) => void;\n};\n\nexport declare enum FileSystemSessionType {\n BACKGROUND = 0,\n FOREGROUND = 1,\n}\n\nexport declare type HTTPResponse = {\n status: number;\n headers: Record<string, string>;\n body: string;\n};\n\nexport declare type FileSystemUploadOptions = (\n | {\n uploadType?: FileSystemUploadType.BINARY_CONTENT;\n }\n | {\n uploadType: FileSystemUploadType.MULTIPART;\n fieldName?: string;\n mimeType?: string;\n parameters?: Record<string, string>;\n }\n) & {\n headers?: Record<string, string>;\n httpMethod?: FileSystemAcceptedUploadHttpMethod;\n sessionType?: FileSystemSessionType;\n};\n\nexport type VideoCompressorType = {\n compress(\n fileUrl: string,\n options?: videoCompresssionType,\n onProgress?: (progress: number) => void\n ): Promise<string>;\n cancelCompression(cancellationId: string): void;\n backgroundUpload(\n url: string,\n fileUrl: string,\n options: FileSystemUploadOptions,\n onProgress?: (writtem: number, total: number) => void\n ): Promise<any>;\n activateBackgroundTask(onExpired?: (data: any) => void): Promise<any>;\n deactivateBackgroundTask(): Promise<any>;\n};\n\nconst VideoCompressEventEmitter = new NativeEventEmitter(\n NativeModules.VideoCompressor\n);\n\nconst NativeVideoCompressor = NativeModules.VideoCompressor;\n\nexport const backgroundUpload = async (\n url: string,\n fileUrl: string,\n options: FileSystemUploadOptions,\n onProgress?: (writtem: number, total: number) => void\n): Promise<any> => {\n const uuid = uuidv4();\n let subscription: NativeEventSubscription;\n try {\n if (onProgress) {\n subscription = VideoCompressEventEmitter.addListener(\n 'VideoCompressorProgress',\n (event: any) => {\n if (event.uuid === uuid) {\n onProgress(event.data.written, event.data.total);\n }\n }\n );\n }\n if (Platform.OS === 'android' && fileUrl.includes('file://')) {\n fileUrl = fileUrl.replace('file://', '');\n }\n const result = await NativeVideoCompressor.upload(fileUrl, {\n uuid,\n method: options.httpMethod,\n headers: options.headers,\n url,\n });\n return result;\n } finally {\n // @ts-ignore\n if (subscription) {\n subscription.remove();\n }\n }\n};\n\nexport const cancelCompression = (cancellationId: string) => {\n return NativeVideoCompressor.cancelCompression(cancellationId);\n};\n\nconst Video: VideoCompressorType = {\n compress: async (\n fileUrl: string,\n options?: videoCompresssionType,\n onProgress?: (progress: number) => void\n ) => {\n const uuid = uuidv4();\n let subscription: NativeEventSubscription;\n try {\n if (onProgress) {\n subscription = VideoCompressEventEmitter.addListener(\n 'videoCompressProgress',\n (event: any) => {\n if (event.uuid === uuid) {\n onProgress(event.data.progress);\n }\n }\n );\n }\n const modifiedOptions: {\n uuid: string;\n bitrate?: number;\n compressionMethod?: compressionMethod;\n maxSize?: number;\n minimumFileSizeForCompress?: number;\n } = { uuid };\n if (options?.bitrate) modifiedOptions.bitrate = options?.bitrate;\n if (options?.compressionMethod) {\n modifiedOptions.compressionMethod = options?.compressionMethod;\n } else {\n modifiedOptions.compressionMethod = 'manual';\n }\n if (options?.maxSize) {\n modifiedOptions.maxSize = options?.maxSize;\n } else {\n modifiedOptions.maxSize = 640;\n }\n if (options?.minimumFileSizeForCompress) {\n modifiedOptions.minimumFileSizeForCompress =\n options?.minimumFileSizeForCompress;\n }\n if (options?.getCancellationId) {\n options?.getCancellationId(uuid);\n }\n const result = await NativeVideoCompressor.compress(\n fileUrl,\n modifiedOptions\n );\n return result;\n } finally {\n // @ts-ignore\n if (subscription) {\n subscription.remove();\n }\n }\n },\n backgroundUpload,\n cancelCompression,\n activateBackgroundTask(onExpired?) {\n if (onExpired) {\n const subscription: NativeEventSubscription =\n VideoCompressEventEmitter.addListener(\n 'backgroundTaskExpired',\n (event: any) => {\n onExpired(event);\n if (subscription) {\n subscription.remove();\n }\n }\n );\n }\n return NativeVideoCompressor.activateBackgroundTask({});\n },\n deactivateBackgroundTask() {\n VideoCompressEventEmitter.removeAllListeners('backgroundTaskExpired');\n return NativeVideoCompressor.deactivateBackgroundTask({});\n },\n} as VideoCompressorType;\n\nexport default Video;\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _configPlugins = require("@expo/config-plugins");
|
|
9
|
+
|
|
10
|
+
const pkg = require('../../../package.json');
|
|
11
|
+
|
|
12
|
+
const withCompressor = config => config;
|
|
13
|
+
|
|
14
|
+
var _default = (0, _configPlugins.createRunOncePlugin)(withCompressor, pkg.name, pkg.version);
|
|
15
|
+
|
|
16
|
+
exports.default = _default;
|
|
17
|
+
//# sourceMappingURL=compressor.js.map
|