@vsllabs/webgl-react
Version:
VSL-Labs Webgl implementation for translating text into 3D sign language
438 lines (361 loc) • 13.3 kB
Markdown
To install the package, run:
Using npm:
```bash
$ npm install @vsllabs/webgl-react
```
Using yarn:
```bash
$ yarn add @vsllabs/webgl-react
```
- [Usage Example (Normal mode)](#usage-example-normal-mode)
- [Usage Example (Streaming mode)](#usage-example-Streaming-mode)
- [Documentation](#documentation)
- [Required Parameters](#required-parameters)
- [Returned Values](#returned-values)
- [Example Workflow](#example-workflow)
## Usage Example (Normal mode):
Below is an example of how to use the useVslWebGL hook within a React component:
```js
import { useState } from 'react'
import { useVslWebGL } from '@vsllabs/webgl-react';
const app = () => {
// example text input state
const [inputText, setInputText] = useState('')
// invoke the useVslWebGL hook with your personal API_KEY and build URLs
const { VSLWebGl, unityProvider, translateTextToASL, isUnityLoaded, isTranslating, replay } = useVslWebGL({
API_KEY: 'Your API Key here',
streaming_mode: false, // Optional (false by default)
// *We will provide these URLs for you
loaderUrl: 'Unity build Url',
dataUrl: 'Unity build Url',
frameworkUrl: 'Unity build Url',
codeUrl: 'Unity build Url',
})
return (
<div
style={{
width: "400px",
height: "700px",
position: "relative",
margin: "auto",
}}
>
{!isUnityLoaded && (
<div
style={{
position: "absolute",
width: "100%",
height: "100%",
top: 0,
left: 0,
background: "#999",
display: "grid",
placeItems: "center",
}}
>
{/* Your Loading spinner here */}
Loading...
</div>
)}
{/* The WebGL component for rendering, can be styled as needed */}
<VSLWebGl
id="unityWebGl"
style={{ width: "100%", height: "100%" }}
unityProvider={unityProvider}
/>
{/* Example input for the text state */}
<input
type="text"
placeholder="Enter Text..."
value={inputText}
onChange={(ev) => setInputText(ev.target.value)}
style={{
border: "1px solid black",
borderRadius: "8px",
minHeight: "30px",
width: "100%",
marginBottom: "16px",
padding: "8px",
}}
/>
{/* Translate button, triggers translation when Unity is loaded and input is provided */}
<button
style={{
border: "1px solid black",
borderRadius: "4px",
padding: "8px 16px",
marginRight: "16px",
backgroundColor: "green",
color: "white",
}}
type="button"
onClick={() => translateTextToASL(inputText)}
>
{isTranslating ? "Loading..." : "Translate"}
</button>
{/* Replay button, replays the last translation */}
<button
style={{
border: "1px solid black",
borderRadius: "4px",
padding: "8px 16px",
}}
type="button"
onClick={replay}
>
Replay
</button>
</div>
);
}
```
Below is an example of the streaming mode with basic UI using the browser speech recognition for illustration:
```js
import { useState, useEffect } from "react";
import { useVslWebGL } from "@vsllabs/webgl-react";
import "./App.css"; // Importing the styling CSS file (file content is below)
const App = () => {
const [inputText, setInputText] = useState("");
const [isStreaming, setIsStreaming] = useState(false);
const {
VSLWebGl,
unityProvider,
translateTextToASL,
isUnityLoaded,
isTranslating,
replay,
} = useVslWebGL({
API_KEY: 'Your API Key here',
streaming_mode: isStreaming,
// *We will provide these URLs for you
loaderUrl: 'Unity build Url',
dataUrl: 'Unity build Url',
frameworkUrl: 'Unity build Url',
codeUrl: 'Unity build Url',
});
useEffect(() => {
if (isStreaming) {
const SpeechRecognition =
window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
alert("Speech Recognition is not supported in this browser.");
return;
}
const recognition = new SpeechRecognition();
recognition.continuous = true;
recognition.interimResults = false;
recognition.lang = "en-US";
recognition.onresult = (event) => {
const lastResult = event.results[event.results.length - 1];
if (lastResult.isFinal) {
const spokenText = lastResult[0].transcript.trim();
setInputText(spokenText);
translateTextToASL(spokenText);
}
};
recognition.onerror = (event) => {
console.error(
"Speech recognition error:",
event.error || event.message || event
);
};
recognition.start();
return () => recognition.stop();
}
}, [isStreaming]);
return (
<div id="appContainer">
{!isUnityLoaded && (
<div id="loadingOverlay">
<div className="spinner" />
</div>
)}
<div id="webglContainer">
<VSLWebGl
id="unityWebGl"
style={{ width: "100%", height: "100%" }}
unityProvider={unityProvider}
/>
</div>
<input
id="textInput"
type="text"
value={inputText}
onChange={(e) => setInputText(e.target.value)}
placeholder="Enter text to translate"
/>
<div id="buttonGroup">
<button
id="translateBtn"
type="button"
onClick={() => translateTextToASL(inputText)}
disabled={!isUnityLoaded || isTranslating}
className={isTranslating ? "btn translate disabled" : "btn translate"}
>
{isTranslating ? "Loading..." : "Translate"}
</button>
<button
id="replayBtn"
type="button"
onClick={replay}
className="btn replay"
className={isStreaming ? "btn replay disabled" : "btn replay"}
disabled={isStreaming}
>
Replay
</button>
<button
id="streamBtn"
type="button"
onClick={() => setIsStreaming((prev) => !prev)}
className={`btn stream ${isStreaming ? "stop" : "start"}`}
>
{isStreaming ? "Stop Streaming" : "Start Streaming"}
</button>
</div>
</div>
);
};
export default App;
```
```css
width: 800px;
height: 850px;
margin: 0 auto;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
padding: 1rem;
background-color: white;
border-radius: 1rem;
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1);
}
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color:
display: flex;
align-items: center;
justify-content: center;
border-radius: 1rem;
z-index: 10;
}
.spinner {
animation: spin 1s linear infinite;
border-top: 4px solid
border-radius: 9999px;
width: 3rem;
height: 3rem;
border-right: 4px solid transparent;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
width: 600px;
height: 600px;
position: relative;
border-radius: 1rem;
overflow: hidden;
}
width: 100%;
padding: 0.5rem 1rem;
border: 1px solid
border-radius: 0.375rem;
outline: none;
transition: box-shadow 0.2s;
}
box-shadow: 0 0 0 2px
}
display: flex;
gap: 0.5rem;
width: 100%;
}
.btn {
flex: 1;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
color: white;
transition: background-color 0.2s;
cursor: pointer;
border: none;
}
.btn.translate {
background-color:
}
.btn.translate:hover {
background-color:
}
.btn.translate.disabled {
background-color:
cursor: not-allowed;
}
.btn.replay {
background-color:
}
.btn.replay.disabled {
background-color:
cursor: not-allowed;
}
.btn.replay:hover {
background-color:
}
.btn.stream.start {
background-color:
}
.btn.stream.start:hover {
background-color:
}
.btn.stream.stop {
background-color:
}
.btn.stream.stop:hover {
background-color:
}
```
The ***useVslWebGL*** hook provides the necessary setup and functionality for integrating the VSL WebGL component within a React application. It returns an object with various properties and functions for rendering, controlling, and interacting with the WebGL component.
* **API_KEY**: Your unique API key for accessing the VSL WebGL services.
* **loaderUrl, dataUrl, frameworkUrl, codeUrl**: URLs provided by VSL for accessing the Unity WebGL build. Each URL is necessary for loading the Unity environment properly.
* **streaming_mode**: Toggle streaming mode. (boolean)
The following values and functions are returned by useVslWebGL:
| Value | Explanation |
| :------------ | :--------------------------------------------- |
| VSLWebGl | <ul><li>A JSX component for rendering the Unity WebGL. Can be styled and controlled within a parent component or container.</li><li>Example: <br><pre lang="javascript"> <VSLWebGl style={{ ... }} unityProvider={unityProvider} /> </pre></li></ul> |
| unityProvider | <ul><li>Required prop for the ***VSLWebGl*** component, provides the Unity instance.</li><li>Pass this to the ***unityProvider*** prop of *VSLWebGl* to initialize the Unity environment.</li></ul> |
| translateTextToASL | <ul><li>Function to trigger text translation within the Unity WebGL.</li><li>**Arguments:** Accepts a single argument (the text to translate).</li><li>**Example:** <pre lang="javascript"> translateTextToASL("Hello, world!") </pre></li></ul> |
| isUnityLoaded | <ul><li>Indicates whether the Unity WebGL component has fully loaded. Useful for checking readiness to show loaders and before triggering translation.</li><li>**Example:** Disabling the translate button until Unity is ready.</li></ul> |
| isTranslating | <ul><li>Represents the loading state during the translation process. Helpful for displaying loading indicators.</li><li>**Example:** <pre lang="javascript"> {isTranslating ? 'Translating...' : 'Translate'} </pre></li></ul> |
| replay | <ul><li>Function to replay the last translated text within the Unity WebGL.</li><li>**Arguments:** No arguments required.</li></ul> |
| changeBgColor | <ul><li>Changes the background color of the WebGL component.</li><li>**Arguments:** Accepts a single argument, a string representing a hex color value (e.g., #FFFFFF for white).</li><li>**Example:** <pre lang="javascript"> changeBgColor('#FF5733') </pre> to set the background color to a shade of orange.</li></ul> |
| setAnimationSpeed | <ul><li>Controls the speed of animations within the WebGL environment.</li><li>**Arguments:** Accepts a single string argument, which can be one of four options: "0" (for pause), "0.5", "1" (default), or "1.5".</li><li>**Example:** <pre lang="javascript"> setAnimationSpeed("1.5") </pre> to set the animation speed to 1.5x.</li></ul> |
| toggleCameraRotation | <ul><li>Toggles the rotation of the camera in the WebGL environment.</li><li>**Arguments:** Accepts a single boolean argument to enable (true) or disable (false > default) camera rotation.</li><li>**Example:** <pre lang="javascript"> toggleCameraRotation(true) </pre> to enable camera rotation.</li></ul> |
| error | <ul><li>If any errors occur during loading or translation, this string provides an error message explaining the issue.</li><li>**Example:** Display error in your UI if it’s not an empty string.</li><li>**Note:** Errors are also logged in the console</li></ul> |
| streaming_mode | <ul><li>Set to true to use streaming mode. </li><li>**Example:** When streaming mode is on, text provided to ***translateTextToASL*** function will be added to a queue where the animations will play in sequential manner. </li><li>**Note:** When set to false and a new text is provided to ***translateTextToASL*** while an animation is playing, will override it and start animating the new sentence. </li><li>**Note:** When streaming mode is on the ***reply*** function cannot be used, invoking it will do nothing</li></ul> |
1. Initialize the Hook: Call useVslWebGL with the required parameters to initialize the WebGL component.
2. Render the Component: Use <VSLWebGl /> in your component, styled to fit your layout.
3. Translate Text: Use the translateTextToASL function to translate input text when Unity is loaded (isUnityLoaded).
4. Replay Last Translation: Use the replay function to repeat the last translation as needed.
5. Handle Errors: Check the error value to catch and display any issues that occur during loading or translation.
## License
[MIT](LICENSE)