- Create /api/audio endpoint for upload/get/delete operations - Add AudioPlayer component with custom controls - Add AudioUpload component for admin interface - Update admin page with audio upload UI and indicators - Update main blog page to use new AudioPlayer component - Add database migration for audio_url and audio_duration columns - Add comprehensive documentation in docs/MP3_AUDIO_FEATURE.md - Update README with audio feature overview
200 lines
5.1 KiB
Markdown
200 lines
5.1 KiB
Markdown
# MP3 Audio Hosting Feature
|
|
|
|
This document describes the MP3 audio hosting functionality added to the blog-backup project.
|
|
|
|
## Overview
|
|
|
|
The blog now supports uploading and hosting MP3 audio files for individual blog posts. This allows you to:
|
|
- Upload custom MP3 files to any blog post
|
|
- Attach audio commentary, interviews, or supplementary content
|
|
- Automatically estimate audio duration
|
|
- Play audio directly in the blog post with a custom audio player
|
|
|
|
## Features
|
|
|
|
### 1. Supabase Storage Integration
|
|
- **Bucket**: `podcast-audio` (shared with podcast feature)
|
|
- **File Size Limit**: 50MB per file
|
|
- **Supported Formats**: MP3, WAV, AIFF
|
|
- **Public Access**: Files are publicly readable via signed URLs
|
|
|
|
### 2. API Endpoints
|
|
|
|
#### `GET /api/audio?postId={id}`
|
|
Retrieves audio information for a blog post.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"hasAudio": true,
|
|
"audioUrl": "https://...",
|
|
"duration": 180
|
|
}
|
|
```
|
|
|
|
#### `POST /api/audio`
|
|
Uploads an audio file and associates it with a blog post.
|
|
|
|
**Request:**
|
|
- Content-Type: `multipart/form-data`
|
|
- Authorization: `Bearer {token}`
|
|
- Body: `file` (audio file), `postId` (string)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"url": "https://...",
|
|
"path": "upload-2026-02-25-123456789-1740523456789.mp3",
|
|
"size": 5242880,
|
|
"estimatedDuration": 327
|
|
}
|
|
```
|
|
|
|
#### `DELETE /api/audio`
|
|
Removes audio from a blog post and deletes the file from storage.
|
|
|
|
**Request:**
|
|
- Authorization: `Bearer {token}`
|
|
- Body: `{ "postId": "..." }`
|
|
|
|
### 3. Database Schema
|
|
|
|
The `blog_messages` table now includes:
|
|
- `audio_url` (text, nullable) - Public URL to the audio file
|
|
- `audio_duration` (integer, nullable) - Estimated duration in seconds
|
|
|
|
### 4. Components
|
|
|
|
#### `AudioPlayer`
|
|
Located in `src/components/AudioPlayer.tsx`
|
|
|
|
A custom audio player with:
|
|
- Play/pause controls
|
|
- Progress bar with seek functionality
|
|
- Volume control with mute toggle
|
|
- Time display (current / total)
|
|
- Dark mode support
|
|
|
|
**Usage:**
|
|
```tsx
|
|
import { AudioPlayer } from "@/components/AudioPlayer";
|
|
|
|
<AudioPlayer
|
|
url="https://..."
|
|
duration={180} // optional
|
|
/>
|
|
```
|
|
|
|
#### `CompactAudioPlayer`
|
|
A minimal version for inline use:
|
|
```tsx
|
|
import { CompactAudioPlayer } from "@/components/AudioPlayer";
|
|
|
|
<CompactAudioPlayer url="https://..." />
|
|
```
|
|
|
|
#### `AudioUpload`
|
|
Located in `src/components/AudioUpload.tsx`
|
|
|
|
Upload component for the admin interface with:
|
|
- Drag-and-drop file selection
|
|
- File type validation
|
|
- File size validation (50MB max)
|
|
- Upload progress indicator
|
|
- Current audio preview
|
|
- Remove/delete functionality
|
|
|
|
**Usage:**
|
|
```tsx
|
|
import { AudioUpload } from "@/components/AudioUpload";
|
|
|
|
<AudioUpload
|
|
postId="123"
|
|
existingAudioUrl={post.audio_url}
|
|
onUploadSuccess={(url, duration) => {}}
|
|
onDeleteSuccess={() => {}}
|
|
/>
|
|
```
|
|
|
|
### 5. Admin Interface
|
|
|
|
The admin dashboard (`/admin`) now includes:
|
|
- Audio indicator badge on posts with audio
|
|
- Audio upload section in the edit modal
|
|
- Preview player for uploaded audio
|
|
- Remove audio functionality
|
|
|
|
## Usage Guide
|
|
|
|
### Adding Audio to a Post
|
|
|
|
1. Go to `/admin` and log in
|
|
2. Find the post you want to add audio to
|
|
3. Click "Edit"
|
|
4. Scroll to the "Audio Attachment" section
|
|
5. Click to upload or drag and drop an MP3 file
|
|
6. Wait for upload to complete
|
|
7. Save changes
|
|
|
|
### Removing Audio from a Post
|
|
|
|
1. Go to `/admin` and log in
|
|
2. Edit the post with audio
|
|
3. In the "Audio Attachment" section, click "Remove"
|
|
4. Confirm deletion
|
|
5. Save changes
|
|
|
|
### Viewing Audio on the Blog
|
|
|
|
- Posts with audio display a 🎧 icon in the admin list
|
|
- On the public blog, audio appears at the top of the post
|
|
- The custom audio player provides full playback controls
|
|
|
|
## Technical Details
|
|
|
|
### File Naming
|
|
Uploaded files are named with the pattern:
|
|
```
|
|
upload-{date}-{postId}-{timestamp}.{ext}
|
|
```
|
|
|
|
Example: `upload-2026-02-25-123456789-1740523456789.mp3`
|
|
|
|
### Duration Estimation
|
|
Since extracting exact MP3 duration server-side requires additional libraries, we estimate duration based on file size:
|
|
- Assumption: 128 kbps bitrate (standard for MP3)
|
|
- Formula: `duration = (fileSize / (128 * 1024 / 8)) * 60`
|
|
|
|
The browser will display the actual duration once the audio file loads.
|
|
|
|
### Storage Costs
|
|
- Supabase free tier includes 1GB storage
|
|
- At 128kbps, 1GB = ~17.5 hours of audio
|
|
- Podcast audio and uploaded MP3s share the same bucket
|
|
|
|
## Future Enhancements
|
|
|
|
Potential improvements:
|
|
1. **Exact Duration Extraction**: Use `music-metadata` library for accurate duration
|
|
2. **Multiple Audio Files**: Support for multiple audio tracks per post
|
|
3. **Audio Transcription**: Auto-generate transcripts from audio
|
|
4. **Waveform Visualization**: Display audio waveforms
|
|
5. **Download Button**: Allow users to download audio files
|
|
|
|
## Troubleshooting
|
|
|
|
### Upload fails
|
|
- Check that file is under 50MB
|
|
- Verify file is a valid audio format (MP3, WAV, AIFF)
|
|
- Ensure you're logged in with a valid session
|
|
|
|
### Audio doesn't play
|
|
- Check browser console for errors
|
|
- Verify audio_url is accessible in the database
|
|
- Test the direct URL in a new tab
|
|
|
|
### Duration shows 0:00
|
|
- This is normal for the initial display
|
|
- The actual duration loads when the audio file is fetched
|
|
- Duration is estimated from file size for the initial display |