Phase 1: Browser bundle + TTS/Tentone solver scaffolding
- Content/Browser: package.json, vite.config.ts, src/index.ts for JS bundling - Content/Browser/build-browser.bat for Windows npm build - Solvers/piper/piper_tts_wrapper.py for TTS sidecar (1C) - Solvers/tentone/build.bat for OpenCV-aware standalone build (1G) - Supports 1H (pmndrs spatial), 1I (echarts analytics), 1J (model-viewer)
This commit is contained in:
parent
91c15ad366
commit
0fbae2f3bc
6 changed files with 260 additions and 0 deletions
25
Content/Browser/build-browser.bat
Normal file
25
Content/Browser/build-browser.bat
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
@echo off
|
||||
setlocal
|
||||
|
||||
REM Build HyperTwist browser runtime bundle
|
||||
REM Phase 1H, 1I, 1J: bundles all JS spatial/analytics/model-viewer repos
|
||||
|
||||
cd /d "%~dp0"
|
||||
|
||||
echo Installing browser runtime dependencies...
|
||||
call npm install
|
||||
if errorlevel 1 (
|
||||
echo npm install failed
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Building browser runtime bundle...
|
||||
call npm run build
|
||||
if errorlevel 1 (
|
||||
echo Build failed
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Browser runtime built successfully.
|
||||
echo Output: dist\hypertwist-browser-runtime.umd.js
|
||||
echo Copy to Content\Browser\ for UE embedded WebBrowser widget loading.
|
||||
34
Content/Browser/package.json
Normal file
34
Content/Browser/package.json
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "hypertwist-browser-runtime",
|
||||
"version": "1.0.0",
|
||||
"description": "Bundled browser runtime for HyperTwist embedded WebBrowser widget",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "vite build",
|
||||
"build-deps": "node scripts/build-dependencies.js",
|
||||
"dev": "vite"
|
||||
},
|
||||
"dependencies": {
|
||||
"three": "^0.160.0",
|
||||
"@pmndrs/postprocessing": "file:../../.external/postprocessing",
|
||||
"@react-three/drei": "file:../../.external/drei",
|
||||
"@react-three/fiber": "^8.15.0",
|
||||
"leva": "file:../../.external/leva",
|
||||
"maath": "file:../../.external/maath",
|
||||
"three-stdlib": "file:../../.external/three-stdlib",
|
||||
"zustand": "file:../../.external/zustand",
|
||||
"@use-gesture/react": "file:../../.external/use-gesture",
|
||||
"@react-spring/three": "file:../../.external/react-spring",
|
||||
"@react-spring/web": "file:../../.external/react-spring",
|
||||
"echarts": "^5.4.0",
|
||||
"zrender": "file:../../.external/zrender",
|
||||
"echarts-gl": "file:../../.external/echarts-gl",
|
||||
"@google/model-viewer": "file:../../.external/model-viewer/packages/model-viewer",
|
||||
"claygl": "file:../../.external/claygl",
|
||||
"rubix-solver": "file:../../.external/rubix-solver"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^5.0.0",
|
||||
"typescript": "^5.3.0"
|
||||
}
|
||||
}
|
||||
71
Content/Browser/src/index.ts
Normal file
71
Content/Browser/src/index.ts
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* HyperTwist Browser Runtime Entry Point
|
||||
*
|
||||
* Exports all bundled browser-capable libraries for use in the embedded
|
||||
* WebBrowser widget or external browser runtime.
|
||||
*
|
||||
* Phase 1 wiring targets:
|
||||
* - 1G: tentone/rubix-solver (vision + solver UI)
|
||||
* - 1H: pmndrs spatial stack (postprocessing, drei, fiber, etc.)
|
||||
* - 1I: ecomfe analytics stack (zrender, echarts-gl)
|
||||
* - 1J: google/model-viewer sub-packages
|
||||
*/
|
||||
|
||||
// Three.js core (peer dependency for most spatial packages)
|
||||
import * as THREE from 'three';
|
||||
|
||||
// pmndrs spatial stack (1H)
|
||||
export { THREE };
|
||||
export { default as postprocessing } from '@pmndrs/postprocessing';
|
||||
export { default as drei } from '@react-three/drei';
|
||||
export { Canvas, useFrame, useThree } from '@react-three/fiber';
|
||||
export { default as leva } from 'leva';
|
||||
export { default as maath } from 'maath';
|
||||
export { default as threeStdlib } from 'three-stdlib';
|
||||
export { create as createZustandStore } from 'zustand';
|
||||
export { useGesture } from '@use-gesture/react';
|
||||
export { useSpring, animated } from '@react-spring/three';
|
||||
|
||||
// Analytics stack (1I)
|
||||
export { default as zrender } from 'zrender';
|
||||
export { default as echarts } from 'echarts';
|
||||
export { default as echartsGl } from 'echarts-gl';
|
||||
|
||||
// Model viewer (1J)
|
||||
export { default as ModelViewerElement } from '@google/model-viewer';
|
||||
|
||||
// claygl / clay-viewer (1H)
|
||||
export { default as claygl } from 'claygl';
|
||||
|
||||
// rubix-solver (1G)
|
||||
// Note: tentone solver is primarily a C++/OpenCV desktop app.
|
||||
// The JS bundle exports a placeholder for future WASM or web port.
|
||||
export const RubixSolver = {
|
||||
version: '1.0.0',
|
||||
note: 'C++ solver compiled as standalone executable. Web port TBD.'
|
||||
};
|
||||
|
||||
// UE Bridge: postMessage API for state synchronization
|
||||
interface UEStateBridge {
|
||||
sendState(state: object): void;
|
||||
onCommand(callback: (cmd: object) => void): void;
|
||||
}
|
||||
|
||||
export const UEBridge: UEStateBridge = {
|
||||
sendState(state: object) {
|
||||
if ((window as any).ue && (window as any).ue.hypertwist) {
|
||||
(window as any).ue.hypertwist.sendState(JSON.stringify(state));
|
||||
} else {
|
||||
window.parent.postMessage({ type: 'hypertwist-state', payload: state }, '*');
|
||||
}
|
||||
},
|
||||
onCommand(callback: (cmd: object) => void) {
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.type === 'hypertwist-command') {
|
||||
callback(event.data.payload);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
console.log('[HyperTwist Browser Runtime] Loaded');
|
||||
28
Content/Browser/vite.config.ts
Normal file
28
Content/Browser/vite.config.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import { resolve } from 'path';
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
lib: {
|
||||
entry: resolve(__dirname, 'src/index.ts'),
|
||||
name: 'HyperTwistBrowserRuntime',
|
||||
fileName: (format) => `hypertwist-browser-runtime.${format}.js`,
|
||||
formats: ['umd', 'es']
|
||||
},
|
||||
rollupOptions: {
|
||||
external: [],
|
||||
output: {
|
||||
globals: {},
|
||||
inlineDynamicImports: true
|
||||
}
|
||||
},
|
||||
outDir: 'dist',
|
||||
emptyOutDir: true,
|
||||
sourcemap: true
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(__dirname, 'src')
|
||||
}
|
||||
}
|
||||
});
|
||||
49
Solvers/piper/piper_tts_wrapper.py
Normal file
49
Solvers/piper/piper_tts_wrapper.py
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
HyperTwist IPC wrapper for rhasspy/piper TTS engine.
|
||||
|
||||
Usage:
|
||||
python piper_tts_wrapper.py --text "Hello world" --model path/to/model.onnx --output output.wav
|
||||
|
||||
Returns:
|
||||
Path to generated WAV file on success
|
||||
"""
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
def synthesize(text: str, model_path: str, config_path: str, output_path: str) -> str:
|
||||
"""Synthesize speech using piper."""
|
||||
if not os.path.exists(model_path):
|
||||
return f"ERROR: Model not found: {model_path}"
|
||||
|
||||
# Try using piper directly if available in PATH
|
||||
try:
|
||||
cmd = [
|
||||
"piper",
|
||||
"--model", model_path,
|
||||
"--config", config_path,
|
||||
"--output_file", output_path
|
||||
]
|
||||
result = subprocess.run(cmd, input=text, text=True, capture_output=True, timeout=60)
|
||||
if result.returncode == 0:
|
||||
return output_path
|
||||
return f"ERROR: {result.stderr}"
|
||||
except FileNotFoundError:
|
||||
return "ERROR: piper executable not found in PATH. Install piper or compile from .external/piper"
|
||||
except Exception as e:
|
||||
return f"ERROR: {e}"
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="HyperTwist Piper TTS Wrapper")
|
||||
parser.add_argument("--text", required=True, help="Text to synthesize")
|
||||
parser.add_argument("--model", required=True, help="Path to .onnx voice model")
|
||||
parser.add_argument("--config", help="Path to model config JSON")
|
||||
parser.add_argument("--output", default="output.wav", help="Output WAV path")
|
||||
args = parser.parse_args()
|
||||
|
||||
config_path = args.config or args.model.replace(".onnx", ".onnx.json")
|
||||
result = synthesize(args.text, args.model, config_path, args.output)
|
||||
print(result)
|
||||
53
Solvers/tentone/build.bat
Normal file
53
Solvers/tentone/build.bat
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
@echo off
|
||||
setlocal
|
||||
|
||||
REM Build tentone/rubix-solver as standalone executable
|
||||
REM Requires OpenCV. If OpenCV is not installed, only the solver logic
|
||||
REM (cube.cpp, solver.cpp, solution.cpp) can be compiled without vision.
|
||||
|
||||
set SRCDIR=..\..\.external\rubix-solver
|
||||
set OUTDIR=..\..\UnrealHyperTwist\Binaries\Win64\Solvers
|
||||
|
||||
if not exist %OUTDIR% mkdir %OUTDIR%
|
||||
|
||||
REM Try to find OpenCV
|
||||
set OPENCV_DIR=
|
||||
if exist "C:\opencv\build" set OPENCV_DIR=C:\opencv\build
|
||||
if exist "C:\tools\opencv\build" set OPENCV_DIR=C:\tools\opencv\build
|
||||
|
||||
if "%OPENCV_DIR%"=="" (
|
||||
echo WARNING: OpenCV not found. Building solver-only executable without vision.
|
||||
echo Install OpenCV and set OPENCV_DIR to enable computer vision features.
|
||||
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
cl /nologo /W4 /O2 /Fe%OUTDIR%\tentone-solver.exe ^
|
||||
%SRCDIR%\cube.cpp ^
|
||||
%SRCDIR%\solver.cpp ^
|
||||
%SRCDIR%\solution.cpp ^
|
||||
%SRCDIR%\utils.cpp ^
|
||||
%SRCDIR%\config.cpp ^
|
||||
%SRCDIR%\main.cpp
|
||||
) else (
|
||||
echo Found OpenCV at %OPENCV_DIR%
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
if errorlevel 1 exit /b 1
|
||||
|
||||
cl /nologo /W4 /O2 /I%OPENCV_DIR%\include /Fe%OUTDIR%\tentone-solver.exe ^
|
||||
%SRCDIR%\cube.cpp ^
|
||||
%SRCDIR%\solver.cpp ^
|
||||
%SRCDIR%\solution.cpp ^
|
||||
%SRCDIR%\utils.cpp ^
|
||||
%SRCDIR%\config.cpp ^
|
||||
%SRCDIR%\vision.cpp ^
|
||||
%SRCDIR%\main.cpp ^
|
||||
/link /LIBPATH:%OPENCV_DIR%\x64\vc16\lib opencv_world490.lib
|
||||
)
|
||||
|
||||
if errorlevel 1 (
|
||||
echo Build failed
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo tentone-solver built successfully at %OUTDIR%\tentone-solver.exe
|
||||
Loading…
Add table
Reference in a new issue