|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8" /> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
|
|
<title>ReadingBuddy β’ Reachy Mini</title> |
|
|
<style> |
|
|
:root{ |
|
|
--bg:#0f172a; |
|
|
--card:rgba(255,255,255,.06); |
|
|
--text:#e5e7eb; |
|
|
--muted:#94a3b8; |
|
|
--brand:#818cf8; |
|
|
--success:#22c55e; |
|
|
} |
|
|
*{ box-sizing:border-box; margin:0; } |
|
|
body{ |
|
|
margin:0; |
|
|
font-family: system-ui, -apple-system, sans-serif; |
|
|
color:var(--text); |
|
|
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%); |
|
|
line-height:1.6; |
|
|
padding:40px 20px; |
|
|
} |
|
|
.container{ |
|
|
max-width: 1000px; |
|
|
margin: 0 auto; |
|
|
} |
|
|
.hero{ |
|
|
text-align:center; |
|
|
margin-bottom:50px; |
|
|
} |
|
|
.logo{ |
|
|
font-size:80px; |
|
|
margin-bottom:20px; |
|
|
} |
|
|
h1{ |
|
|
font-size:3rem; |
|
|
margin:0 0 16px; |
|
|
background: linear-gradient(135deg, #818cf8, #22c55e); |
|
|
-webkit-background-clip: text; |
|
|
-webkit-text-fill-color: transparent; |
|
|
background-clip: text; |
|
|
} |
|
|
.tagline{ |
|
|
font-size:1.3rem; |
|
|
color:var(--muted); |
|
|
margin-bottom:32px; |
|
|
} |
|
|
h2{ |
|
|
font-size:1.8rem; |
|
|
margin:40px 0 24px; |
|
|
text-align:center; |
|
|
} |
|
|
.voice-grid{ |
|
|
display:grid; |
|
|
grid-template-columns:repeat(auto-fit, minmax(200px, 1fr)); |
|
|
gap:16px; |
|
|
margin:32px 0; |
|
|
} |
|
|
.voice-card{ |
|
|
position:relative; |
|
|
aspect-ratio: 3/2; |
|
|
border-radius:16px; |
|
|
overflow:hidden; |
|
|
border:3px solid rgba(129,140,248,.3); |
|
|
background-size:cover; |
|
|
background-position:center; |
|
|
display:flex; |
|
|
flex-direction:column; |
|
|
justify-content:flex-end; |
|
|
padding:16px; |
|
|
transition: transform 0.2s, border-color 0.2s; |
|
|
} |
|
|
.voice-card:hover{ |
|
|
transform: translateY(-4px); |
|
|
border-color: rgba(129,140,248,.6); |
|
|
} |
|
|
.voice-card::before{ |
|
|
content:''; |
|
|
position:absolute; |
|
|
inset:0; |
|
|
background: linear-gradient(to top, rgba(0,0,0,.85) 0%, rgba(0,0,0,.3) 60%, transparent 100%); |
|
|
} |
|
|
.voice-card .name{ |
|
|
position:relative; |
|
|
font-size:1.2rem; |
|
|
font-weight:700; |
|
|
margin-bottom:4px; |
|
|
} |
|
|
.voice-card .desc{ |
|
|
position:relative; |
|
|
font-size:0.9rem; |
|
|
color:rgba(255,255,255,.8); |
|
|
} |
|
|
.pills{ |
|
|
display:flex; |
|
|
gap:12px; |
|
|
justify-content:center; |
|
|
flex-wrap:wrap; |
|
|
margin:32px 0; |
|
|
} |
|
|
.pill{ |
|
|
padding:8px 16px; |
|
|
border-radius:999px; |
|
|
background:rgba(129,140,248,.15); |
|
|
border:1px solid rgba(129,140,248,.3); |
|
|
font-size:0.95rem; |
|
|
} |
|
|
.section{ |
|
|
background:var(--card); |
|
|
border:1px solid rgba(255,255,255,.1); |
|
|
border-radius:20px; |
|
|
padding:40px; |
|
|
margin:40px 0; |
|
|
} |
|
|
.section h2{ |
|
|
margin-top:0; |
|
|
text-align:left; |
|
|
} |
|
|
.steps{ |
|
|
display:grid; |
|
|
gap:16px; |
|
|
} |
|
|
.step{ |
|
|
display:flex; |
|
|
gap:16px; |
|
|
align-items:start; |
|
|
} |
|
|
.num{ |
|
|
width:36px; |
|
|
height:36px; |
|
|
border-radius:50%; |
|
|
background:rgba(129,140,248,.2); |
|
|
border:2px solid rgba(129,140,248,.4); |
|
|
display:grid; |
|
|
place-items:center; |
|
|
font-weight:700; |
|
|
flex-shrink:0; |
|
|
} |
|
|
code{ |
|
|
background:rgba(255,255,255,.08); |
|
|
padding:4px 10px; |
|
|
border-radius:8px; |
|
|
font-size:0.9em; |
|
|
word-break:break-all; |
|
|
} |
|
|
.code-block{ |
|
|
background:rgba(0,0,0,.3); |
|
|
border:1px solid rgba(255,255,255,.1); |
|
|
border-radius:12px; |
|
|
padding:16px; |
|
|
margin:16px 0; |
|
|
font-family: monospace; |
|
|
font-size:0.9em; |
|
|
overflow-x:auto; |
|
|
line-height:1.8; |
|
|
white-space:pre-wrap; |
|
|
} |
|
|
.code-block code{ |
|
|
background:transparent; |
|
|
padding:0; |
|
|
} |
|
|
.features{ |
|
|
display:grid; |
|
|
grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); |
|
|
gap:20px; |
|
|
margin:40px 0; |
|
|
} |
|
|
.feature{ |
|
|
background:var(--card); |
|
|
border:1px solid rgba(255,255,255,.1); |
|
|
border-radius:16px; |
|
|
padding:24px; |
|
|
text-align:center; |
|
|
} |
|
|
.feature-icon{ |
|
|
font-size:48px; |
|
|
margin-bottom:12px; |
|
|
} |
|
|
.feature h3{ |
|
|
font-size:1.1rem; |
|
|
margin-bottom:8px; |
|
|
} |
|
|
.feature p{ |
|
|
color:var(--muted); |
|
|
font-size:0.95rem; |
|
|
} |
|
|
.note{ |
|
|
background:rgba(34,197,94,.1); |
|
|
border:1px solid rgba(34,197,94,.3); |
|
|
border-radius:12px; |
|
|
padding:16px; |
|
|
margin:16px 0; |
|
|
color:#d1fae5; |
|
|
} |
|
|
.note strong{ |
|
|
color:#ecfdf5; |
|
|
} |
|
|
.tier-grid{ |
|
|
display:grid; |
|
|
grid-template-columns:repeat(auto-fit, minmax(200px, 1fr)); |
|
|
gap:16px; |
|
|
margin:24px 0; |
|
|
} |
|
|
.tier-card{ |
|
|
background:rgba(0,0,0,.2); |
|
|
border:1px solid rgba(255,255,255,.1); |
|
|
border-radius:16px; |
|
|
padding:20px; |
|
|
text-align:center; |
|
|
} |
|
|
.tier-card .tier-icon{ |
|
|
font-size:36px; |
|
|
margin-bottom:10px; |
|
|
} |
|
|
.tier-card h3{ |
|
|
font-size:1rem; |
|
|
margin-bottom:6px; |
|
|
} |
|
|
.tier-card p{ |
|
|
font-size:0.85rem; |
|
|
color:var(--muted); |
|
|
} |
|
|
.tier-card .tier-badge{ |
|
|
display:inline-block; |
|
|
padding:3px 10px; |
|
|
border-radius:999px; |
|
|
font-size:0.75rem; |
|
|
font-weight:700; |
|
|
margin-bottom:10px; |
|
|
} |
|
|
.badge-default{ background:rgba(34,197,94,.2); color:#86efac; border:1px solid rgba(34,197,94,.3); } |
|
|
.badge-premium{ background:rgba(129,140,248,.2); color:#c7d2fe; border:1px solid rgba(129,140,248,.3); } |
|
|
.badge-fallback{ background:rgba(255,255,255,.1); color:var(--muted); border:1px solid rgba(255,255,255,.1); } |
|
|
footer{ |
|
|
text-align:center; |
|
|
margin-top:60px; |
|
|
padding-top:30px; |
|
|
border-top:1px solid rgba(255,255,255,.1); |
|
|
color:var(--muted); |
|
|
font-size:0.9rem; |
|
|
} |
|
|
a{ color:#c7d2fe; text-decoration:none; } |
|
|
a:hover{ text-decoration:underline; } |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<div class="container"> |
|
|
<div class="hero"> |
|
|
<div class="logo">π€π</div> |
|
|
<h1>ReadingBuddy</h1> |
|
|
<p class="tagline">Your Reachy Mini reads books aloud with character voices</p> |
|
|
|
|
|
<div class="pills"> |
|
|
<span class="pill">πΈ Camera OCR</span> |
|
|
<span class="pill">π 4 Voices</span> |
|
|
<span class="pill">π§ Page Memory</span> |
|
|
<span class="pill">π Story Library</span> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<h2>π Character Voices</h2> |
|
|
<div class="voice-grid"> |
|
|
<div class="voice-card" style="background-image: url('reachy_mini_bookreader/static/voices/techstoryteller.jpg')"> |
|
|
<div class="name">Tech Storyteller</div> |
|
|
<div class="desc">GPU Dad mode</div> |
|
|
</div> |
|
|
<div class="voice-card" style="background-image: url('reachy_mini_bookreader/static/voices/superhero.jpg')"> |
|
|
<div class="name">Superhero</div> |
|
|
<div class="desc">Big energy</div> |
|
|
</div> |
|
|
<div class="voice-card" style="background-image: url('reachy_mini_bookreader/static/voices/princess.jpg')"> |
|
|
<div class="name">Princess</div> |
|
|
<div class="desc">Sweet + bright</div> |
|
|
</div> |
|
|
<div class="voice-card" style="background-image: url('reachy_mini_bookreader/static/voices/robothero.jpg')"> |
|
|
<div class="name">Robot Hero</div> |
|
|
<div class="desc">Strong + brave</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="features"> |
|
|
<div class="feature"> |
|
|
<div class="feature-icon">πΈ</div> |
|
|
<h3>Smart Camera</h3> |
|
|
<p>Capture pages, extract text instantly</p> |
|
|
</div> |
|
|
<div class="feature"> |
|
|
<div class="feature-icon">π</div> |
|
|
<h3>Three-Tier TTS</h3> |
|
|
<p>ElevenLabs β Piper β espeak fallback</p> |
|
|
</div> |
|
|
<div class="feature"> |
|
|
<div class="feature-icon">π§ </div> |
|
|
<h3>Page Memory</h3> |
|
|
<p>Remembers where you left off</p> |
|
|
</div> |
|
|
<div class="feature"> |
|
|
<div class="feature-icon">π</div> |
|
|
<h3>Story Library</h3> |
|
|
<p>Classic tales pre-loaded</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="section"> |
|
|
<h2>π Voice Quality Tiers</h2> |
|
|
<p style="color:var(--muted); margin-bottom:24px; text-align:center;"> |
|
|
ReadingBuddy uses a smart three-tier voice system β great voices out of the box, upgradeable anytime! |
|
|
</p> |
|
|
|
|
|
<div class="tier-grid"> |
|
|
<div class="tier-card"> |
|
|
<div class="tier-icon">π</div> |
|
|
<div class="tier-badge badge-premium">Premium</div> |
|
|
<h3>ElevenLabs</h3> |
|
|
<p>Professional character voices with emotion and expression. Requires API key.</p> |
|
|
</div> |
|
|
<div class="tier-card"> |
|
|
<div class="tier-icon">π₯</div> |
|
|
<div class="tier-badge badge-default">Default β</div> |
|
|
<h3>Piper TTS</h3> |
|
|
<p>Natural-sounding voices, runs locally on your robot. Completely free!</p> |
|
|
</div> |
|
|
<div class="tier-card"> |
|
|
<div class="tier-icon">π₯</div> |
|
|
<div class="tier-badge badge-fallback">Fallback</div> |
|
|
<h3>espeak-ng</h3> |
|
|
<p>Robotic backup voice. Always available, no setup needed.</p> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="note"> |
|
|
<strong>π‘ Out of the box:</strong> You get Piper TTS β natural voices, completely free, no API key needed! |
|
|
Each character has a distinct voice personality. |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="section"> |
|
|
<h2>π Install on Reachy Mini</h2> |
|
|
<div class="steps"> |
|
|
<div class="step"> |
|
|
<div class="num">1</div> |
|
|
<div>Open dashboard at <code>http://REACHY_IP:8000</code></div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">2</div> |
|
|
<div>Click <strong>Install from Hugging Face</strong></div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">3</div> |
|
|
<div>Search <code>reachy_mini_bookreader</code></div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">4</div> |
|
|
<div>Click <strong>Install</strong> β <strong>Run</strong> β <strong>βοΈ</strong></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="section"> |
|
|
<h2>π₯ Setup Piper Voices (One-Time)</h2> |
|
|
<p style="color:var(--muted); margin-bottom:20px;"> |
|
|
After installing, download the voice models once via SSH: |
|
|
</p> |
|
|
|
|
|
<div class="steps"> |
|
|
<div class="step"> |
|
|
<div class="num">1</div> |
|
|
<div>SSH into your Reachy Mini: |
|
|
<div class="code-block"><code>ssh pollen@YOUR_REACHY_IP</code></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">2</div> |
|
|
<div>Create the voices folder: |
|
|
<div class="code-block"><code>mkdir -p ~/.local/share/piper-voices |
|
|
cd ~/.local/share/piper-voices</code></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">3</div> |
|
|
<div>Download all 4 character voices: |
|
|
<div class="code-block"><code>wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/arctic/medium/en_US-arctic-medium.onnx |
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/arctic/medium/en_US-arctic-medium.onnx.json |
|
|
|
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/danny/low/en_US-danny-low.onnx |
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/danny/low/en_US-danny-low.onnx.json |
|
|
|
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/amy/medium/en_US-amy-medium.onnx |
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/amy/medium/en_US-amy-medium.onnx.json |
|
|
|
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/john/medium/en_US-john-medium.onnx |
|
|
wget https://huggingface.co/rhasspy/piper-voices/resolve/v1.0.0/en/en_US/john/medium/en_US-john-medium.onnx.json</code></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">4</div> |
|
|
<div>Restart the app and enjoy natural voices! π€</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="section"> |
|
|
<h2>π Enable Premium ElevenLabs Voices (Optional)</h2> |
|
|
<p style="color:var(--muted); margin-bottom:20px;"> |
|
|
For the absolute best quality with theatrical character voices: |
|
|
</p> |
|
|
|
|
|
<div class="steps"> |
|
|
<div class="step"> |
|
|
<div class="num">1</div> |
|
|
<div>Get API key from <a href="https://elevenlabs.io" target="_blank">elevenlabs.io</a></div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">2</div> |
|
|
<div>On your Reachy Mini, create a <code>.env</code> file: |
|
|
<div class="code-block"><code>cd ~/.local/share/reachy-mini/apps/reachy_mini_bookreader |
|
|
nano .env</code></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">3</div> |
|
|
<div>Add these credentials (using our recommended voices): |
|
|
<div class="code-block"><code>ELEVENLABS_API_KEY=your_api_key_here |
|
|
ELEVEN_VOICE_TECH=9lv4qqEb8CqLgosI5Due |
|
|
ELEVEN_VOICE_SUPERHERO=248nvfaZe8BXhKntjmpp |
|
|
ELEVEN_VOICE_PRINCESS=mHX7OoPk2G45VMAuinIt |
|
|
ELEVEN_VOICE_ROBOTHERO=Q8ZbQAANLFvLw8uPBR8d</code></div> |
|
|
</div> |
|
|
</div> |
|
|
<div class="step"> |
|
|
<div class="num">4</div> |
|
|
<div>Save (<code>Ctrl+X</code>, <code>Y</code>, <code>Enter</code>) and restart the app</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="note"> |
|
|
<strong>π‘ Note:</strong> These are our curated voice IDs that work great for each character! |
|
|
You can also choose your own voices from the <a href="https://elevenlabs.io/app/voice-library" target="_blank" style="color:#a7f3d0;">ElevenLabs Voice Library</a>. |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<footer> |
|
|
<p>Requires <a href="https://www.pollen-robotics.com/reachy-mini/">Reachy Mini</a> robot hardware</p> |
|
|
<p style="margin-top:8px;">Made with β€οΈ for educational robotics</p> |
|
|
</footer> |
|
|
</div> |
|
|
</body> |
|
|
</html> |