<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>audium — terminal music player</title>
<meta name="description" content="A keyboard-driven music player that lives in your terminal. No Electron. No cloud. Just audio." />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400&family=Instrument+Serif:ital@0;1&display=swap" rel="stylesheet" />
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
:root {
--bg: #0e0e0e;
--surface: #161616;
--border: #242424;
--accent: #64b4ff;
--text: #f0f0f0;
--muted: #555;
--dimmed: #999;
--mono: 'DM Mono', monospace;
--serif: 'Instrument Serif', Georgia, serif;
--radius: 4px;
--max: 900px;
}
body { background: var(--bg); color: var(--text); font-family: var(--mono); font-size: 14px; line-height: 1.7; -webkit-font-smoothing: antialiased; overflow-x: hidden; }
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
body::before { content:''; position:fixed; inset:0; background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='1'/%3E%3C/svg%3E"); opacity:0.025; pointer-events:none; z-index:1000; }
.wrap { max-width: var(--max); margin: 0 auto; padding: 0 32px; }
nav { position:fixed; top:0; left:0; right:0; z-index:100; border-bottom:1px solid var(--border); background:rgba(14,14,14,0.88); backdrop-filter:blur(12px); }
nav .wrap { display:flex; align-items:center; justify-content:space-between; height:52px; }
.nav-logo { font-size:15px; font-weight:500; color:var(--text); letter-spacing:0.04em; }
.nav-logo span { color:var(--accent); }
.nav-links { display:flex; gap:28px; list-style:none; }
.nav-links a { color:var(--dimmed); font-size:12px; letter-spacing:0.06em; text-transform:uppercase; transition:color 0.15s; }
.nav-links a:hover { color:var(--text); text-decoration:none; }
.hero { padding:160px 0 100px; position:relative; }
.hero::after { content:''; position:absolute; inset:0; background:repeating-linear-gradient(to bottom,transparent,transparent 3px,rgba(255,255,255,0.012) 3px,rgba(255,255,255,0.012) 4px); pointer-events:none; }
.hero-eyebrow { font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:var(--accent); margin-bottom:20px; opacity:0; animation:fade-up 0.6s 0.1s forwards; }
.hero h1 { font-family:var(--serif); font-size:clamp(52px,8vw,88px); font-weight:400; line-height:1.0; letter-spacing:-0.02em; color:var(--text); opacity:0; animation:fade-up 0.6s 0.2s forwards; }
.hero h1 em { font-style:italic; color:var(--accent); }
.hero-sub { margin-top:28px; max-width:520px; color:var(--dimmed); font-size:14px; line-height:1.8; opacity:0; animation:fade-up 0.6s 0.35s forwards; }
.hero-actions { display:flex; flex-wrap:wrap; gap:12px; margin-top:44px; opacity:0; animation:fade-up 0.6s 0.5s forwards; }
.btn { display:inline-flex; align-items:center; gap:8px; padding:10px 20px; border-radius:var(--radius); font-family:var(--mono); font-size:13px; font-weight:500; cursor:pointer; border:1px solid transparent; transition:all 0.15s; }
.btn-primary { background:var(--accent); color:#000; }
.btn-primary:hover { background:#90caff; text-decoration:none; }
.btn-ghost { background:transparent; color:var(--dimmed); border-color:var(--border); }
.btn-ghost:hover { color:var(--text); border-color:var(--dimmed); text-decoration:none; }
.terminal-wrap { margin-top:72px; opacity:0; animation:fade-up 0.7s 0.65s forwards; }
.terminal { background:var(--surface); border:1px solid var(--border); border-radius:8px; overflow:hidden; box-shadow:0 40px 80px rgba(0,0,0,0.5); }
.term-bar { display:flex; align-items:center; gap:7px; padding:12px 16px; border-bottom:1px solid var(--border); background:#111; }
.dot { width:11px; height:11px; border-radius:50%; }
.dot-r { background:#ff5f57; } .dot-y { background:#febc2e; } .dot-g { background:#28c840; }
.term-title { flex:1; text-align:center; color:var(--muted); font-size:11px; letter-spacing:0.04em; }
.section { padding:80px 0; border-top:1px solid var(--border); }
.section-label { font-size:11px; letter-spacing:0.14em; text-transform:uppercase; color:var(--muted); margin-bottom:12px; }
.section h2 { font-family:var(--serif); font-size:clamp(28px,4vw,42px); font-weight:400; line-height:1.15; margin-bottom:40px; }
.install-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:16px; }
.install-card { background:var(--surface); border:1px solid var(--border); border-radius:var(--radius); padding:24px; transition:border-color 0.15s; }
.install-card:hover { border-color:var(--accent); }
.install-card-title { font-size:11px; letter-spacing:0.1em; text-transform:uppercase; color:var(--muted); margin-bottom:12px; }
.install-card code { display:block; color:var(--accent); font-size:12.5px; word-break:break-all; }
.install-card .comment { margin-top:8px; color:var(--muted); font-size:11px; }
.features-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:1px; background:var(--border); border:1px solid var(--border); border-radius:var(--radius); overflow:hidden; }
.feature { background:var(--surface); padding:32px 28px; }
.feature-icon { font-size:22px; margin-bottom:14px; display:block; }
.feature h3 { font-size:14px; font-weight:500; color:var(--text); margin-bottom:8px; }
.feature p { color:var(--dimmed); font-size:12.5px; line-height:1.75; }
.keybind-table { width:100%; border-collapse:collapse; }
.keybind-table tr { border-bottom:1px solid var(--border); }
.keybind-table tr:last-child { border-bottom:none; }
.keybind-table td { padding:10px 0; font-size:13px; color:var(--dimmed); }
.keybind-table td:first-child { width:160px; padding-right:24px; }
.keybind-table td:first-child kbd { display:inline-block; background:var(--surface); border:1px solid var(--border); border-radius:3px; padding:2px 8px; font-family:var(--mono); font-size:12px; color:var(--accent); }
.why-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:24px; margin-top:40px; }
.why-item { border-left:2px solid var(--border); padding-left:20px; transition:border-color 0.15s; }
.why-item:hover { border-color:var(--accent); }
.why-item h3 { font-size:13px; font-weight:500; color:var(--text); margin-bottom:6px; }
.why-item p { color:var(--dimmed); font-size:12.5px; line-height:1.75; }
footer { border-top:1px solid var(--border); padding:40px 0; }
footer .wrap { display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:16px; }
footer p { color:var(--muted); font-size:12px; }
.footer-links { display:flex; gap:20px; list-style:none; }
.footer-links a { color:var(--muted); font-size:12px; }
.footer-links a:hover { color:var(--dimmed); }
@keyframes fade-up { from { opacity:0; transform:translateY(16px); } to { opacity:1; transform:translateY(0); } }
@media (max-width:600px) { .wrap { padding:0 20px; } .hero { padding:120px 0 64px; } .nav-links { display:none; } }
</style>
</head>
<body>
<nav>
<div class="wrap">
<span class="nav-logo">aud<span>i</span>um</span>
<ul class="nav-links">
<li><a href="#install">Install</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#why">Why audium</a></li>
<li><a href="#keybinds">Keybinds</a></li>
<li><a href="https://github.com/takashialpha/audium">GitHub</a></li>
<li><a href="https://crates.io/crates/audium">crates.io</a></li>
</ul>
</div>
</nav>
<section class="hero">
<div class="wrap">
<p class="hero-eyebrow">Apache-2.0 — available on crates.io & AUR</p>
<h1>Music that lives<br>in your <em>terminal.</em></h1>
<p class="hero-sub">
audium is a keyboard-driven music player for people who live in the terminal.
No Electron. No cloud sync. No background daemons. No FFmpeg.
Your files, your library, your rules.
</p>
<div class="hero-actions">
<a class="btn btn-primary" href="#install">Get started</a>
<a class="btn btn-ghost" href="https://github.com/takashialpha/audium">View source →</a>
</div>
<div class="terminal-wrap">
<div class="terminal">
<div class="term-bar">
<div class="dot dot-r"></div>
<div class="dot dot-y"></div>
<div class="dot dot-g"></div>
<span class="term-title">audium</span>
</div>
<canvas id="tui" style="display:block;width:100%;background:#161616;border-radius:0 0 8px 8px;"></canvas>
<script>
(function() {
const FONT_SIZE = 12;
const FONT = FONT_SIZE + 'px "DM Mono",monospace';
const PAD_X = 16, PAD_Y = 20, LINE_H = 19;
const A = '#64b4ff', D = '#2e2e2e', M = '#606060', W = '#f0f0f0';
const ROWS = [
[[' audium', A], [' \u2014 terminal music player [?] help [f] file picker [c] playlist [m] menu [q] quit', M]],
[['\u250c' + '\u2500'.repeat(25) + '\u252c' + '\u2500'.repeat(54) + '\u2510', D]],
[['│', D], [' Playlists ', A], ['│', D], [' All Tracks ', A], ['│', D]],
[['│ │', D], [' # Title ', M], ['│', D]],
[['│', D], [' > All Tracks (4) ', A], ['│', D], [' 1 04 - Neon Arpeggio ', M], ['│', D]],
[['│', D], [' Late Night (2) ', M], ['│', D], [' 2 Drift ', M], ['│', D]],
[['│', D], [' Focus (2) ', M], ['│', D], [' > 3 Weightless (feat. Macarena) ', A], ['│', D]],
[['│ │', D], [' 4 The River Calls ', M], ['│', D]],
[['│ │ │', D]],
[['│ \u251c' + '\u2500'.repeat(54) + '\u2524', D]],
[['│ │', D], [' Queue ', A], ['│', D]],
[['│ │', D], [' 1 04 - Neon Arpeggio ', M], ['│', D]],
[['│ │', D], [' 2 Drift ', M], ['│', D]],
[['│ │', D], [' > 3 Weightless (feat. Macarena) ', A], ['│', D]],
[['\u2514' + '\u2500'.repeat(25) + '\u2534' + '\u2500'.repeat(54) + '\u2518', D]],
[['⏸ ', A], ['Weightless (feat. Macarena)', W], [' loop queue', M]],
[['█'.repeat(20), A], ['░'.repeat(39), D], [' 2:14 / 5:02', M]],
];
function draw() {
const canvas = document.getElementById('tui');
const dpr = window.devicePixelRatio || 1;
const cssW = canvas.parentElement.clientWidth;
const cssH = PAD_Y * 2 + LINE_H * ROWS.length;
canvas.style.height = cssH + 'px';
canvas.width = cssW * dpr;
canvas.height = cssH * dpr;
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr);
ctx.font = FONT;
ROWS.forEach((segs, row) => {
let x = PAD_X;
const y = PAD_Y + row * LINE_H;
segs.forEach(([text, colour]) => {
ctx.fillStyle = colour;
ctx.fillText(text, x, y);
x += ctx.measureText(text).width;
});
});
}
if (document.fonts && document.fonts.ready) {
document.fonts.ready.then(draw);
} else {
window.addEventListener('load', draw);
}
window.addEventListener('resize', draw);
})();
</script>
</div>
</div>
</div>
</section>
<section class="section" id="install">
<div class="wrap">
<p class="section-label">Installation</p>
<h2>Pick your platform.</h2>
<div class="install-grid">
<div class="install-card">
<p class="install-card-title">Cargo (all platforms)</p>
<code>cargo install audium</code>
<p class="comment"># requires Rust 1.85+</p>
</div>
<div class="install-card">
<p class="install-card-title">AUR (Arch Linux)</p>
<code>paru -S audium</code>
<p class="comment"># or yay, or manually with makepkg</p>
</div>
</div>
<p style="margin-top:20px;color:var(--muted);font-size:12.5px;">Linux requires ALSA to run and its development headers to build. See the <a href="https://github.com/takashialpha/audium#building-from-source">README</a> for distro-specific instructions. macOS and Windows have no extra dependencies.</p>
</div>
</section>
<section class="section" id="features">
<div class="wrap">
<p class="section-label">Features</p>
<h2>Everything you need.<br><em style="font-style:italic;color:var(--accent);">Nothing you don't.</em></h2>
<div class="features-grid" style="margin-top:40px;">
<div class="feature">
<span class="feature-icon">♪</span>
<h3>Format agnostic</h3>
<p>Plays MP3, FLAC, OGG, WAV, AAC, M4A, Opus, AIFF and more via Symphonia — no FFmpeg required.</p>
</div>
<div class="feature">
<span class="feature-icon">⌨</span>
<h3>Fully keyboard-driven</h3>
<p>Every action is a single keypress. Tab between panels, j/k to navigate, space to play.</p>
</div>
<div class="feature">
<span class="feature-icon">📂</span>
<h3>Built-in file picker</h3>
<p>Browse your filesystem and import audio without ever leaving the app.</p>
</div>
<div class="feature">
<span class="feature-icon">🎨</span>
<h3>Themes</h3>
<p>15 built-in themes — dark, light, nord, gruvbox, catppuccin, rosé pine, dracula, tokyo night, and more. Switch live with instant preview. Transparency support for composited terminals.</p>
</div>
<div class="feature">
<span class="feature-icon">🎵</span>
<h3>Playlists & loop modes</h3>
<p>Create, rename, and delete playlists. Loop a single track or the whole queue — toggle with <code style="color:var(--accent)">l</code>.</p>
</div>
<div class="feature">
<span class="feature-icon">🔊</span>
<h3>Threaded audio</h3>
<p>Playback runs on a dedicated thread. UI interactions will never stutter your music.</p>
</div>
<div class="feature">
<span class="feature-icon">💾</span>
<h3>It's your library</h3>
<p>Stored at <code style="color:var(--accent)">~/.audium/library.json</code> — plain JSON, human-readable, editable by hand. audium doesn't rename your files, doesn't embed metadata, and never phones home.</p>
</div>
</div>
</div>
</section>
<section class="section" id="why">
<div class="wrap">
<p class="section-label">Why audium</p>
<h2>Lighter. Simpler.<br><em style="font-style:italic;color:var(--accent);">Actually yours.</em></h2>
<p style="color:var(--dimmed);font-size:13.5px;max-width:600px;line-height:1.85;">
Alternatives like termusic ship with heavy dependency trees, FFmpeg requirements, daemon processes,
or config formats that take longer to learn than the app itself.
audium takes a different approach.
</p>
<div class="why-grid">
<div class="why-item">
<h3>No FFmpeg, no daemon</h3>
<p>One binary. Zero background processes. Symphonia handles every format natively in-process.</p>
</div>
<div class="why-item">
<h3>Smaller and faster to build</h3>
<p>Fewer dependencies means shorter compile times and a ~3 MB release binary with no runtime surprises.</p>
</div>
<div class="why-item">
<h3>Cleaner UI</h3>
<p>Built on ratatui with a layout designed for daily use — not just feature completeness. Panels, queue, progress bar, volume: everything visible at once.</p>
</div>
<div class="why-item">
<h3>Modern codebase</h3>
<p>Written in Rust edition 2024. No unsafe, no global state, no legacy baggage.</p>
</div>
<div class="why-item">
<h3>Plain data, no lock-in</h3>
<p>Your library is a JSON file you can read, edit, back up, or move between machines freely. audium is a tool, not a platform.</p>
</div>
<div class="why-item">
<h3>System audio, done right</h3>
<p>audium plays through your default system output. Switch devices at the OS level and it follows — no in-app device picker that fights your setup.</p>
</div>
</div>
</div>
</section>
<section class="section" id="keybinds">
<div class="wrap">
<p class="section-label">Keybindings</p>
<h2>Muscle memory<br>over menus.</h2>
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:48px;margin-top:40px;">
<div>
<p style="color:var(--muted);font-size:11px;letter-spacing:0.1em;text-transform:uppercase;margin-bottom:16px;">Playback</p>
<table class="keybind-table">
<tr><td><kbd>Space</kbd></td><td>Play / Pause</td></tr>
<tr><td><kbd>n</kbd></td><td>Next track</td></tr>
<tr><td><kbd>N</kbd></td><td>Previous track</td></tr>
<tr><td><kbd>←</kbd> / <kbd>→</kbd></td><td>Seek backward / forward</td></tr>
<tr><td><kbd>+</kbd> / <kbd>=</kbd></td><td>Volume up</td></tr>
<tr><td><kbd>-</kbd></td><td>Volume down</td></tr>
<tr><td><kbd>l</kbd></td><td>Cycle loop mode</td></tr>
</table>
</div>
<div>
<p style="color:var(--muted);font-size:11px;letter-spacing:0.1em;text-transform:uppercase;margin-bottom:16px;">Navigation</p>
<table class="keybind-table">
<tr><td><kbd>Tab</kbd></td><td>Cycle panel focus</td></tr>
<tr><td><kbd>j</kbd> / <kbd>↓</kbd></td><td>Move down</td></tr>
<tr><td><kbd>k</kbd> / <kbd>↑</kbd></td><td>Move up</td></tr>
<tr><td><kbd>Enter</kbd></td><td>Play selected</td></tr>
<tr><td><kbd>?</kbd></td><td>Help overlay</td></tr>
</table>
</div>
<div>
<p style="color:var(--muted);font-size:11px;letter-spacing:0.1em;text-transform:uppercase;margin-bottom:16px;">Library & Queue</p>
<table class="keybind-table">
<tr><td><kbd>f</kbd></td><td>Open file picker</td></tr>
<tr><td><kbd>a</kbd></td><td>Add to queue</td></tr>
<tr><td><kbd>p</kbd></td><td>Add to playlist</td></tr>
<tr><td><kbd>c</kbd></td><td>New playlist</td></tr>
<tr><td><kbd>z</kbd></td><td>Shuffle playlist into queue</td></tr>
<tr><td><kbd>d</kbd></td><td>Remove</td></tr>
<tr><td><kbd>r</kbd></td><td>Rename</td></tr>
<tr><td><kbd>m</kbd></td><td>Menu</td></tr>
<tr><td><kbd>q</kbd></td><td>Quit</td></tr>
</table>
</div>
</div>
</div>
</section>
<footer>
<div class="wrap">
<p>audium — <a href="https://github.com/takashialpha/audium/blob/main/LICENSE">Apache-2.0</a></p>
<ul class="footer-links">
<li><a href="https://github.com/takashialpha/audium">GitHub</a></li>
<li><a href="https://crates.io/crates/audium">crates.io</a></li>
<li><a href="https://aur.archlinux.org/packages/audium">AUR</a></li>
</ul>
</div>
</footer>
</body>
</html>