mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-26 13:45:16 -07:00
tests and better website
This commit is contained in:
+451
-392
@@ -1,422 +1,481 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import { Github, Globe, Languages, MessageSquare, SlidersHorizontal, Zap } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ControlUI } from '@/components/ControlUI';
|
||||
import { Features } from '@/components/Features';
|
||||
import { Footer } from '@/components/Footer';
|
||||
import { Navbar } from '@/components/Navbar';
|
||||
import { AppleIcon, LinuxIcon, WindowsIcon } from '@/components/PlatformIcons';
|
||||
import { VoiceCreator } from '@/components/VoiceCreator';
|
||||
import { DOWNLOAD_LINKS, GITHUB_REPO } from '@/lib/constants';
|
||||
import type { DownloadLinks } from '@/lib/releases';
|
||||
import {
|
||||
Github,
|
||||
Globe,
|
||||
Languages,
|
||||
MessageSquare,
|
||||
SlidersHorizontal,
|
||||
Zap,
|
||||
} from "lucide-react";
|
||||
import {useEffect, useState} from "react";
|
||||
import {ApiSection} from "@/components/ApiSection";
|
||||
import {ControlUI} from "@/components/ControlUI";
|
||||
import {Features} from "@/components/Features";
|
||||
import {Footer} from "@/components/Footer";
|
||||
import {Navbar} from "@/components/Navbar";
|
||||
import {AppleIcon, LinuxIcon, WindowsIcon} from "@/components/PlatformIcons";
|
||||
import {TutorialsSection} from "@/components/TutorialsSection";
|
||||
import {VoiceCreator} from "@/components/VoiceCreator";
|
||||
import {DOWNLOAD_LINKS, GITHUB_REPO} from "@/lib/constants";
|
||||
import type {DownloadLinks} from "@/lib/releases";
|
||||
|
||||
export default function Home() {
|
||||
const [downloadLinks, setDownloadLinks] = useState<DownloadLinks>(DOWNLOAD_LINKS);
|
||||
const [version, setVersion] = useState<string | null>(null);
|
||||
const [totalDownloads, setTotalDownloads] = useState<number | null>(null);
|
||||
const [downloadLinks, setDownloadLinks] =
|
||||
useState<DownloadLinks>(DOWNLOAD_LINKS);
|
||||
const [version, setVersion] = useState<string | null>(null);
|
||||
const [totalDownloads, setTotalDownloads] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/api/releases')
|
||||
.then((res) => {
|
||||
if (!res.ok) throw new Error('Failed to fetch releases');
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (data.downloadLinks) setDownloadLinks(data.downloadLinks);
|
||||
if (data.version) setVersion(data.version);
|
||||
if (data.totalDownloads != null) setTotalDownloads(data.totalDownloads);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to fetch release info:', error);
|
||||
});
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
fetch("/api/releases")
|
||||
.then((res) => {
|
||||
if (!res.ok) throw new Error("Failed to fetch releases");
|
||||
return res.json();
|
||||
})
|
||||
.then((data) => {
|
||||
if (data.downloadLinks) setDownloadLinks(data.downloadLinks);
|
||||
if (data.version) setVersion(data.version);
|
||||
if (data.totalDownloads != null) setTotalDownloads(data.totalDownloads);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to fetch release info:", error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
|
||||
{/* ── Hero Section ─────────────────────────────────────────────── */}
|
||||
<section className="relative pt-32 pb-16">
|
||||
{/* Background glow */}
|
||||
<div className="hero-glow hero-glow-fade pointer-events-none absolute inset-0 -top-32">
|
||||
<div className="absolute left-1/2 top-0 -translate-x-1/2 w-[800px] h-[600px] rounded-full bg-accent/15 blur-[150px]" />
|
||||
<div className="absolute left-1/2 top-12 -translate-x-1/2 w-[500px] h-[400px] rounded-full bg-accent/10 blur-[80px]" />
|
||||
</div>
|
||||
{/* ── Hero Section ─────────────────────────────────────────────── */}
|
||||
<section className="relative pt-32 pb-16">
|
||||
{/* Background glow */}
|
||||
<div className="hero-glow hero-glow-fade pointer-events-none absolute inset-0 -top-32">
|
||||
<div className="absolute left-1/2 top-0 -translate-x-1/2 w-[800px] h-[600px] rounded-full bg-accent/15 blur-[150px]" />
|
||||
<div className="absolute left-1/2 top-12 -translate-x-1/2 w-[500px] h-[400px] rounded-full bg-accent/10 blur-[80px]" />
|
||||
</div>
|
||||
|
||||
<div className="relative mx-auto max-w-7xl px-6 text-center">
|
||||
{/* Logo */}
|
||||
<div
|
||||
className="fade-in mx-auto mb-8 h-[120px] w-[120px] md:h-[160px] md:w-[160px]"
|
||||
style={{ animationDelay: '0ms' }}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/voicebox-logo-app.webp"
|
||||
alt="Voicebox"
|
||||
className="h-full w-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
<div className="relative mx-auto max-w-7xl px-6 text-center">
|
||||
{/* Logo */}
|
||||
<div
|
||||
className="fade-in mx-auto mb-8 h-[120px] w-[120px] md:h-[160px] md:w-[160px]"
|
||||
style={{animationDelay: "0ms"}}
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src="/voicebox-logo-app.webp"
|
||||
alt="Voicebox"
|
||||
className="h-full w-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Headline */}
|
||||
<div className="fade-in relative" style={{ animationDelay: '100ms' }}>
|
||||
<h1 className="text-5xl font-bold tracking-tighter leading-[0.9] text-foreground md:text-7xl lg:text-8xl">
|
||||
Your voice, your machine.
|
||||
</h1>
|
||||
</div>
|
||||
{/* Headline */}
|
||||
<div className="fade-in relative" style={{animationDelay: "100ms"}}>
|
||||
<h1 className="text-5xl font-bold tracking-tighter leading-[0.9] text-foreground md:text-7xl lg:text-8xl">
|
||||
Clone any voice, in seconds.
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Subtitle */}
|
||||
<p
|
||||
className="fade-in mx-auto mt-6 max-w-2xl text-lg text-muted-foreground md:text-xl"
|
||||
style={{ animationDelay: '200ms' }}
|
||||
>
|
||||
Open source voice cloning studio with support for multiple TTS engines. Clone any voice,
|
||||
generate natural speech, and compose multi-voice projects — all running locally.
|
||||
</p>
|
||||
{/* Subtitle */}
|
||||
<p
|
||||
className="fade-in mx-auto mt-6 max-w-2xl text-lg text-muted-foreground md:text-xl"
|
||||
style={{animationDelay: "200ms"}}
|
||||
>
|
||||
Open source voice cloning studio with support for multiple TTS
|
||||
engines. Clone any voice, generate natural speech, and compose
|
||||
multi-voice projects. All running{" "}
|
||||
<b className="text-white">locally on your machine.</b>
|
||||
</p>
|
||||
|
||||
{/* CTAs */}
|
||||
<div
|
||||
className="fade-in mt-10 flex flex-col sm:flex-row items-center justify-center gap-4"
|
||||
style={{ animationDelay: '300ms' }}
|
||||
>
|
||||
<a
|
||||
href="#download"
|
||||
className="rounded-full bg-accent px-8 py-3.5 text-sm font-semibold uppercase tracking-wider text-white shadow-[0_4px_20px_hsl(43_60%_50%/0.3),inset_0_2px_0_rgba(255,255,255,0.2),inset_0_-2px_0_rgba(0,0,0,0.1)] transition-all hover:bg-accent-faint active:shadow-[0_2px_10px_hsl(43_60%_50%/0.3),inset_0_4px_8px_rgba(0,0,0,0.3)]"
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
<a
|
||||
href={GITHUB_REPO}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2 rounded-full border border-border/60 bg-card/40 backdrop-blur-sm px-6 py-3 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground hover:border-border"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
View on GitHub
|
||||
</a>
|
||||
</div>
|
||||
{/* CTAs */}
|
||||
<div
|
||||
className="fade-in mt-10 flex flex-col sm:flex-row items-center justify-center gap-4"
|
||||
style={{animationDelay: "300ms"}}
|
||||
>
|
||||
<a
|
||||
href="#download"
|
||||
className="rounded-full bg-accent px-8 py-3.5 text-sm font-semibold uppercase tracking-wider text-white shadow-[0_4px_20px_hsl(43_60%_50%/0.3),inset_0_2px_0_rgba(255,255,255,0.2),inset_0_-2px_0_rgba(0,0,0,0.1)] transition-all hover:bg-accent-faint active:shadow-[0_2px_10px_hsl(43_60%_50%/0.3),inset_0_4px_8px_rgba(0,0,0,0.3)]"
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
<a
|
||||
href={GITHUB_REPO}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2 rounded-full border border-border/60 bg-card/40 backdrop-blur-sm px-6 py-3 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground hover:border-border"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
View on GitHub
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* Version + downloads */}
|
||||
<p
|
||||
className="fade-in mt-4 text-xs text-muted-foreground/50"
|
||||
style={{ animationDelay: '400ms' }}
|
||||
>
|
||||
{version ?? ''}
|
||||
{version && totalDownloads != null ? ' \u00b7 ' : ''}
|
||||
{totalDownloads != null ? `${totalDownloads.toLocaleString()} downloads` : ''}
|
||||
{version || totalDownloads != null ? ' \u00b7 ' : ''}
|
||||
macOS, Windows, Linux
|
||||
</p>
|
||||
</div>
|
||||
{/* Version + downloads */}
|
||||
<p
|
||||
className="fade-in mt-4 text-xs text-muted-foreground/50"
|
||||
style={{animationDelay: "400ms"}}
|
||||
>
|
||||
{version ?? ""}
|
||||
{version && totalDownloads != null ? " \u00b7 " : ""}
|
||||
{totalDownloads != null
|
||||
? `${totalDownloads.toLocaleString()} downloads`
|
||||
: ""}
|
||||
{version || totalDownloads != null ? " \u00b7 " : ""}
|
||||
macOS, Windows, Linux
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* ── ControlUI mockup ─────────────────────────────────────── */}
|
||||
<div className="mt-16">
|
||||
<ControlUI />
|
||||
</div>
|
||||
</section>
|
||||
{/* ── ControlUI mockup ─────────────────────────────────────── */}
|
||||
<div className="mt-16">
|
||||
<ControlUI />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Features ─────────────────────────────────────────────── */}
|
||||
<Features />
|
||||
{/* ── Features ─────────────────────────────────────────────── */}
|
||||
<Features />
|
||||
|
||||
{/* ── Voice Creator ────────────────────────────────────────── */}
|
||||
<VoiceCreator />
|
||||
{/* ── Voice Creator ────────────────────────────────────────── */}
|
||||
<VoiceCreator />
|
||||
|
||||
{/* ── Models ─────────────────────────────────────────────────── */}
|
||||
<section id="about" className="border-t border-border py-24">
|
||||
<div className="mx-auto max-w-5xl px-6">
|
||||
<div className="text-center mb-14">
|
||||
<h2 className="text-3xl font-semibold tracking-tight text-foreground md:text-4xl mb-4">
|
||||
Multi-Engine Architecture
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Choose the right model for every job. All models run locally on your hardware —
|
||||
download once, use forever.
|
||||
</p>
|
||||
</div>
|
||||
{/* ── Tutorials ────────────────────────────────────────────── */}
|
||||
<TutorialsSection />
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{/* Qwen3-TTS */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">Qwen3-TTS</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by Alibaba</span>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
1.7B
|
||||
</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
0.6B
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
High-quality multilingual voice cloning with natural prosody. The only engine with
|
||||
delivery instructions — control tone, pace, and emotion with natural language.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Globe className="h-3 w-3" />
|
||||
10 languages
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<MessageSquare className="h-3 w-3" />
|
||||
Delivery instructions
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* ── API Section ──────────────────────────────────────────── */}
|
||||
<ApiSection />
|
||||
|
||||
{/* Chatterbox */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">Chatterbox</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by Resemble AI</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Production-grade voice cloning with the broadest language support. 23 languages with
|
||||
zero-shot cloning and emotion exaggeration control.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Languages className="h-3 w-3" />
|
||||
23 languages
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* ── Models ─────────────────────────────────────────────────── */}
|
||||
<section id="about" className="border-t border-border py-24">
|
||||
<div className="mx-auto max-w-5xl px-6">
|
||||
<div className="text-center mb-14">
|
||||
<h2 className="text-3xl font-semibold tracking-tight text-foreground md:text-4xl mb-4">
|
||||
Multi-Engine Architecture
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Choose the right model for every job. All models run locally on
|
||||
your hardware — download once, use forever.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Chatterbox Turbo */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">Chatterbox Turbo</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by Resemble AI</span>
|
||||
</div>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
350M
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Lightweight and fast. Supports paralinguistic tags — embed [laugh], [sigh], [gasp]
|
||||
and more directly in your text for expressive, natural speech.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Zap className="h-3 w-3" />
|
||||
350M params
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<MessageSquare className="h-3 w-3" />
|
||||
[laugh] [sigh] tags
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{/* Qwen3-TTS */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
Qwen3-TTS
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by Alibaba
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
1.7B
|
||||
</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
0.6B
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
High-quality multilingual voice cloning with natural prosody.
|
||||
The only engine with delivery instructions — control tone, pace,
|
||||
and emotion with natural language.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Globe className="h-3 w-3" />
|
||||
10 languages
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<MessageSquare className="h-3 w-3" />
|
||||
Delivery instructions
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* LuxTTS */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">LuxTTS</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by ZipVoice</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Ultra-fast, CPU-friendly voice cloning at 48kHz. Exceeds 150x realtime on CPU with
|
||||
~1GB VRAM. The fastest engine for quick iterations.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Zap className="h-3 w-3" />
|
||||
150x realtime
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
48kHz output
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* Chatterbox */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
Chatterbox
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by Resemble AI
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Production-grade voice cloning with the broadest language
|
||||
support. 23 languages with zero-shot cloning and emotion
|
||||
exaggeration control.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Languages className="h-3 w-3" />
|
||||
23 languages
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Qwen CustomVoice */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">Qwen CustomVoice</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by Alibaba</span>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
1.7B
|
||||
</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
0.6B
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Nine premium preset speakers with natural-language style control. Tell the model how
|
||||
to deliver — "speak slowly with warmth", "authoritative and clear" — and it adapts
|
||||
tone, emotion, and pace.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<SlidersHorizontal className="h-3 w-3" />
|
||||
Instruct control
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Globe className="h-3 w-3" />
|
||||
10 languages
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
9 preset voices
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* Chatterbox Turbo */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
Chatterbox Turbo
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by Resemble AI
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
350M
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Lightweight and fast. Supports paralinguistic tags — embed
|
||||
[laugh], [sigh], [gasp] and more directly in your text for
|
||||
expressive, natural speech.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Zap className="h-3 w-3" />
|
||||
350M params
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<MessageSquare className="h-3 w-3" />
|
||||
[laugh] [sigh] tags
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* HumeAI TADA */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">TADA</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by Hume AI</span>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
3B
|
||||
</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
1B
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Speech-language model with text-acoustic dual alignment. Built for long-form
|
||||
generation — produces 700s+ of coherent audio without drift. Multilingual at 3B,
|
||||
English-focused at 1B.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Globe className="h-3 w-3" />
|
||||
10 languages
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
Long-form coherent
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* LuxTTS */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
LuxTTS
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by ZipVoice
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Ultra-fast, CPU-friendly voice cloning at 48kHz. Exceeds 150x
|
||||
realtime on CPU with ~1GB VRAM. The fastest engine for quick
|
||||
iterations.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Zap className="h-3 w-3" />
|
||||
150x realtime
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
48kHz output
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Kokoro 82M */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">Kokoro</h3>
|
||||
<span className="text-xs text-muted-foreground/60">by hexgrad · Apache 2.0</span>
|
||||
</div>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
82M
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Tiny 82M-parameter TTS that runs at CPU realtime with negligible VRAM. Pre-built
|
||||
voice styles instead of cloning — pick a voice, type, generate. Smallest footprint
|
||||
of any engine.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Zap className="h-3 w-3" />
|
||||
CPU realtime
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
Preset voices
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/* Qwen CustomVoice */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
Qwen CustomVoice
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by Alibaba
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
1.7B
|
||||
</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
0.6B
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Nine premium preset speakers with natural-language style
|
||||
control. Tell the model how to deliver — "speak slowly with
|
||||
warmth", "authoritative and clear" — and it adapts tone,
|
||||
emotion, and pace.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<SlidersHorizontal className="h-3 w-3" />
|
||||
Instruct control
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Globe className="h-3 w-3" />
|
||||
10 languages
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
9 preset voices
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Download Section ─────────────────────────────────────── */}
|
||||
<section id="download" className="border-t border-border py-24">
|
||||
<div className="mx-auto max-w-4xl px-6">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-semibold tracking-tight text-foreground md:text-4xl mb-4">
|
||||
Download Voicebox
|
||||
</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Available for macOS, Windows, and Linux. No dependencies required.
|
||||
</p>
|
||||
</div>
|
||||
{/* HumeAI TADA */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
TADA
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by Hume AI
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-1.5">
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
3B
|
||||
</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
1B
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Speech-language model with text-acoustic dual alignment. Built
|
||||
for long-form generation — produces 700s+ of coherent audio
|
||||
without drift. Multilingual at 3B, English-focused at 1B.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Globe className="h-3 w-3" />
|
||||
10 languages
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
Long-form coherent
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-2xl mx-auto">
|
||||
{/* macOS ARM */}
|
||||
<a
|
||||
href={downloadLinks.macArm}
|
||||
download
|
||||
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"
|
||||
>
|
||||
<AppleIcon 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">macOS</div>
|
||||
<div className="text-xs text-muted-foreground">Apple Silicon (ARM)</div>
|
||||
</div>
|
||||
</a>
|
||||
{/* Kokoro 82M */}
|
||||
<div className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-6 transition-colors hover:border-accent/30">
|
||||
<div className="flex items-start justify-between mb-3">
|
||||
<div>
|
||||
<h3 className="text-base font-semibold text-foreground">
|
||||
Kokoro
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground/60">
|
||||
by hexgrad · Apache 2.0
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full border border-border bg-background text-muted-foreground">
|
||||
82M
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4">
|
||||
Tiny 82M-parameter TTS that runs at CPU realtime with negligible
|
||||
VRAM. Pre-built voice styles instead of cloning — pick a voice,
|
||||
type, generate. Smallest footprint of any engine.
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
<Zap className="h-3 w-3" />
|
||||
CPU realtime
|
||||
</span>
|
||||
<span className="flex items-center gap-1 text-[11px] text-muted-foreground/70">
|
||||
Preset voices
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* macOS Intel */}
|
||||
<a
|
||||
href={downloadLinks.macIntel}
|
||||
download
|
||||
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"
|
||||
>
|
||||
<AppleIcon 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">macOS</div>
|
||||
<div className="text-xs text-muted-foreground">Intel (x64)</div>
|
||||
</div>
|
||||
</a>
|
||||
{/* ── Download Section ─────────────────────────────────────── */}
|
||||
<section id="download" className="border-t border-border py-24">
|
||||
<div className="mx-auto max-w-4xl px-6">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-3xl font-semibold tracking-tight text-foreground md:text-4xl mb-4">
|
||||
Download Voicebox
|
||||
</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Available for macOS, Windows, and Linux. No dependencies required.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Windows */}
|
||||
<a
|
||||
href={downloadLinks.windows}
|
||||
download
|
||||
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"
|
||||
>
|
||||
<WindowsIcon 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">Windows</div>
|
||||
<div className="text-xs text-muted-foreground">64-bit (MSI)</div>
|
||||
</div>
|
||||
</a>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3 max-w-2xl mx-auto">
|
||||
{/* macOS ARM */}
|
||||
<a
|
||||
href={downloadLinks.macArm}
|
||||
download
|
||||
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"
|
||||
>
|
||||
<AppleIcon 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">macOS</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Apple Silicon (ARM)
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{/* Linux */}
|
||||
<a
|
||||
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">Build from source</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
{/* macOS Intel */}
|
||||
<a
|
||||
href={downloadLinks.macIntel}
|
||||
download
|
||||
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"
|
||||
>
|
||||
<AppleIcon 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">macOS</div>
|
||||
<div className="text-xs text-muted-foreground">Intel (x64)</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{/* GitHub link */}
|
||||
<div className="mt-6 text-center">
|
||||
<a
|
||||
href={`${GITHUB_REPO}/releases`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
View all releases on GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/* Windows */}
|
||||
<a
|
||||
href={downloadLinks.windows}
|
||||
download
|
||||
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"
|
||||
>
|
||||
<WindowsIcon 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">Windows</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
64-bit (MSI)
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
{/* ── Footer ───────────────────────────────────────────────── */}
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
{/* Linux */}
|
||||
<a
|
||||
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">
|
||||
Build from source
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{/* GitHub link */}
|
||||
<div className="mt-6 text-center">
|
||||
<a
|
||||
href={`${GITHUB_REPO}/releases`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
|
||||
>
|
||||
<Github className="h-4 w-4" />
|
||||
View all releases on GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ── Footer ───────────────────────────────────────────────── */}
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
"use client";
|
||||
|
||||
import {AppWindow, Code2, Gamepad2, Terminal, Wrench} from "lucide-react";
|
||||
|
||||
type Endpoint = {
|
||||
method: "POST" | "GET" | "DELETE" | "PATCH";
|
||||
path: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
const ENDPOINTS: Endpoint[] = [
|
||||
{method: "POST", path: "/generate", label: "Generate speech"},
|
||||
{method: "POST", path: "/generate/{id}/cancel", label: "Cancel a generation"},
|
||||
{method: "GET", path: "/profiles", label: "List voice profiles"},
|
||||
{method: "POST", path: "/profiles", label: "Create a new profile"},
|
||||
{method: "GET", path: "/models/status", label: "Model catalog & state"},
|
||||
{method: "GET", path: "/history", label: "Past generations"},
|
||||
{method: "GET", path: "/health", label: "Server health"},
|
||||
];
|
||||
|
||||
const METHOD_STYLES: Record<Endpoint["method"], string> = {
|
||||
POST: "bg-accent/10 text-accent border-accent/20",
|
||||
GET: "bg-muted text-muted-foreground border-border",
|
||||
DELETE: "bg-red-500/10 text-red-400 border-red-500/20",
|
||||
PATCH: "bg-blue-500/10 text-blue-400 border-blue-500/20",
|
||||
};
|
||||
|
||||
const CURL_SNIPPET = `curl -X POST http://127.0.0.1:17493/generate \\
|
||||
-H "Content-Type: application/json" \\
|
||||
-d '{
|
||||
"text": "Welcome to the game, player one.",
|
||||
"profile_id": "morgan-freeman",
|
||||
"engine": "qwen",
|
||||
"instruct": "warm, slow, cinematic"
|
||||
}' \\
|
||||
--output line.wav`;
|
||||
|
||||
const USE_CASES = [
|
||||
{
|
||||
icon: Gamepad2,
|
||||
title: "Games",
|
||||
description:
|
||||
"Generate NPC dialogue on the fly, localize characters into new languages, or ship expressive voice lines without a studio.",
|
||||
},
|
||||
{
|
||||
icon: AppWindow,
|
||||
title: "Apps & agents",
|
||||
description:
|
||||
"Give your app or AI agent a voice. Real-time narration, accessibility readouts, voice replies — all running on the user's machine.",
|
||||
},
|
||||
{
|
||||
icon: Wrench,
|
||||
title: "Scripts & tools",
|
||||
description:
|
||||
"Batch-generate audiobook chapters, automate podcast intros, or wire Voicebox into your Stream Deck. It's just a localhost URL.",
|
||||
},
|
||||
];
|
||||
|
||||
export function ApiSection() {
|
||||
return (
|
||||
<section id="api" className="border-t border-border py-24">
|
||||
<div className="mx-auto max-w-6xl px-6">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-14">
|
||||
<div className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-card/40 backdrop-blur-sm px-3 py-1 mb-4">
|
||||
<Code2 className="h-3 w-3 text-accent" />
|
||||
<span className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Built-in REST API
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-semibold tracking-tight text-foreground md:text-4xl mb-4">
|
||||
Your local voice API
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Every engine you download becomes a REST endpoint on your machine.
|
||||
Build apps, games, and voice tools with full programmatic control —
|
||||
no API keys, no rate limits, no per-character fees.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Main panel: endpoints + code snippet */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-5 gap-5 mb-14">
|
||||
{/* Endpoint reference */}
|
||||
<div className="lg:col-span-3 rounded-xl border border-border bg-card/60 backdrop-blur-sm overflow-hidden">
|
||||
<div className="flex items-center justify-between px-5 py-3 border-b border-border/60 bg-card/40">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex gap-1">
|
||||
<div className="h-2 w-2 rounded-full bg-muted-foreground/30" />
|
||||
<div className="h-2 w-2 rounded-full bg-muted-foreground/30" />
|
||||
<div className="h-2 w-2 rounded-full bg-muted-foreground/30" />
|
||||
</div>
|
||||
<span className="text-xs font-medium text-foreground ml-2">
|
||||
API Reference
|
||||
</span>
|
||||
</div>
|
||||
<code className="text-[10px] bg-background border border-border px-1.5 py-0.5 rounded font-mono text-muted-foreground">
|
||||
http://127.0.0.1:17493
|
||||
</code>
|
||||
</div>
|
||||
<div className="px-5 py-4 space-y-1">
|
||||
{ENDPOINTS.map((ep) => (
|
||||
<div
|
||||
key={`${ep.method}-${ep.path}`}
|
||||
className="flex items-center gap-3 py-1.5 group"
|
||||
>
|
||||
<span
|
||||
className={`text-[10px] font-mono font-semibold w-12 text-center rounded px-1 py-0.5 border ${METHOD_STYLES[ep.method]}`}
|
||||
>
|
||||
{ep.method}
|
||||
</span>
|
||||
<code className="text-xs font-mono text-foreground/90">
|
||||
{ep.path}
|
||||
</code>
|
||||
<span className="text-xs text-muted-foreground/60 ml-auto">
|
||||
{ep.label}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="border-t border-border/60 px-5 py-3 bg-card/40">
|
||||
<a
|
||||
href="http://127.0.0.1:17493/docs"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs text-accent hover:underline"
|
||||
>
|
||||
See the full OpenAPI reference at{" "}
|
||||
<code className="font-mono">/docs</code> when Voicebox is running
|
||||
→
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Code snippet */}
|
||||
<div className="lg:col-span-2 rounded-xl border border-border bg-card/60 backdrop-blur-sm overflow-hidden flex flex-col">
|
||||
<div className="flex items-center gap-2 px-4 py-3 border-b border-border/60 bg-card/40">
|
||||
<Terminal className="h-3.5 w-3.5 text-muted-foreground" />
|
||||
<span className="text-xs font-medium text-foreground">
|
||||
Generate a line
|
||||
</span>
|
||||
<span className="ml-auto text-[10px] text-muted-foreground/50 font-mono">
|
||||
curl
|
||||
</span>
|
||||
</div>
|
||||
<pre className="flex-1 p-4 text-[11px] font-mono text-muted-foreground/90 leading-relaxed overflow-x-auto whitespace-pre">
|
||||
<code>{CURL_SNIPPET}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Use cases */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
{USE_CASES.map((uc) => {
|
||||
const Icon = uc.icon;
|
||||
return (
|
||||
<div
|
||||
key={uc.title}
|
||||
className="rounded-xl border border-border bg-card/60 backdrop-blur-sm p-5 transition-colors hover:border-accent/30"
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Icon className="h-4 w-4 text-accent" />
|
||||
<h3 className="text-[15px] font-medium text-foreground">
|
||||
{uc.title}
|
||||
</h3>
|
||||
</div>
|
||||
<p className="text-sm leading-relaxed text-muted-foreground">
|
||||
{uc.description}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Bottom bar: key selling points */}
|
||||
<div className="mt-10 flex flex-wrap items-center justify-center gap-x-8 gap-y-2 text-xs text-muted-foreground">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-accent" />
|
||||
No API keys
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-accent" />
|
||||
No rate limits
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-accent" />
|
||||
No per-character fees
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-accent" />
|
||||
Works offline
|
||||
</span>
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-accent" />
|
||||
Your audio, your machine
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -59,6 +59,12 @@ export function Navbar() {
|
||||
>
|
||||
About
|
||||
</a>
|
||||
<a
|
||||
href="#api"
|
||||
className="rounded-md px-3 py-1.5 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
|
||||
>
|
||||
API
|
||||
</a>
|
||||
<a
|
||||
href="#download"
|
||||
className="rounded-md px-3 py-1.5 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground"
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
"use client";
|
||||
|
||||
import {Play, Youtube} from "lucide-react";
|
||||
|
||||
type Tutorial = {
|
||||
id: string;
|
||||
title: string;
|
||||
author: string;
|
||||
thumbnail: string;
|
||||
};
|
||||
|
||||
const TUTORIALS: (Tutorial | null)[] = [
|
||||
{
|
||||
id: "sisnzgc73zc",
|
||||
title: "Free AI Voice Generator on Your PC (Clones Any Voice)",
|
||||
author: "Kevin Stratvert",
|
||||
thumbnail: "/tutorials/sisnzgc73zc.jpg",
|
||||
},
|
||||
{
|
||||
id: "woQe90k7g3c",
|
||||
title: "NEW Voicebox DESTROYS ElevenLabs?",
|
||||
author: "Julian Goldie SEO",
|
||||
thumbnail: "/tutorials/woQe90k7g3c.jpg",
|
||||
},
|
||||
{
|
||||
id: "kqxqjRsdD5E",
|
||||
title: "This Open-Source TTS App Sounds Scary Good (And It's Free)",
|
||||
author: "Dave Swift",
|
||||
thumbnail: "/tutorials/kqxqjRsdD5E.jpg",
|
||||
},
|
||||
];
|
||||
|
||||
function TutorialCard({tutorial}: {tutorial: Tutorial}) {
|
||||
return (
|
||||
<a
|
||||
href={`https://www.youtube.com/watch?v=${tutorial.id}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group rounded-xl border border-border bg-card/60 backdrop-blur-sm overflow-hidden transition-all hover:border-accent/30 hover:bg-card"
|
||||
>
|
||||
<div className="relative aspect-video overflow-hidden bg-muted">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img
|
||||
src={tutorial.thumbnail}
|
||||
alt={tutorial.title}
|
||||
className="h-full w-full object-cover transition-transform duration-500 group-hover:scale-105"
|
||||
/>
|
||||
{/* Gradient overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-black/0 to-black/0" />
|
||||
{/* Play button overlay */}
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<div className="flex h-14 w-14 items-center justify-center rounded-full bg-black/50 backdrop-blur-md border border-white/20 transition-all group-hover:scale-110 group-hover:bg-accent/90 group-hover:border-accent">
|
||||
<Play className="h-5 w-5 text-white fill-white ml-0.5" />
|
||||
</div>
|
||||
</div>
|
||||
{/* YouTube badge */}
|
||||
<div className="absolute top-3 right-3 flex items-center gap-1 rounded bg-black/60 backdrop-blur-sm px-2 py-1">
|
||||
<Youtube className="h-3 w-3 text-white" />
|
||||
<span className="text-[10px] font-medium text-white uppercase tracking-wider">
|
||||
YouTube
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<h3 className="text-sm font-medium text-foreground line-clamp-2 leading-snug mb-1.5 group-hover:text-accent transition-colors">
|
||||
{tutorial.title}
|
||||
</h3>
|
||||
<p className="text-xs text-muted-foreground">{tutorial.author}</p>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
function TutorialPlaceholder() {
|
||||
return (
|
||||
<div className="rounded-xl border border-dashed border-border/60 bg-card/30 backdrop-blur-sm overflow-hidden">
|
||||
<div className="relative aspect-video overflow-hidden bg-gradient-to-br from-card via-muted/20 to-card">
|
||||
<div className="absolute inset-0 flex items-center justify-center">
|
||||
<div className="flex h-14 w-14 items-center justify-center rounded-full border border-border/40 bg-card/40">
|
||||
<Play className="h-5 w-5 text-muted-foreground/40 fill-muted-foreground/40 ml-0.5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="h-3 w-3/4 rounded bg-muted-foreground/10 mb-2" />
|
||||
<div className="h-2.5 w-1/3 rounded bg-muted-foreground/10" />
|
||||
<p className="text-[11px] text-muted-foreground/50 mt-3 uppercase tracking-wider">
|
||||
Coming soon
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TutorialsSection() {
|
||||
return (
|
||||
<section id="tutorials" className="border-t border-border py-24">
|
||||
<div className="mx-auto max-w-6xl px-6">
|
||||
<div className="text-center mb-14">
|
||||
<div className="inline-flex items-center gap-2 rounded-full border border-border/60 bg-card/40 backdrop-blur-sm px-3 py-1 mb-4">
|
||||
<Youtube className="h-3 w-3 text-accent" />
|
||||
<span className="text-[11px] font-medium uppercase tracking-wider text-muted-foreground">
|
||||
Video tutorials
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-semibold tracking-tight text-foreground md:text-4xl mb-4">
|
||||
Learn by watching
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
Walkthroughs from the community covering setup, voice cloning, and
|
||||
production workflows.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-5">
|
||||
{TUTORIALS.map((tutorial, i) =>
|
||||
tutorial ? (
|
||||
<TutorialCard key={tutorial.id} tutorial={tutorial} />
|
||||
) : (
|
||||
<TutorialPlaceholder key={`placeholder-${i}`} />
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user