whisper.rn 0.3.3 → 0.3.5
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 +15 -2
- package/android/build.gradle +12 -2
- package/android/src/main/CMakeLists.txt +55 -0
- package/android/src/main/java/com/rnwhisper/RNWhisper.java +268 -0
- package/android/src/newarch/java/com/rnwhisper/RNWhisperModule.java +10 -228
- package/android/src/oldarch/java/com/rnwhisper/RNWhisperModule.java +16 -222
- package/cpp/README.md +4 -0
- package/cpp/coreml/whisper-encoder.mm +4 -2
- package/cpp/ggml.c +9 -1
- package/cpp/ggml.h +1 -0
- package/cpp/whisper.cpp +151 -99
- package/cpp/whisper.h +2 -1
- package/ios/RNWhisperContext.mm +2 -2
- package/lib/commonjs/NativeRNWhisper.js.map +1 -1
- package/lib/commonjs/index.js +5 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/NativeRNWhisper.js +3 -0
- package/lib/module/NativeRNWhisper.js.map +1 -1
- package/lib/module/index.js +5 -2
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/NativeRNWhisper.d.ts +1 -3
- package/lib/typescript/NativeRNWhisper.d.ts.map +1 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativeRNWhisper.ts +2 -3
- package/src/index.ts +4 -3
- package/android/src/main/jni/whisper/Android.mk +0 -26
- package/android/src/main/jni/whisper/Application.mk +0 -1
- package/android/src/main/jni/whisper/Whisper.mk +0 -22
- /package/android/src/main/{jni/whisper/jni.cpp → jni.cpp} +0 -0
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
package com.rnwhisper;
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.NonNull;
|
|
4
|
-
import android.util.Log;
|
|
5
|
-
import android.os.Build;
|
|
6
|
-
import android.os.Handler;
|
|
7
|
-
import android.os.AsyncTask;
|
|
8
|
-
import android.media.AudioRecord;
|
|
9
4
|
|
|
10
5
|
import com.facebook.react.bridge.Promise;
|
|
11
6
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
12
7
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
13
8
|
import com.facebook.react.bridge.ReactMethod;
|
|
14
|
-
import com.facebook.react.bridge.LifecycleEventListener;
|
|
15
9
|
import com.facebook.react.bridge.ReadableMap;
|
|
16
|
-
import com.facebook.react.bridge.WritableMap;
|
|
17
10
|
import com.facebook.react.module.annotations.ReactModule;
|
|
18
11
|
|
|
19
12
|
import java.util.HashMap;
|
|
@@ -23,17 +16,14 @@ import java.io.FileInputStream;
|
|
|
23
16
|
import java.io.PushbackInputStream;
|
|
24
17
|
|
|
25
18
|
@ReactModule(name = RNWhisperModule.NAME)
|
|
26
|
-
public class RNWhisperModule extends ReactContextBaseJavaModule
|
|
19
|
+
public class RNWhisperModule extends ReactContextBaseJavaModule {
|
|
27
20
|
public static final String NAME = "RNWhisper";
|
|
28
21
|
|
|
29
|
-
private
|
|
30
|
-
private Downloader downloader;
|
|
22
|
+
private RNWhisper rnwhisper;
|
|
31
23
|
|
|
32
24
|
public RNWhisperModule(ReactApplicationContext reactContext) {
|
|
33
25
|
super(reactContext);
|
|
34
|
-
reactContext
|
|
35
|
-
this.reactContext = reactContext;
|
|
36
|
-
this.downloader = new Downloader(reactContext);
|
|
26
|
+
rnwhisper = new RNWhisper(reactContext);
|
|
37
27
|
}
|
|
38
28
|
|
|
39
29
|
@Override
|
|
@@ -42,234 +32,38 @@ public class RNWhisperModule extends ReactContextBaseJavaModule implements Lifec
|
|
|
42
32
|
return NAME;
|
|
43
33
|
}
|
|
44
34
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
int identifier = reactContext.getResources().getIdentifier(
|
|
49
|
-
filePath,
|
|
50
|
-
"drawable",
|
|
51
|
-
reactContext.getPackageName()
|
|
52
|
-
);
|
|
53
|
-
if (identifier == 0) {
|
|
54
|
-
identifier = reactContext.getResources().getIdentifier(
|
|
55
|
-
filePath,
|
|
56
|
-
"raw",
|
|
57
|
-
reactContext.getPackageName()
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
return identifier;
|
|
35
|
+
@Override
|
|
36
|
+
public HashMap<String, Object> getConstants() {
|
|
37
|
+
return rnwhisper.getTypedExportedConstants();
|
|
61
38
|
}
|
|
62
39
|
|
|
63
40
|
@ReactMethod
|
|
64
41
|
public void initContext(final ReadableMap options, final Promise promise) {
|
|
65
|
-
|
|
66
|
-
private Exception exception;
|
|
67
|
-
|
|
68
|
-
@Override
|
|
69
|
-
protected Integer doInBackground(Void... voids) {
|
|
70
|
-
try {
|
|
71
|
-
String modelPath = options.getString("filePath");
|
|
72
|
-
boolean isBundleAsset = options.getBoolean("isBundleAsset");
|
|
73
|
-
|
|
74
|
-
String modelFilePath = modelPath;
|
|
75
|
-
if (!isBundleAsset && (modelPath.startsWith("http://") || modelPath.startsWith("https://"))) {
|
|
76
|
-
modelFilePath = downloader.downloadFile(modelPath);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
long context;
|
|
80
|
-
int resId = getResourceIdentifier(modelFilePath);
|
|
81
|
-
if (resId > 0) {
|
|
82
|
-
context = WhisperContext.initContextWithInputStream(
|
|
83
|
-
new PushbackInputStream(reactContext.getResources().openRawResource(resId))
|
|
84
|
-
);
|
|
85
|
-
} else if (isBundleAsset) {
|
|
86
|
-
context = WhisperContext.initContextWithAsset(reactContext.getAssets(), modelFilePath);
|
|
87
|
-
} else {
|
|
88
|
-
context = WhisperContext.initContext(modelFilePath);
|
|
89
|
-
}
|
|
90
|
-
if (context == 0) {
|
|
91
|
-
throw new Exception("Failed to initialize context");
|
|
92
|
-
}
|
|
93
|
-
int id = Math.abs(new Random().nextInt());
|
|
94
|
-
WhisperContext whisperContext = new WhisperContext(id, reactContext, context);
|
|
95
|
-
contexts.put(id, whisperContext);
|
|
96
|
-
return id;
|
|
97
|
-
} catch (Exception e) {
|
|
98
|
-
exception = e;
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
@Override
|
|
104
|
-
protected void onPostExecute(Integer id) {
|
|
105
|
-
if (exception != null) {
|
|
106
|
-
promise.reject(exception);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
promise.resolve(id);
|
|
110
|
-
}
|
|
111
|
-
}.execute();
|
|
42
|
+
rnwhisper.initContext(options, promise);
|
|
112
43
|
}
|
|
113
44
|
|
|
114
45
|
@ReactMethod
|
|
115
|
-
public void transcribeFile(
|
|
116
|
-
|
|
117
|
-
if (context == null) {
|
|
118
|
-
promise.reject("Context not found");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (context.isCapturing()) {
|
|
122
|
-
promise.reject("The context is in realtime transcribe mode");
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (context.isTranscribing()) {
|
|
126
|
-
promise.reject("Context is already transcribing");
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
new AsyncTask<Void, Void, WritableMap>() {
|
|
130
|
-
private Exception exception;
|
|
131
|
-
|
|
132
|
-
@Override
|
|
133
|
-
protected WritableMap doInBackground(Void... voids) {
|
|
134
|
-
try {
|
|
135
|
-
String waveFilePath = filePath;
|
|
136
|
-
|
|
137
|
-
if (filePath.startsWith("http://") || filePath.startsWith("https://")) {
|
|
138
|
-
waveFilePath = downloader.downloadFile(filePath);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
int resId = getResourceIdentifier(waveFilePath);
|
|
142
|
-
if (resId > 0) {
|
|
143
|
-
return context.transcribeInputStream(
|
|
144
|
-
(int) jobId,
|
|
145
|
-
reactContext.getResources().openRawResource(resId),
|
|
146
|
-
options
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return context.transcribeInputStream(
|
|
151
|
-
(int) jobId,
|
|
152
|
-
new FileInputStream(new File(waveFilePath)),
|
|
153
|
-
options
|
|
154
|
-
);
|
|
155
|
-
} catch (Exception e) {
|
|
156
|
-
exception = e;
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
@Override
|
|
162
|
-
protected void onPostExecute(WritableMap data) {
|
|
163
|
-
if (exception != null) {
|
|
164
|
-
promise.reject(exception);
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
promise.resolve(data);
|
|
168
|
-
}
|
|
169
|
-
}.execute();
|
|
46
|
+
public void transcribeFile(double id, double jobId, String filePath, ReadableMap options, Promise promise) {
|
|
47
|
+
rnwhisper.transcribeFile(id, jobId, filePath, options, promise);
|
|
170
48
|
}
|
|
171
49
|
|
|
172
50
|
@ReactMethod
|
|
173
|
-
public void startRealtimeTranscribe(
|
|
174
|
-
|
|
175
|
-
if (context == null) {
|
|
176
|
-
promise.reject("Context not found");
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
if (context.isCapturing()) {
|
|
180
|
-
promise.reject("Context is already in capturing");
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
int state = context.startRealtimeTranscribe(jobId, options);
|
|
184
|
-
if (state == AudioRecord.STATE_INITIALIZED) {
|
|
185
|
-
promise.resolve(null);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
promise.reject("Failed to start realtime transcribe. State: " + state);
|
|
51
|
+
public void startRealtimeTranscribe(double id, double jobId, ReadableMap options, Promise promise) {
|
|
52
|
+
rnwhisper.startRealtimeTranscribe(id, jobId, options, promise);
|
|
189
53
|
}
|
|
190
54
|
|
|
191
55
|
@ReactMethod
|
|
192
|
-
public void abortTranscribe(
|
|
193
|
-
|
|
194
|
-
if (context == null) {
|
|
195
|
-
promise.reject("Context not found");
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
context.stopTranscribe(jobId);
|
|
56
|
+
public void abortTranscribe(double contextId, double jobId, Promise promise) {
|
|
57
|
+
rnwhisper.abortTranscribe(contextId, jobId, promise);
|
|
199
58
|
}
|
|
200
59
|
|
|
201
60
|
@ReactMethod
|
|
202
|
-
public void releaseContext(
|
|
203
|
-
|
|
204
|
-
private Exception exception;
|
|
205
|
-
|
|
206
|
-
@Override
|
|
207
|
-
protected Void doInBackground(Void... voids) {
|
|
208
|
-
try {
|
|
209
|
-
WhisperContext context = contexts.get(id);
|
|
210
|
-
if (context == null) {
|
|
211
|
-
throw new Exception("Context " + id + " not found");
|
|
212
|
-
}
|
|
213
|
-
context.release();
|
|
214
|
-
contexts.remove(id);
|
|
215
|
-
} catch (Exception e) {
|
|
216
|
-
exception = e;
|
|
217
|
-
}
|
|
218
|
-
return null;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
@Override
|
|
222
|
-
protected void onPostExecute(Void result) {
|
|
223
|
-
if (exception != null) {
|
|
224
|
-
promise.reject(exception);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
promise.resolve(null);
|
|
228
|
-
}
|
|
229
|
-
}.execute();
|
|
61
|
+
public void releaseContext(double id, Promise promise) {
|
|
62
|
+
rnwhisper.releaseContext(id, promise);
|
|
230
63
|
}
|
|
231
64
|
|
|
232
65
|
@ReactMethod
|
|
233
66
|
public void releaseAllContexts(Promise promise) {
|
|
234
|
-
|
|
235
|
-
private Exception exception;
|
|
236
|
-
|
|
237
|
-
@Override
|
|
238
|
-
protected Void doInBackground(Void... voids) {
|
|
239
|
-
try {
|
|
240
|
-
onHostDestroy();
|
|
241
|
-
} catch (Exception e) {
|
|
242
|
-
exception = e;
|
|
243
|
-
}
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
@Override
|
|
248
|
-
protected void onPostExecute(Void result) {
|
|
249
|
-
if (exception != null) {
|
|
250
|
-
promise.reject(exception);
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
promise.resolve(null);
|
|
254
|
-
}
|
|
255
|
-
}.execute();
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
@Override
|
|
259
|
-
public void onHostResume() {
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
@Override
|
|
263
|
-
public void onHostPause() {
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
@Override
|
|
267
|
-
public void onHostDestroy() {
|
|
268
|
-
WhisperContext.abortAllTranscribe();
|
|
269
|
-
for (WhisperContext context : contexts.values()) {
|
|
270
|
-
context.release();
|
|
271
|
-
}
|
|
272
|
-
contexts.clear();
|
|
273
|
-
downloader.clearCache();
|
|
67
|
+
rnwhisper.releaseAllContexts(promise);
|
|
274
68
|
}
|
|
275
69
|
}
|
package/cpp/README.md
ADDED
|
@@ -53,9 +53,11 @@ void whisper_coreml_encode(
|
|
|
53
53
|
error: nil
|
|
54
54
|
];
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
@autoreleasepool {
|
|
57
|
+
whisper_encoder_implOutput * outCoreML = [(__bridge id) ctx->data predictionFromLogmel_data:inMultiArray error:nil];
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
memcpy(out, outCoreML.output.dataPointer, outCoreML.output.count * sizeof(float));
|
|
60
|
+
}
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
#if __cplusplus
|
package/cpp/ggml.c
CHANGED
|
@@ -292,7 +292,7 @@ typedef double wsp_ggml_float;
|
|
|
292
292
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
293
293
|
#include <intrin.h>
|
|
294
294
|
#else
|
|
295
|
-
#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__) || defined(__SSSE3__)
|
|
295
|
+
#if defined(__AVX__) || defined(__AVX2__) || defined(__AVX512F__) || defined(__SSSE3__) || defined(__SSE3__)
|
|
296
296
|
#include <immintrin.h>
|
|
297
297
|
#endif
|
|
298
298
|
#endif
|
|
@@ -18721,6 +18721,14 @@ int wsp_ggml_cpu_has_sse3(void) {
|
|
|
18721
18721
|
#endif
|
|
18722
18722
|
}
|
|
18723
18723
|
|
|
18724
|
+
int wsp_ggml_cpu_has_ssse3(void) {
|
|
18725
|
+
#if defined(__SSSE3__)
|
|
18726
|
+
return 1;
|
|
18727
|
+
#else
|
|
18728
|
+
return 0;
|
|
18729
|
+
#endif
|
|
18730
|
+
}
|
|
18731
|
+
|
|
18724
18732
|
int wsp_ggml_cpu_has_vsx(void) {
|
|
18725
18733
|
#if defined(__POWER9_VECTOR__)
|
|
18726
18734
|
return 1;
|
package/cpp/ggml.h
CHANGED
|
@@ -1508,6 +1508,7 @@ extern "C" {
|
|
|
1508
1508
|
WSP_GGML_API int wsp_ggml_cpu_has_clblast (void);
|
|
1509
1509
|
WSP_GGML_API int wsp_ggml_cpu_has_gpublas (void);
|
|
1510
1510
|
WSP_GGML_API int wsp_ggml_cpu_has_sse3 (void);
|
|
1511
|
+
WSP_GGML_API int wsp_ggml_cpu_has_ssse3 (void);
|
|
1511
1512
|
WSP_GGML_API int wsp_ggml_cpu_has_vsx (void);
|
|
1512
1513
|
|
|
1513
1514
|
//
|