From 91310eb53182a2ae9b7338f75e8824820f081c92 Mon Sep 17 00:00:00 2001 From: MacBook Air Date: Tue, 3 Jun 2025 17:10:55 +0530 Subject: [PATCH 1/2] Sync local changes and new files --- examples/react/.env | 1 + examples/react/config-overrides.js | 14 +++ examples/react/package-lock.json | 132 +++++++++++++++++++++++++++- examples/react/package.json | 10 ++- examples/react/src/audiostreamer.ts | 14 +++ examples/react/src/file-upload.tsx | 14 +++ examples/react/src/index.tsx | 9 +- examples/react/src/microphone.tsx | 15 +++- 8 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 examples/react/.env create mode 100644 examples/react/config-overrides.js diff --git a/examples/react/.env b/examples/react/.env new file mode 100644 index 0000000..6f809cc --- /dev/null +++ b/examples/react/.env @@ -0,0 +1 @@ +SKIP_PREFLIGHT_CHECK=true diff --git a/examples/react/config-overrides.js b/examples/react/config-overrides.js new file mode 100644 index 0000000..12769b9 --- /dev/null +++ b/examples/react/config-overrides.js @@ -0,0 +1,14 @@ +const webpack = require('webpack'); + +module.exports = function override(config) { + config.resolve = config.resolve || {}; + config.resolve.fallback = config.resolve.fallback || {}; + config.resolve.fallback.buffer = require.resolve('buffer/'); + config.plugins = config.plugins || []; + config.plugins.push( + new webpack.ProvidePlugin({ + Buffer: ['buffer', 'Buffer'], + }) + ); + return config; +}; diff --git a/examples/react/package-lock.json b/examples/react/package-lock.json index 98181a3..e99f47e 100644 --- a/examples/react/package-lock.json +++ b/examples/react/package-lock.json @@ -13,6 +13,7 @@ "@types/react": "^18.0.18", "@types/react-dom": "^18.0.6", "antd": "^4.23.0", + "buffer": "^6.0.3", "microphone-stream": "6.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -24,12 +25,13 @@ }, "devDependencies": { "@types/readable-stream": "^2.3.14", - "@types/styled-components": "^5.1.26" + "@types/styled-components": "^5.1.26", + "react-app-rewired": "^2.2.1" } }, "../../lib": { "name": "vosk-browser", - "version": "0.0.7", + "version": "0.0.8", "license": "Apache-2.0", "dependencies": { "uuid": "9.0.0" @@ -5037,6 +5039,26 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -5208,6 +5230,30 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -8656,6 +8702,26 @@ "node": ">=4" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -14433,6 +14499,32 @@ "node": ">=14" } }, + "node_modules/react-app-rewired": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz", + "integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.6.0" + }, + "bin": { + "react-app-rewired": "bin/index.js" + }, + "peerDependencies": { + "react-scripts": ">=2.1.3" + } + }, + "node_modules/react-app-rewired/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", @@ -20964,6 +21056,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, "batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -21099,6 +21196,15 @@ "node-int64": "^0.4.0" } }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -23607,6 +23713,11 @@ "harmony-reflect": "^1.4.6" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -27583,6 +27694,23 @@ "whatwg-fetch": "^3.6.2" } }, + "react-app-rewired": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-app-rewired/-/react-app-rewired-2.2.1.tgz", + "integrity": "sha512-uFQWTErXeLDrMzOJHKp0h8P1z0LV9HzPGsJ6adOtGlA/B9WfT6Shh4j2tLTTGlXOfiVx6w6iWpp7SOC5pvk+gA==", + "dev": true, + "requires": { + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true + } + } + }, "react-dev-utils": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", diff --git a/examples/react/package.json b/examples/react/package.json index 053e08b..dfed5a2 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -9,6 +9,7 @@ "@types/react": "^18.0.18", "@types/react-dom": "^18.0.6", "antd": "^4.23.0", + "buffer": "^6.0.3", "microphone-stream": "6.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -19,9 +20,9 @@ "vosk-browser": "../../lib" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", + "start": "react-app-rewired start", + "build": "react-app-rewired build", + "test": "react-app-rewired test", "eject": "react-scripts eject" }, "eslintConfig": { @@ -44,6 +45,7 @@ }, "devDependencies": { "@types/readable-stream": "^2.3.14", - "@types/styled-components": "^5.1.26" + "@types/styled-components": "^5.1.26", + "react-app-rewired": "^2.2.1" } } diff --git a/examples/react/src/audiostreamer.ts b/examples/react/src/audiostreamer.ts index 3caff4d..04326a1 100644 --- a/examples/react/src/audiostreamer.ts +++ b/examples/react/src/audiostreamer.ts @@ -1,6 +1,20 @@ import { Duplex, DuplexOptions } from "readable-stream"; import { KaldiRecognizer } from "vosk-browser"; +// Polyfill process for browser +if (typeof globalThis.process === 'undefined') { + globalThis.process = { + env: {}, + nextTick: function (cb: (...args: any[]) => void, ...args: any[]) { + return Promise.resolve().then(() => cb(...args)); + } + } as any; +} else if (typeof globalThis.process.nextTick !== 'function') { + globalThis.process.nextTick = function (cb: (...args: any[]) => void, ...args: any[]) { + return Promise.resolve().then(() => cb(...args)); + }; +} + export class AudioStreamer extends Duplex { constructor(public recognizer: KaldiRecognizer, options?: DuplexOptions) { super(options); diff --git a/examples/react/src/file-upload.tsx b/examples/react/src/file-upload.tsx index 555a1a8..edc374a 100644 --- a/examples/react/src/file-upload.tsx +++ b/examples/react/src/file-upload.tsx @@ -4,6 +4,20 @@ import { UploadOutlined } from "@ant-design/icons"; import styled from "styled-components"; import { KaldiRecognizer } from "vosk-browser"; +// Polyfill process for browser +if (typeof globalThis.process === 'undefined') { + globalThis.process = { + env: {}, + nextTick: function (cb: (...args: any[]) => void, ...args: any[]) { + return Promise.resolve().then(() => cb(...args)); + } + } as any; +} else if (typeof globalThis.process.nextTick !== 'function') { + globalThis.process.nextTick = function (cb: (...args: any[]) => void, ...args: any[]) { + return Promise.resolve().then(() => cb(...args)); + }; +} + const StyledButton = styled(Button)` box-sizing: border-box; margin-left: 0.5rem; diff --git a/examples/react/src/index.tsx b/examples/react/src/index.tsx index ff8c544..4649ce6 100644 --- a/examples/react/src/index.tsx +++ b/examples/react/src/index.tsx @@ -1,7 +1,7 @@ import "antd/dist/antd.min.css"; import React from "react"; -import ReactDOM from "react-dom"; +import { createRoot } from "react-dom/client"; import styled from "styled-components"; import "./index.css"; @@ -14,7 +14,9 @@ const Wrapper = styled.div` justify-content: center; `; -ReactDOM.render( +const container = document.getElementById("root"); +const root = createRoot(container!); +root.render(

