Two reports, one root: the platform's speech engine. "Loud cracking at the end of every sentence" is the browser/OS TTS popping between its internal sentence chunks (an idle cancel makes it worse). Hygiene for that path: never cancel when nothing is pending, normalise the spoken text (control characters, ellipses, dashes), and a 140ms beat between sections so speech never runs into the engine's tail. The real fix is a second voice source that does not use the platform engine: - lib/providers carries TTS profiles (OpenAI gpt-4o-mini-tts, Groq playai-tts, any OpenAI-compatible /audio/speech behind the custom provider), male voices first. - /api/tts proxies them with the same guards and the key still in headers. - the picker gains System / Natural, with the provider's voice list. - lib/podcast-audio plays one clip per section through a hidden <audio> element, measures the clip's real duration and gives each word a slice of it proportional to its spoken length - the highlight follows the audio exactly, and pause/seek/chapters become real audio operations. Clips cache per session, the next section generates while the current plays, and a voice change disposes the element and its blobs. Speed applies live (setRate) without dropping the cache. podcast-test stubs /api/tts with a real silent WAV and pins the path: the voice list, the request body, exactly one playing element, and the highlight riding currentTime. 43 checks. tests/lib.mjs launches Chromium with the autoplay policy relaxed (a real device has the listener's gesture). Version 0.7.6, SW v98.
44 lines
1.2 KiB
JSON
44 lines
1.2 KiB
JSON
{
|
|
"name": "freezmo",
|
|
"version": "0.7.6",
|
|
"private": true,
|
|
"license": "GPL-3.0-only",
|
|
"scripts": {
|
|
"predev": "node scripts/copy-pdf-worker.mjs",
|
|
"dev": "next dev -H 0.0.0.0 -p 3207",
|
|
"prebuild": "node scripts/copy-pdf-worker.mjs",
|
|
"build": "next build",
|
|
"start": "next start -H 0.0.0.0 -p 3207",
|
|
"lint": "eslint",
|
|
"test:e2e": "node tests/run-all.mjs",
|
|
"version:bump": "node scripts/bump-version.mjs"
|
|
},
|
|
"dependencies": {
|
|
"canvas-confetti": "^1.9.4",
|
|
"framer-motion": "^12.23.24",
|
|
"jszip": "^3.10.2",
|
|
"katex": "^0.19.0",
|
|
"mammoth": "^1.13.0",
|
|
"next": "15.5.27",
|
|
"pdfjs-dist": "^6.4.299",
|
|
"react": "19.1.0",
|
|
"react-dom": "19.1.0",
|
|
"web-push": "^3.6.7",
|
|
"zod": "^4.1.13"
|
|
},
|
|
"devDependencies": {
|
|
"@eslint/eslintrc": "^3",
|
|
"@tailwindcss/postcss": "^4",
|
|
"@types/canvas-confetti": "^1.9.0",
|
|
"@types/node": "^20",
|
|
"@types/react": "^19",
|
|
"@types/react-dom": "^19",
|
|
"@types/web-push": "^3.6.4",
|
|
"axe-core": "^4.14.0",
|
|
"eslint": "^9",
|
|
"eslint-config-next": "15.5.27",
|
|
"playwright-core": "^1.64.0",
|
|
"tailwindcss": "^4",
|
|
"typescript": "^5"
|
|
}
|
|
}
|