Skip to content

Commit 5405f3a

Browse files
committed
Rework loadModel for ios to match the wfloat-web style
1 parent 2a4551f commit 5405f3a

12 files changed

Lines changed: 703 additions & 629 deletions

File tree

CONTRIBUTING.md

Lines changed: 8 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
# Contributing
21

3-
Thanks for contributing to `@wfloat/react-native-wfloat`.
2+
Before running the example app, create a local config file for untracked developer-specific values:
43

5-
This repository is a React Native library package with a local example app used to exercise the library during development.
4+
```ts
5+
// example/src/localConfig.ts
6+
export const LOCAL_CONFIG = {
7+
modelId: 'your-model-id',
8+
} as const;
9+
```
610

7-
Before contributing, please read the [Code of Conduct](./CODE_OF_CONDUCT.md).
11+
This file is gitignored. Use it for values you need locally in the example app but do not want to commit, such as a model id.
812

913
## Repository structure
1014

1115
- The package itself lives at the repository root.
1216
- The example app lives in [`example/`](./example) and is used to run the package on iOS and Android during local development.
1317

14-
The root package is the main thing you are developing. The example app is a harness for validating package changes in a real React Native app.
15-
1618
## Getting started
1719

1820
Install dependencies from the repository root:
@@ -21,100 +23,9 @@ Install dependencies from the repository root:
2123
yarn
2224
```
2325

24-
This repo uses Yarn workspaces. Use Yarn for development commands.
25-
26-
## Development model
27-
28-
Most code changes happen in the package at the repository root:
29-
30-
- JavaScript and TypeScript source lives in [`src/`](./src).
31-
- iOS native code lives in [`ios/`](./ios).
32-
- Android native code lives in [`android/`](./android).
33-
- Generated package output is written to [`lib/`](./lib) by the build step.
34-
35-
The example app in [`example/`](./example) is how you run and verify the package while you work.
36-
37-
## Core commands
38-
39-
From the repository root:
40-
41-
```sh
42-
yarn typecheck
43-
yarn lint
44-
yarn test
45-
yarn prepare
46-
```
47-
48-
What these do:
49-
50-
- `yarn typecheck` runs TypeScript checks.
51-
- `yarn lint` runs ESLint.
52-
- `yarn test` runs Jest tests.
53-
- `yarn prepare` runs `bob build` and regenerates the package build output.
54-
55-
## When to run `yarn prepare`
56-
57-
Run `yarn prepare` from the repository root when you change package code that should be rebuilt into distributable output, especially:
58-
59-
- files in `src/`
60-
- exported package APIs
61-
- codegen-related package definitions
62-
- package build output before publishing
63-
64-
Broadly, `yarn prepare` is the package build step for this repository.
65-
66-
## Working with the example app
67-
68-
You can run the example app either from the root with the workspace script or from inside `example/`.
69-
70-
From the repository root:
71-
72-
```sh
73-
yarn example start
74-
yarn example ios
75-
yarn example android
76-
```
77-
78-
Equivalent commands from `example/`:
79-
80-
```sh
81-
yarn start
82-
yarn ios
83-
yarn android
84-
```
85-
86-
## Typical development workflows
87-
88-
### JavaScript or TypeScript package changes
89-
90-
1. Edit package code in the repository root.
91-
2. Start Metro for the example app.
92-
3. Run the example app on iOS or Android.
93-
4. Run `yarn prepare` if you need refreshed built package output.
94-
95-
Typical commands:
96-
97-
```sh
98-
yarn example start
99-
yarn example ios
100-
```
101-
102-
or
103-
104-
```sh
105-
yarn example start
106-
yarn example android
107-
```
10826

10927
### iOS native changes
11028

111-
If you change iOS native code or iOS dependency state:
112-
113-
1. Make the package change in the repository root.
114-
2. Run `yarn prepare` if the package build or codegen output needs to be refreshed.
115-
3. Install pods from `example/ios`.
116-
4. Run the example app on iOS.
117-
11829
Typical commands:
11930

12031
```sh
@@ -124,105 +35,3 @@ bundle exec pod install
12435
cd ../..
12536
yarn example ios
12637
```
127-
128-
Notes:
129-
130-
- Use Bundler for CocoaPods commands.
131-
- Run React Native doctor for this repo from `example/`, not from the repository root.
132-
133-
Example:
134-
135-
```sh
136-
cd example
137-
npx react-native doctor
138-
```
139-
140-
### Android native changes
141-
142-
If you change Android native code or Android build configuration:
143-
144-
1. Make the package change in the repository root.
145-
2. Run `yarn prepare` if the package build or codegen output needs to be refreshed.
146-
3. Run the example app on Android.
147-
148-
Typical commands:
149-
150-
```sh
151-
yarn prepare
152-
yarn example android
153-
```
154-
155-
If you need Android codegen artifacts explicitly:
156-
157-
```sh
158-
cd example/android
159-
./gradlew generateCodegenArtifactsFromSchema
160-
cd ../..
161-
```
162-
163-
## Tooling notes
164-
165-
- CocoaPods and the iOS Ruby toolchain are configured from [`example/Gemfile`](./example/Gemfile).
166-
- The example app links to the package in the repository root.
167-
- Metro is configured so the example app can develop against the local package source.
168-
169-
## Quality checks
170-
171-
Before opening a pull request, run:
172-
173-
```sh
174-
yarn typecheck
175-
yarn lint
176-
yarn test
177-
```
178-
179-
If your change affects package build output or native integration, also run:
180-
181-
```sh
182-
yarn prepare
183-
```
184-
185-
If your change affects iOS, also verify:
186-
187-
```sh
188-
cd example/ios
189-
bundle exec pod install
190-
cd ../..
191-
yarn example ios
192-
```
193-
194-
If your change affects Android, also verify:
195-
196-
```sh
197-
yarn example android
198-
```
199-
200-
## Commit messages
201-
202-
This repo follows [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
203-
204-
Examples:
205-
206-
- `feat: add playback status event`
207-
- `fix: correct Android module initialization`
208-
- `docs: update iOS setup instructions`
209-
- `chore: refresh build configuration`
210-
211-
## Publishing
212-
213-
This repo uses `release-it` for releases:
214-
215-
```sh
216-
yarn release
217-
```
218-
219-
Before publishing, make sure the package has been rebuilt and the example app still validates the current changes.
220-
221-
## Pull requests
222-
223-
When opening a pull request:
224-
225-
- keep the change focused
226-
- include tests when practical
227-
- update docs when behavior or setup changes
228-
- mention any iOS or Android manual verification you performed

android/src/main/java/com/wfloat/WfloatModule.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.wfloat
33
import com.facebook.react.bridge.ReactApplicationContext
44
import com.facebook.react.module.annotations.ReactModule
55
import com.facebook.react.bridge.Promise
6+
import com.facebook.react.bridge.ReadableMap
67
import android.content.res.AssetManager
78
import com.k2fsa.sherpa.onnx.OfflineTts
89
import com.k2fsa.sherpa.onnx.OfflineTtsConfig
@@ -30,6 +31,13 @@ class WfloatModule(reactContext: ReactApplicationContext) :
3031
return NAME
3132
}
3233

34+
override fun loadModel(options: ReadableMap, promise: Promise) {
35+
promise.reject(
36+
"UNIMPLEMENTED",
37+
"loadModel is only implemented on iOS right now."
38+
)
39+
}
40+
3341
private fun copyDir(assetManager: AssetManager, assetDir: String, targetDir: File) {
3442
val assets = assetManager.list(assetDir) ?: return
3543
targetDir.mkdirs()

example/src/App.tsx

Lines changed: 8 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,25 @@
1-
import { Text, View, StyleSheet, Button } from 'react-native';
2-
import {
3-
speech,
4-
playWav,
5-
loadModel,
6-
unloadModel,
7-
testStorage,
8-
streamSpeech,
9-
} from '@wfloat/react-native-wfloat';
10-
11-
const playSound = async () => {
12-
try {
13-
const text =
14-
'Implementing a super epic duper VITS with streaming capabilities on iOS is feasible but requires custom development. VITS, originally a non-streaming text-to-speech model, has been adapted for streaming in projects like VITS Server, which supports fast inference and streaming capabilities. However, integrating such a server-based solution into an iOS app would involve setting up a backend server to handle the TTS processing and streaming the generated audio to the iOS device.'; // hellooooo hi world this is going to be a looong sentence let's see if it fails. Is a realistic text and i am messing with it";
15-
// const text = 'Hello world.';
16-
// const words = text.split(" ");
17-
// const randomLength = Math.floor(Math.random() * words.length) + 1;
18-
// const randomText = words.slice(0, randomLength).join(" ");
19-
20-
// console.log("random text", randomText);
21-
22-
const startTime = Date.now();
23-
const newSound = await speech('en_US-ryan-medium', text);
24-
const endTime = Date.now();
25-
26-
console.log(`runtime is ${endTime - startTime}ms`);
27-
console.log(newSound);
28-
playWav(newSound);
29-
} catch (error) {
30-
console.error(error);
31-
}
32-
};
33-
34-
const streamAudio = async () => {
35-
try {
36-
// const text = "Hello there Dubfloat. Wfloat is a realistic text. Anyway now you know. Auuuh, Peace out!";
37-
const text =
38-
'Implementing a super duper VITS with streaming capabilities on iOS is feasible but requires custom development. VITS, originally a non-streaming text-to-speech model, has been adapted for streaming in projects like VITS Server, which supports fast inference and streaming capabilities. However, integrating such a server-based solution into an iOS app would involve setting up a backend server to handle the TTS processing and streaming the generated audio to the iOS device.';
39-
// const words = text.split(" ");
40-
// const randomLength = Math.floor(Math.random() * words.length) + 1;
41-
// const randomText = words.slice(0, randomLength).join(" ");
42-
43-
// console.log("random text", randomText);
44-
45-
const startTime = Date.now();
46-
const newSound = await streamSpeech('en_US-ryan-medium', text);
47-
console.log('newSound', newSound);
48-
const endTime = Date.now();
49-
playWav(newSound);
50-
51-
console.log(`runtime is ${endTime - startTime}ms`);
52-
console.log(newSound);
53-
// playWav(newSound);
54-
} catch (error) {
55-
console.error(error);
56-
}
57-
};
1+
import { View, StyleSheet, Button } from 'react-native';
2+
import { SpeechClient } from '@wfloat/react-native-wfloat';
3+
import { LOCAL_CONFIG } from './localConfig';
584

595
const downloadVoice = async () => {
606
try {
61-
// const modelPath = await loadModel('default_male');
627
console.log('loading model');
63-
const modelPath = await loadModel('en_US-ryan-medium');
8+
await SpeechClient.loadModel(LOCAL_CONFIG.modelId, {
9+
onProgressCallback: (event) => {
10+
console.log('loadModel progress', event);
11+
},
12+
});
6413
console.log('model loaded');
65-
console.log(modelPath);
6614
} catch (error) {
6715
console.error(error);
6816
}
6917
};
7018

71-
const removeVoice = async () => {
72-
await unloadModel('en_US-ryan-medium');
73-
};
74-
7519
export default function App() {
7620
return (
7721
<View style={styles.container}>
78-
{/* <Text>Result: {result}</Text> */}
79-
<Button title="Stream speech" onPress={streamAudio} />
80-
<Button title="Play Sound" onPress={playSound} />
8122
<Button title="Load model" onPress={downloadVoice} />
82-
<Button title="Unload model" onPress={removeVoice} />
83-
<Button title="Test Storage" onPress={testStorage} />
8423
</View>
8524
);
8625
}

ios/Wfloat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#ifdef RCT_NEW_ARCH_ENABLED
44

55
#import "generated/RNWfloatSpec/RNWfloatSpec.h"
6-
@interface Wfloat : NSObject <NativeWfloatSpec>
6+
@interface Wfloat : NativeWfloatSpecBase <NativeWfloatSpec>
77

88
#else
99

0 commit comments

Comments
 (0)