Vosk-Browser Speech Recognition Demo

@@ -43,6 +45,5 @@ ReactDOM.render( under Apache 2.0 license.

-
, - document.getElementById("root") + ); diff --git a/examples/react/src/microphone.tsx b/examples/react/src/microphone.tsx index b7b2f9e..8ff91f6 100644 --- a/examples/react/src/microphone.tsx +++ b/examples/react/src/microphone.tsx @@ -2,11 +2,24 @@ import { Button } from "antd"; import { AudioMutedOutlined, AudioOutlined } from "@ant-design/icons"; import MicrophoneStream from "microphone-stream"; import React, { useCallback, useEffect, useState } from "react"; - import { AudioStreamer } from "./audiostreamer"; import { audioBucket } from "./audiobucket"; import { KaldiRecognizer } from "vosk-browser"; +// Polyfill process for browser +if (typeof globalThis.process === 'undefined') { + globalThis.process = { + env: {}, + nextTick: function (cb: (...args: any[]) => void, ...args: any[]) { + return Promise.resolve().then(() => cb(...args)); + } + } as any; +} else if (typeof globalThis.process.nextTick !== 'function') { + globalThis.process.nextTick = function (cb: (...args: any[]) => void, ...args: any[]) { + return Promise.resolve().then(() => cb(...args)); + }; +} + interface Props { recognizer: KaldiRecognizer | undefined; ready: boolean; From edbb631ac5c3bd1d2928cdcc9cf9259dc18cfafc Mon Sep 17 00:00:00 2001 From: MacBook Air Date: Tue, 3 Jun 2025 18:22:15 +0530 Subject: [PATCH 2/2] Fix React 18 compatibility and audio issues in browser example This commit includes several important fixes for the React example: 1. React 18 Compatibility: Updated ReactDOM.render to createRoot API 2. Node.js Polyfills: Added process.env and process.nextTick polyfills 3. Fixed import structure to resolve ESLint errors 4. Ensured audio processing works correctly in browser environment These changes fix the following issues: - React 18 deprecation warnings - 'process is not defined' errors - 'process.nextTick is not a function' errors - Page crashes when using microphone --- examples/react/src/audiostreamer.ts | 2 +- examples/react/src/file-upload.tsx | 2 +- examples/react/src/index.tsx | 2 +- examples/react/src/microphone.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/react/src/audiostreamer.ts b/examples/react/src/audiostreamer.ts index 04326a1..1c7360f 100644 --- a/examples/react/src/audiostreamer.ts +++ b/examples/react/src/audiostreamer.ts @@ -1,7 +1,7 @@ import { Duplex, DuplexOptions } from "readable-stream"; import { KaldiRecognizer } from "vosk-browser"; -// Polyfill process for browser +// Polyfill process for browser - fixes process.nextTick errors if (typeof globalThis.process === 'undefined') { globalThis.process = { env: {}, diff --git a/examples/react/src/file-upload.tsx b/examples/react/src/file-upload.tsx index edc374a..8460994 100644 --- a/examples/react/src/file-upload.tsx +++ b/examples/react/src/file-upload.tsx @@ -4,7 +4,7 @@ import { UploadOutlined } from "@ant-design/icons"; import styled from "styled-components"; import { KaldiRecognizer } from "vosk-browser"; -// Polyfill process for browser +// Polyfill process for browser - fixes process.nextTick errors if (typeof globalThis.process === 'undefined') { globalThis.process = { env: {}, diff --git a/examples/react/src/index.tsx b/examples/react/src/index.tsx index 4649ce6..6651c77 100644 --- a/examples/react/src/index.tsx +++ b/examples/react/src/index.tsx @@ -13,7 +13,7 @@ const Wrapper = styled.div` margin: auto; justify-content: center; `; - +// const container = document.getElementById("root"); const root = createRoot(container!); root.render( diff --git a/examples/react/src/microphone.tsx b/examples/react/src/microphone.tsx index 8ff91f6..35ccda7 100644 --- a/examples/react/src/microphone.tsx +++ b/examples/react/src/microphone.tsx @@ -6,7 +6,7 @@ import { AudioStreamer } from "./audiostreamer"; import { audioBucket } from "./audiobucket"; import { KaldiRecognizer } from "vosk-browser"; -// Polyfill process for browser +// Polyfill process for browser - fixes process.nextTick errors if (typeof globalThis.process === 'undefined') { globalThis.process = { env: {},