From 6b0a0eede600f5266d59edda24db195877a5b01b Mon Sep 17 00:00:00 2001 From: yankun Date: Thu, 30 Jul 2026 15:26:57 +0800 Subject: [PATCH] feat: add speech synthesis demo --- .../demo-speech-synthesis/.env.development | 1 + .../demo-speech-synthesis/.env.production | 1 + capabilities/demo-speech-synthesis/.gitignore | 7 + capabilities/demo-speech-synthesis/README.md | 38 ++++ capabilities/demo-speech-synthesis/index.html | 13 ++ .../demo-speech-synthesis/package.json | 29 +++ .../demo-speech-synthesis/postcss.config.js | 7 + .../demo-speech-synthesis/public/config.json | 11 + .../public/thumbnail.png | Bin 0 -> 24064 bytes .../demo-speech-synthesis/src/App.vue | 205 ++++++++++++++++++ .../src/assets/cutos.png | Bin 0 -> 7773 bytes .../src/components/CutosTopbar.vue | 35 +++ .../demo-speech-synthesis/src/main.ts | 5 + .../demo-speech-synthesis/src/style.css | 9 + .../demo-speech-synthesis/src/utils/config.ts | 34 +++ .../demo-speech-synthesis/src/vite-env.d.ts | 1 + .../demo-speech-synthesis/tailwind.config.js | 6 + .../demo-speech-synthesis/tsconfig.json | 19 ++ .../demo-speech-synthesis/vite.config.ts | 17 ++ 19 files changed, 438 insertions(+) create mode 100644 capabilities/demo-speech-synthesis/.env.development create mode 100644 capabilities/demo-speech-synthesis/.env.production create mode 100644 capabilities/demo-speech-synthesis/.gitignore create mode 100644 capabilities/demo-speech-synthesis/README.md create mode 100644 capabilities/demo-speech-synthesis/index.html create mode 100644 capabilities/demo-speech-synthesis/package.json create mode 100644 capabilities/demo-speech-synthesis/postcss.config.js create mode 100644 capabilities/demo-speech-synthesis/public/config.json create mode 100644 capabilities/demo-speech-synthesis/public/thumbnail.png create mode 100644 capabilities/demo-speech-synthesis/src/App.vue create mode 100644 capabilities/demo-speech-synthesis/src/assets/cutos.png create mode 100644 capabilities/demo-speech-synthesis/src/components/CutosTopbar.vue create mode 100644 capabilities/demo-speech-synthesis/src/main.ts create mode 100644 capabilities/demo-speech-synthesis/src/style.css create mode 100644 capabilities/demo-speech-synthesis/src/utils/config.ts create mode 100644 capabilities/demo-speech-synthesis/src/vite-env.d.ts create mode 100644 capabilities/demo-speech-synthesis/tailwind.config.js create mode 100644 capabilities/demo-speech-synthesis/tsconfig.json create mode 100644 capabilities/demo-speech-synthesis/vite.config.ts diff --git a/capabilities/demo-speech-synthesis/.env.development b/capabilities/demo-speech-synthesis/.env.development new file mode 100644 index 0000000..b0b990f --- /dev/null +++ b/capabilities/demo-speech-synthesis/.env.development @@ -0,0 +1 @@ +VITE_CUTOS_BROKER_URL=mock diff --git a/capabilities/demo-speech-synthesis/.env.production b/capabilities/demo-speech-synthesis/.env.production new file mode 100644 index 0000000..ef96a64 --- /dev/null +++ b/capabilities/demo-speech-synthesis/.env.production @@ -0,0 +1 @@ +VITE_CUTOS_BROKER_URL=localhost diff --git a/capabilities/demo-speech-synthesis/.gitignore b/capabilities/demo-speech-synthesis/.gitignore new file mode 100644 index 0000000..2f98841 --- /dev/null +++ b/capabilities/demo-speech-synthesis/.gitignore @@ -0,0 +1,7 @@ +node_modules +dist +dist-ssr +release +*.local +*.log +.DS_Store diff --git a/capabilities/demo-speech-synthesis/README.md b/capabilities/demo-speech-synthesis/README.md new file mode 100644 index 0000000..b65e6e7 --- /dev/null +++ b/capabilities/demo-speech-synthesis/README.md @@ -0,0 +1,38 @@ +# Demo Speech Synthesis + +CUTOS 4.0 LWA demo for `@cutos/speech-synthesis`. It uses the browser-side Web Speech API and Windows-installed voices. It does not require a CUTOS Provider, Device Driver, or Gateway service. + +## Local Development + +Build the sibling SDK first: + +```sh +cd ../sdk +npm install +npm run build + +cd ../demo-speech-synthesis +npm install +npm run dev +``` + +## LWA Build And Release + +```sh +npx cutos lwa build +npx cutos login --username office +npx cutos lwa upload +npx cutos lwa list demo-speech-synthesis +npx cutos lwa publish --device +``` + +The release version is managed only by `public/config.json`. + +## Offline Validation + +1. Run the LWA on a Windows CUTOS Runtime. +2. Confirm **Speech API Ready** and at least one listed voice. +3. Prefer a voice marked **Local** for offline operation. +4. Enter text and click **Speak**; the Activity card should show start and completion events. + +If no voices are listed, install a Windows speech voice pack and restart the Runtime. Some WebView implementations require speech to start from a user interaction, so this demo always uses an explicit Speak button. diff --git a/capabilities/demo-speech-synthesis/index.html b/capabilities/demo-speech-synthesis/index.html new file mode 100644 index 0000000..9929de6 --- /dev/null +++ b/capabilities/demo-speech-synthesis/index.html @@ -0,0 +1,13 @@ + + + + + + + CUTOS Speech Synthesis + + +
+ + + diff --git a/capabilities/demo-speech-synthesis/package.json b/capabilities/demo-speech-synthesis/package.json new file mode 100644 index 0000000..290a90a --- /dev/null +++ b/capabilities/demo-speech-synthesis/package.json @@ -0,0 +1,29 @@ +{ + "name": "demo-speech-synthesis", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "cutos lwa build", + "build:app": "vue-tsc --noEmit && vite build", + "package": "cutos lwa package", + "validate": "cutos lwa validate", + "preview": "vite preview" + }, + "dependencies": { + "@cutos/core": "^4.0.8", + "@cutos/speech-synthesis": "^4.0.0", + "vue": "^3.4.31" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.5", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.40", + "postcss-import": "^16.1.0", + "tailwindcss": "^3.4.7", + "typescript": "^5.5.4", + "vite": "^5.3.4", + "vue-tsc": "^2.0.26" + } +} diff --git a/capabilities/demo-speech-synthesis/postcss.config.js b/capabilities/demo-speech-synthesis/postcss.config.js new file mode 100644 index 0000000..9d55d43 --- /dev/null +++ b/capabilities/demo-speech-synthesis/postcss.config.js @@ -0,0 +1,7 @@ +export default { + plugins: { + 'postcss-import': {}, + tailwindcss: {}, + autoprefixer: {} + } +} diff --git a/capabilities/demo-speech-synthesis/public/config.json b/capabilities/demo-speech-synthesis/public/config.json new file mode 100644 index 0000000..9522a7c --- /dev/null +++ b/capabilities/demo-speech-synthesis/public/config.json @@ -0,0 +1,11 @@ +{ + "name": "demo-speech-synthesis", + "version": "0.1.1", + "description": "CUTOS 4.0 offline Web Speech API text-to-speech demo.", + "params": { + "title": "CUTOS Speech Synthesis", + "subtitle": "Web Speech API · Windows Offline TTS", + "host": "localhost" + }, + "drvDependencies": {} +} diff --git a/capabilities/demo-speech-synthesis/public/thumbnail.png b/capabilities/demo-speech-synthesis/public/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..83da7faf15c31176125f9a56c4dba8e8c21e5a2b GIT binary patch literal 24064 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 literal 0 HcmV?d00001 diff --git a/capabilities/demo-speech-synthesis/src/App.vue b/capabilities/demo-speech-synthesis/src/App.vue new file mode 100644 index 0000000..02655af --- /dev/null +++ b/capabilities/demo-speech-synthesis/src/App.vue @@ -0,0 +1,205 @@ + + + diff --git a/capabilities/demo-speech-synthesis/src/assets/cutos.png b/capabilities/demo-speech-synthesis/src/assets/cutos.png new file mode 100644 index 0000000000000000000000000000000000000000..9f73429832a319c18f3557b88adc7567d2114347 GIT binary patch literal 7773 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 literal 0 HcmV?d00001 diff --git a/capabilities/demo-speech-synthesis/src/components/CutosTopbar.vue b/capabilities/demo-speech-synthesis/src/components/CutosTopbar.vue new file mode 100644 index 0000000..a1bf462 --- /dev/null +++ b/capabilities/demo-speech-synthesis/src/components/CutosTopbar.vue @@ -0,0 +1,35 @@ + + + + + diff --git a/capabilities/demo-speech-synthesis/src/main.ts b/capabilities/demo-speech-synthesis/src/main.ts new file mode 100644 index 0000000..fe5bae3 --- /dev/null +++ b/capabilities/demo-speech-synthesis/src/main.ts @@ -0,0 +1,5 @@ +import { createApp } from 'vue' +import App from './App.vue' +import './style.css' + +createApp(App).mount('#app') diff --git a/capabilities/demo-speech-synthesis/src/style.css b/capabilities/demo-speech-synthesis/src/style.css new file mode 100644 index 0000000..11f9307 --- /dev/null +++ b/capabilities/demo-speech-synthesis/src/style.css @@ -0,0 +1,9 @@ +:root { font-family: Inter, "Segoe UI", Arial, sans-serif; color: #20262c; background: #eef1f3; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; } +* { box-sizing: border-box; } body { margin: 0; min-width: 320px; min-height: 100vh; } button, input, select, textarea { font: inherit; }.app-shell { min-height: 100vh; background: #eef1f3; }.page { width: min(1420px, 100%); margin: 0 auto; padding: 28px clamp(18px, 3vw, 42px) 36px; } +.hero { display:flex; justify-content:space-between; align-items:flex-end; gap:24px; margin: 0 0 22px; }.eyebrow { margin:0 0 7px; color:#168c81; font-size:11px; font-weight:800; letter-spacing:.13em; }.hero h2,.card h3 { margin:0; }.hero h2 { font-size:28px; line-height:1.2; }.hero p:not(.eyebrow) { max-width:690px; margin:9px 0 0; color:#627079; line-height:1.55; }.sdk-badge { min-width:245px; display:flex; flex-direction:column; gap:4px; padding:12px 14px; border:1px solid #ced8dd; border-radius:8px; background:#fff; font-size:12px; }.sdk-badge span { color:#71808a; font-size:10px; font-weight:800; letter-spacing:.1em; }.sdk-badge strong { color:#26343b; } +.grid { display:grid; grid-template-columns:repeat(12,minmax(0,1fr)); gap:18px; }.card { min-width:0; padding:20px; border:1px solid #d6dfe3; border-radius:10px; background:#fff; box-shadow:0 1px 2px rgba(25,42,50,.04); }.compose-card { grid-column:span 7; }.voices-card { grid-column:span 5; }.controls-card { grid-column:span 4; }.activity-card { grid-column:span 8; }.card-heading { display:flex; align-items:flex-start; justify-content:space-between; gap:12px; margin-bottom:18px; }.card h3 { font-size:18px; }.state,.count { padding:5px 8px; border-radius:999px; background:#edf1f3; color:#65737b; font-size:11px; font-weight:700; }.state.active { background:#def5ee; color:#137867; }.state.paused { background:#fff1d8; color:#9a6413; } +.field-label { display:block; margin:0 0 7px; color:#53636b; font-size:12px; font-weight:700; }textarea,select { width:100%; border:1px solid #bbc9cf; border-radius:6px; background:#fff; color:#26343b; outline:none; }textarea { resize:vertical; padding:11px; line-height:1.55; }select { height:38px; padding:0 10px; }textarea:focus,select:focus { border-color:#16a394; box-shadow:0 0 0 3px rgba(22,163,148,.12); }.textarea-meta { display:flex; justify-content:space-between; gap:12px; margin:7px 0 16px; color:#839098; font-size:11px; }.action-row { display:flex; flex-wrap:wrap; gap:9px; }button { min-height:36px; padding:0 14px; border:1px solid #b9c6cc; border-radius:6px; background:#fff; color:#35444b; cursor:pointer; font-weight:700; font-size:13px; }button:hover:not(:disabled) { border-color:#71848d; }button:disabled { cursor:not-allowed; opacity:.45; }.primary { border-color:#168f81; background:#16a394; color:#fff; }.primary:hover:not(:disabled) { background:#118b7d; }.text-button { min-height:0; padding:0; border:0; color:#168c81; background:transparent; } +.filter-row { display:flex; align-items:flex-end; gap:16px; margin-bottom:16px; }.filter-row label:first-child { flex:1; }.filter-row label > span { display:block; margin-bottom:7px; color:#53636b; font-size:12px; font-weight:700; }.switch { display:flex; align-items:center; gap:7px; height:38px; color:#53636b; font-size:12px; white-space:nowrap; }.switch input { width:15px; height:15px; accent-color:#16a394; }.voice-note { margin:13px 0 0; color:#728087; font-size:12px; line-height:1.45; }.voice-note strong { color:#168c81; } +.range { display:block; margin:0 0 21px; }.range:last-child { margin-bottom:0; }.range span { display:flex; justify-content:space-between; margin-bottom:8px; color:#53636b; font-size:12px; font-weight:700; }.range b { color:#168c81; }.range input { width:100%; accent-color:#16a394; }.activity-list { max-height:197px; overflow:auto; border-top:1px solid #e7edef; }.activity-item { display:grid; grid-template-columns:75px 1fr; gap:10px; padding:9px 1px; border-bottom:1px solid #edf1f3; font-size:12px; line-height:1.4; }.activity-item time { color:#87949b; }.activity-item.success span { color:#157969; }.activity-item.warning span { color:#9a6413; }.activity-item.error span { color:#b34d49; }.empty { margin:17px 0; color:#87949b; font-size:12px; } +@media (max-width:900px) { .compose-card,.voices-card,.controls-card,.activity-card { grid-column:span 6; }.hero { align-items:flex-start; flex-direction:column; }.sdk-badge { min-width:0; width:100%; } } +@media (max-width:640px) { .page { padding:20px 14px 28px; }.grid { grid-template-columns:1fr; gap:14px; }.compose-card,.voices-card,.controls-card,.activity-card { grid-column:span 1; }.card { padding:17px; }.filter-row { align-items:flex-start; flex-direction:column; gap:10px; }.textarea-meta { align-items:flex-start; flex-direction:column; gap:3px; } } diff --git a/capabilities/demo-speech-synthesis/src/utils/config.ts b/capabilities/demo-speech-synthesis/src/utils/config.ts new file mode 100644 index 0000000..a77d233 --- /dev/null +++ b/capabilities/demo-speech-synthesis/src/utils/config.ts @@ -0,0 +1,34 @@ +export interface LwaConfig { + name: string + version: string + params: Record +} + +const fallback: LwaConfig = { + name: 'demo-speech-synthesis', + version: '0.1.1', + params: { title: 'CUTOS Speech Synthesis', subtitle: 'Web Speech API · Windows Offline TTS', host: 'localhost' } +} + +function parseParams() { + const raw = new URLSearchParams(location.search).get('params') + if (!raw) return {} + try { + const value = JSON.parse(raw) + return value && typeof value === 'object' ? value as Record : {} + } catch { + return {} + } +} + +export async function loadConfig(): Promise { + try { + const url = new URL('config.json', window.location.href).toString() + const response = await fetch(url, { cache: 'no-cache' }) + if (!response.ok) throw new Error(`Failed to load config.json: ${response.status}`) + const config = await response.json() as LwaConfig + return { ...fallback, ...config, params: { ...fallback.params, ...config.params, ...parseParams() } } + } catch { + return { ...fallback, params: { ...fallback.params, ...parseParams() } } + } +} diff --git a/capabilities/demo-speech-synthesis/src/vite-env.d.ts b/capabilities/demo-speech-synthesis/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/capabilities/demo-speech-synthesis/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/capabilities/demo-speech-synthesis/tailwind.config.js b/capabilities/demo-speech-synthesis/tailwind.config.js new file mode 100644 index 0000000..d008c38 --- /dev/null +++ b/capabilities/demo-speech-synthesis/tailwind.config.js @@ -0,0 +1,6 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{vue,ts}'], + theme: { extend: {} }, + plugins: [] +} diff --git a/capabilities/demo-speech-synthesis/tsconfig.json b/capabilities/demo-speech-synthesis/tsconfig.json new file mode 100644 index 0000000..9250956 --- /dev/null +++ b/capabilities/demo-speech-synthesis/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + "moduleResolution": "Bundler", + "allowImportingTsExtensions": false, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "strict": true, + "baseUrl": ".", + "paths": { "@/*": ["src/*"] } + }, + "include": ["src/**/*.ts", "src/**/*.vue"] +} diff --git a/capabilities/demo-speech-synthesis/vite.config.ts b/capabilities/demo-speech-synthesis/vite.config.ts new file mode 100644 index 0000000..1444291 --- /dev/null +++ b/capabilities/demo-speech-synthesis/vite.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +export default defineConfig({ + base: './', + publicDir: 'public', + build: { target: ['chrome74'] }, + resolve: { alias: { '@': '/src' } }, + plugins: [vue()], + optimizeDeps: { + esbuildOptions: { + define: { global: 'globalThis' }, + target: 'es2015', + supported: { bigint: true } + } + } +})