Compare commits

...
9 Commits
Author SHA1 Message Date
Jamie Pine 40fcb8d917 Bump version: 0.2.3 → 0.2.4 2026-03-15 10:18:51 -07:00
Jamie Pine ad64d1c3d9 Collect all zipvoice files for PyInstaller (fixes source code error) 2026-03-15 10:18:40 -07:00
Jamie Pine f826e45250 Install chatterbox-tts in CI release workflow 2026-03-15 10:17:23 -07:00
Jamie Pine 3d53c06c5b Bump version: 0.2.2 → 0.2.3 2026-03-15 10:08:56 -07:00
James Pine 9835b9f6d4 fix: prevent stale release data by removing Next.js fetch cache
Replace next: { revalidate: 600 } with cache: 'no-store' on GitHub
API fetches so new releases show up within 5 minutes (in-memory cache
only, no Next.js/Vercel cache layer on top).
2026-03-15 10:07:50 -07:00
Jamie Pine a15dd30b1e Update tauri-action to v0.6 to fix updater JSON and signature generation 2026-03-15 10:05:36 -07:00
Jamie Pine 1d343ac071 Treat missing/draft releases as up-to-date instead of showing error 2026-03-15 09:52:17 -07:00
James Pine ca602de0ae fix: don't reset audio player when unmuting during playback 2026-03-15 09:29:44 -07:00
James Pine cdc0293ca8 feat: add /linux-install page with build-from-source instructions
Linux download card now links to /linux-install instead of a direct
binary download. The page explains the CI situation and gives
clone + setup + build commands.
2026-03-15 09:17:30 -07:00
17 changed files with 195 additions and 18 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.2.2
current_version = 0.2.4
commit = True
tag = True
tag_name = v{new_version}
+3 -1
View File
@@ -61,6 +61,7 @@ jobs:
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r backend/requirements.txt
pip install --no-deps chatterbox-tts
- name: Install MLX dependencies (Apple Silicon only)
if: matrix.backend == 'mlx'
@@ -122,7 +123,7 @@ jobs:
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- uses: tauri-apps/tauri-action@v0
- uses: tauri-apps/tauri-action@v0.6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
@@ -173,6 +174,7 @@ jobs:
python -m pip install --upgrade pip
pip install pyinstaller
pip install -r backend/requirements.txt
pip install --no-deps chatterbox-tts
- name: Install PyTorch with CUDA 12.1
run: |
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@voicebox/app",
"version": "0.2.2",
"version": "0.2.4",
"private": true,
"type": "module",
"scripts": {
+1 -1
View File
@@ -1,3 +1,3 @@
# Backend package
__version__ = "0.2.2"
__version__ = "0.2.4"
+1
View File
@@ -76,6 +76,7 @@ def build_server(cuda=False):
'--hidden-import', 'backend.backends.luxtts_backend',
'--hidden-import', 'zipvoice',
'--hidden-import', 'zipvoice.luxvoice',
'--collect-all', 'zipvoice',
'--hidden-import', 'torch',
'--hidden-import', 'transformers',
'--hidden-import', 'fastapi',
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@voicebox/landing",
"version": "0.2.2",
"version": "0.2.4",
"description": "Landing page for voicebox.sh",
"scripts": {
"dev": "bun --bun next dev --turbo",
-1
View File
@@ -2,7 +2,6 @@ import { NextResponse } from 'next/server';
import { getLatestRelease } from '@/lib/releases';
export const dynamic = 'force-dynamic';
export const revalidate = 600; // Revalidate every 10 minutes
export async function GET() {
try {
+169
View File
@@ -0,0 +1,169 @@
import type { Metadata } from 'next';
import { Footer } from '@/components/Footer';
import { Navbar } from '@/components/Navbar';
import { GITHUB_REPO } from '@/lib/constants';
export const metadata: Metadata = {
title: 'Linux Install - Voicebox',
description: 'Build Voicebox from source on Linux. Clone, setup, and build in three commands.',
};
export default function LinuxInstall() {
return (
<>
<Navbar />
<section className="relative pt-32 pb-24">
<div className="mx-auto max-w-2xl px-6">
<h1 className="text-3xl font-bold tracking-tight text-foreground">Install on Linux</h1>
<p className="mt-4 text-muted-foreground">
We&apos;re currently working through CI issues that prevent us from shipping a reliable
pre-built binary for Linux. In the meantime, building from source is straightforward and
takes just a few minutes.
</p>
<div className="mt-10 space-y-6">
{/* Prerequisites */}
<div>
<h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-3">
Prerequisites
</h2>
<ul className="list-disc list-inside text-sm text-muted-foreground space-y-1">
<li>
<a
href="https://git-scm.com"
target="_blank"
rel="noopener noreferrer"
className="text-foreground hover:underline"
>
Git
</a>
</li>
<li>
<a
href="https://www.rust-lang.org/tools/install"
target="_blank"
rel="noopener noreferrer"
className="text-foreground hover:underline"
>
Rust
</a>
</li>
<li>
<a
href="https://github.com/casey/just#installation"
target="_blank"
rel="noopener noreferrer"
className="text-foreground hover:underline"
>
just
</a>{' '}
— install via{' '}
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">cargo install just</code>
</li>
<li>
<a
href="https://bun.sh"
target="_blank"
rel="noopener noreferrer"
className="text-foreground hover:underline"
>
Bun
</a>
</li>
<li>
Tauri system deps —{' '}
<a
href="https://v2.tauri.app/start/prerequisites/#linux"
target="_blank"
rel="noopener noreferrer"
className="text-foreground hover:underline"
>
see Tauri docs
</a>
</li>
</ul>
</div>
{/* Steps */}
<div>
<h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-3">
Build from source
</h2>
<div className="space-y-3">
<div className="rounded-lg border border-border bg-card/60 p-4 font-mono text-sm">
<div className="text-muted-foreground select-none"># Clone the repo</div>
<div>git clone https://github.com/jamiepine/voicebox.git</div>
<div>cd voicebox</div>
</div>
<div className="rounded-lg border border-border bg-card/60 p-4 font-mono text-sm">
<div className="text-muted-foreground select-none">
# Install all dependencies (Python venv, JS deps, etc.)
</div>
<div>just setup</div>
</div>
<div className="rounded-lg border border-border bg-card/60 p-4 font-mono text-sm">
<div className="text-muted-foreground select-none"># Build the app</div>
<div>just build</div>
</div>
</div>
<p className="mt-4 text-sm text-muted-foreground">
The built app will be in{' '}
<code className="text-xs bg-muted px-1.5 py-0.5 rounded">
tauri/src-tauri/target/release/bundle/
</code>
</p>
</div>
{/* Dev mode */}
<div>
<h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wider mb-3">
Or run in dev mode
</h2>
<div className="rounded-lg border border-border bg-card/60 p-4 font-mono text-sm">
<div className="text-muted-foreground select-none">
# Start the dev server with hot reload
</div>
<div>just dev</div>
</div>
</div>
</div>
{/* Links */}
<div className="mt-12 pt-8 border-t border-border flex flex-wrap gap-4 text-sm">
<a
href={GITHUB_REPO}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
GitHub Repo
</a>
<a
href={`${GITHUB_REPO}/issues`}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
Report an issue
</a>
<a
href={`${GITHUB_REPO}/blob/main/CONTRIBUTING.md`}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground hover:text-foreground transition-colors"
>
Contributing guide
</a>
</div>
</div>
</section>
<Footer />
</>
);
}
+2 -3
View File
@@ -294,14 +294,13 @@ export default function Home() {
{/* Linux */}
<a
href={downloadLinks.linux}
download
href="/linux-install"
className="flex items-center rounded-xl border border-border bg-card/60 backdrop-blur-sm px-5 py-4 transition-all hover:border-accent/30 hover:bg-card group"
>
<LinuxIcon className="h-6 w-6 shrink-0 text-muted-foreground group-hover:text-foreground transition-colors" />
<div className="ml-4">
<div className="text-sm font-medium">Linux</div>
<div className="text-xs text-muted-foreground">AppImage (x64)</div>
<div className="text-xs text-muted-foreground">Build from source</div>
</div>
</a>
</div>
@@ -20,7 +20,9 @@ export function unlockAudioContext() {
audioUnlocked = true;
// Unlock WaveSurfer's internal audio element
if (sharedWaveSurfer) {
// Skip if already playing — the context is already unlocked and the
// play/pause/reset dance would destroy the active playback.
if (sharedWaveSurfer && !sharedWaveSurfer.isPlaying()) {
const media = sharedWaveSurfer.getMediaElement();
if (media) {
media.muted = true;
+3 -2
View File
@@ -18,7 +18,7 @@ const GITHUB_API_BASE = 'https://api.github.com';
// Cache for release info (in-memory cache, resets on server restart)
let cachedReleaseInfo: ReleaseInfo | null = null;
let cacheTimestamp: number = 0;
const CACHE_DURATION = 1000 * 60 * 10; // 10 minutes
const CACHE_DURATION = 1000 * 60 * 5; // 5 minutes
// Cache for star count
let cachedStarCount: number | null = null;
@@ -36,7 +36,7 @@ export async function getLatestRelease(): Promise<ReleaseInfo> {
try {
const response = await fetch(`${GITHUB_API_BASE}/repos/${GITHUB_REPO}/releases/latest`, {
next: { revalidate: 600 }, // Revalidate every 10 minutes
cache: 'no-store',
headers: {
Accept: 'application/vnd.github.v3+json',
},
@@ -123,6 +123,7 @@ async function getTotalDownloads(): Promise<number> {
const response = await fetch(
`${GITHUB_API_BASE}/repos/${GITHUB_REPO}/releases?per_page=100&page=${page}`,
{
cache: 'no-store',
headers: { Accept: 'application/vnd.github.v3+json' },
},
);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "voicebox",
"version": "0.2.2",
"version": "0.2.4",
"private": true,
"workspaces": [
"app",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@voicebox/tauri",
"private": true,
"version": "0.2.2",
"version": "0.2.4",
"type": "module",
"scripts": {
"dev": "vite",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "voicebox"
version = "0.2.2"
version = "0.2.4"
description = "A production-quality desktop app for Qwen3-TTS voice cloning and generation"
authors = ["you"]
license = ""
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Voicebox",
"version": "0.2.2",
"version": "0.2.4",
"identifier": "sh.voicebox.app",
"build": {
"beforeDevCommand": "bun run dev",
+5 -1
View File
@@ -64,13 +64,17 @@ class TauriUpdater implements PlatformUpdater {
}
this.notifySubscribers();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
// Tauri updater throws on 404 / no published release / network errors.
// Treat "no update available" style errors as up-to-date, not failures.
const isNoUpdate = /404|not found|no update|up.to.date/i.test(message);
this.status = {
checking: false,
available: false,
downloading: false,
installing: false,
readyToInstall: false,
error: error instanceof Error ? error.message : 'Failed to check for updates',
error: isNoUpdate ? undefined : message,
};
this.notifySubscribers();
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@voicebox/web",
"private": true,
"version": "0.2.2",
"version": "0.2.4",
"type": "module",
"scripts": {
"dev": "vite",