Implement audio player component with HTML5 audio and download functionality

This commit is contained in:
2025-12-09 09:29:05 +00:00
parent e92d0349bf
commit ea77b17363
3 changed files with 74 additions and 15 deletions

View File

@@ -2,8 +2,9 @@ import { useState } from 'react'
import './App.css'
import TextInputSection from './components/TextInputSection'
import VoiceAssignmentSection from './components/VoiceAssignmentSection'
import AudioPlayerSection from './components/AudioPlayerSection'
import type { Role } from './api/tts'
import { detectRoles } from './api/tts'
import { detectRoles, generateAudiobook } from './api/tts'
function App() {
const [text, setText] = useState('')
@@ -15,6 +16,7 @@ function App() {
const [speed, setSpeed] = useState(1.0) // Default: 1.0x
const [isGenerating, setIsGenerating] = useState(false)
const [error, setError] = useState<string | null>(null)
const [audioUrl, setAudioUrl] = useState<string | null>(null)
const handleTextChange = (newText: string) => {
setText(newText)
@@ -63,26 +65,46 @@ function App() {
setError(null)
try {
// TODO: Implement audio generation
console.log('Generating audiobook with:', {
// Convert voice assignments to the format expected by the API
const rolesArray = Array.from(voiceAssignments.entries()).map(([id, voice]) => ({
id,
voice
}))
// Generate the audiobook
const audioBlob = await generateAudiobook({
text,
language,
voiceAssignments: Array.from(voiceAssignments.entries()),
lang: language,
roles: rolesArray,
speed
})
// Placeholder - will be implemented in later tasks
setTimeout(() => {
setIsGenerating(false)
setPhase('generated')
}, 1000)
// Create a blob URL for the audio
const url = URL.createObjectURL(audioBlob)
setAudioUrl(url)
// Move to generated phase
setPhase('generated')
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to generate audiobook')
console.error('Generation error:', err)
} finally {
setIsGenerating(false)
}
}
const handleDownload = () => {
if (!audioUrl) return
// Create a temporary anchor element to trigger download
const link = document.createElement('a')
link.href = audioUrl
link.download = 'audiobook.wav'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}
// Check if all roles have assigned voices
const allRolesAssigned = roles.length > 0 && roles.every(role => voiceAssignments.has(role.id))
@@ -122,10 +144,11 @@ function App() {
/>
)}
{phase === 'generated' && (
<div className="text-center">
<p>Audio player phase (to be implemented)</p>
</div>
{phase === 'generated' && audioUrl && (
<AudioPlayerSection
audioUrl={audioUrl}
onDownload={handleDownload}
/>
)}
</div>
</div>

View File

@@ -0,0 +1,36 @@
interface AudioPlayerSectionProps {
audioUrl: string;
onDownload: () => void;
}
export default function AudioPlayerSection({
audioUrl,
onDownload
}: AudioPlayerSectionProps) {
return (
<div className="w-full max-w-4xl mx-auto p-6">
<h2 className="text-2xl font-bold mb-6">Your Audiobook is Ready!</h2>
<div className="bg-white rounded-lg shadow-md p-6 mb-6">
<h3 className="text-lg font-semibold mb-4">Listen to your audiobook</h3>
<audio
controls
src={audioUrl}
className="w-full"
preload="metadata"
>
Your browser does not support the audio element.
</audio>
</div>
<div className="flex justify-center">
<button
onClick={onDownload}
className="px-6 py-3 bg-green-600 hover:bg-green-700 text-white font-semibold rounded-lg transition-colors cursor-pointer"
>
Download audiobook
</button>
</div>
</div>
);
}