feat: implement Phase 2 - Web Audio API engine and waveform visualization

Phase 2 Complete Features:
- Web Audio API context management with browser compatibility
- Audio file upload with drag-and-drop support
- Audio decoding for multiple formats (WAV, MP3, OGG, FLAC, AAC, M4A)
- AudioPlayer class with full playback control
- Waveform visualization using Canvas API
- Real-time waveform rendering with progress indicator
- Playback controls (play, pause, stop, seek)
- Volume control with mute/unmute
- Timeline scrubbing
- Audio file information display

Components:
- AudioEditor: Main editor container
- FileUpload: Drag-and-drop file upload component
- AudioInfo: Display audio file metadata
- Waveform: Canvas-based waveform visualization
- PlaybackControls: Transport controls with volume slider

Audio Engine:
- lib/audio/context.ts: AudioContext management
- lib/audio/decoder.ts: Audio file decoding utilities
- lib/audio/player.ts: AudioPlayer class for playback
- lib/waveform/peaks.ts: Waveform peak generation

Hooks:
- useAudioPlayer: Complete audio player state management

Types:
- types/audio.ts: TypeScript definitions for audio types

Features Working:
✓ Load audio files via drag-and-drop or file picker
✓ Display waveform with real-time progress
✓ Play/pause/stop controls
✓ Seek by clicking on waveform or using timeline slider
✓ Volume control with visual feedback
✓ Audio file metadata display (duration, sample rate, channels)
✓ Toast notifications for user feedback
✓ SSR-safe audio context initialization
✓ Dark/light theme support

Tech Stack:
- Web Audio API for playback
- Canvas API for waveform rendering
- React 19 hooks for state management
- TypeScript for type safety

Build verified and working ✓

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-17 15:32:00 +01:00
parent 45b73e148b
commit ebfb4d3fff
12 changed files with 1313 additions and 103 deletions

View File

@@ -4,21 +4,21 @@ import * as React from 'react';
import { Music, Settings } from 'lucide-react';
import { ThemeToggle } from '@/components/layout/ThemeToggle';
import { Button } from '@/components/ui/Button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/Card';
import { ToastProvider } from '@/components/ui/Toast';
import { AudioEditor } from '@/components/editor/AudioEditor';
export default function Home() {
return (
<ToastProvider>
<div className="min-h-screen bg-background">
{/* Header */}
<header className="border-b border-border">
<header className="border-b border-border sticky top-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 z-50">
<div className="container mx-auto px-3 sm:px-4 py-3 sm:py-4 flex items-center justify-between gap-2">
<div className="min-w-0 flex-1 flex items-center gap-3">
<Music className="h-6 w-6 text-primary" />
<div>
<Music className="h-6 w-6 text-primary flex-shrink-0" />
<div className="min-w-0">
<h1 className="text-xl sm:text-2xl font-bold text-foreground">Audio UI</h1>
<p className="text-xs sm:text-sm text-muted-foreground">
<p className="text-xs sm:text-sm text-muted-foreground truncate">
Professional audio editing in your browser
</p>
</div>
@@ -37,108 +37,14 @@ export default function Home() {
</header>
{/* Main content */}
<main className="container mx-auto px-3 sm:px-4 py-6 sm:py-8 md:py-16">
<div className="max-w-4xl mx-auto space-y-8">
{/* Welcome Card */}
<Card>
<CardHeader>
<CardTitle>Welcome to Audio UI</CardTitle>
<CardDescription>
A sophisticated browser-only audio editor built with Next.js 16 and Web Audio API
</CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<p className="text-sm text-muted-foreground">
This project is currently in development. The following features are planned:
</p>
<ul className="space-y-2 text-sm">
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Multi-track audio editing with professional mixer</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Advanced effects: EQ, compression, reverb, delay, and more</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Waveform visualization with zoom and scroll</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Audio recording from microphone</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Automation lanes for parameters</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Export to WAV, MP3, OGG, and FLAC</span>
</li>
<li className="flex items-start gap-2">
<span className="text-primary"></span>
<span>Project save/load with IndexedDB</span>
</li>
</ul>
</div>
</CardContent>
</Card>
{/* Tech Stack Card */}
<Card>
<CardHeader>
<CardTitle>Technology Stack</CardTitle>
<CardDescription>
Built with modern web technologies
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 text-sm">
<div>
<h4 className="font-semibold mb-2">Frontend</h4>
<ul className="space-y-1 text-muted-foreground">
<li> Next.js 16 with React 19</li>
<li> TypeScript 5</li>
<li> Tailwind CSS 4</li>
<li> Lucide React Icons</li>
</ul>
</div>
<div>
<h4 className="font-semibold mb-2">Audio</h4>
<ul className="space-y-1 text-muted-foreground">
<li> Web Audio API</li>
<li> Canvas API</li>
<li> MediaRecorder API</li>
<li> AudioWorklets</li>
</ul>
</div>
</div>
</CardContent>
</Card>
{/* Privacy Card */}
<Card>
<CardHeader>
<CardTitle>Privacy First</CardTitle>
<CardDescription>
Your audio never leaves your device
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">
All audio processing happens locally in your browser using the Web Audio API.
No files are uploaded to any server. Your projects are saved in your browser's
IndexedDB storage, giving you complete control over your data.
</p>
</CardContent>
</Card>
<main className="container mx-auto px-3 sm:px-4 py-6 sm:py-8">
<div className="max-w-6xl mx-auto">
<AudioEditor />
</div>
</main>
{/* Footer */}
<footer className="border-t border-border mt-8 sm:mt-12 md:mt-16">
<footer className="border-t border-border mt-8 sm:mt-12">
<div className="container mx-auto px-3 sm:px-4 py-6 text-center text-xs sm:text-sm text-muted-foreground">
<p>
Powered by{' '}