feat(audiobook): change audio format from MP3 to WAV for project downloads and merging

This commit is contained in:
2026-03-10 17:56:46 +08:00
parent 006aa0c85f
commit bf7c73e57c
3 changed files with 24 additions and 14 deletions

View File

@@ -321,6 +321,8 @@ function ProjectCard({ project, onRefresh }: { project: AudiobookProject; onRefr
const [editFields, setEditFields] = useState({ name: '', description: '', instruct: '' })
const [sequentialPlayingId, setSequentialPlayingId] = useState<number | null>(null)
const [turbo, setTurbo] = useState(false)
const [charsCollapsed, setCharsCollapsed] = useState(false)
const [chaptersCollapsed, setChaptersCollapsed] = useState(false)
const prevStatusRef = useRef(project.status)
const autoExpandedRef = useRef(new Set<string>())
@@ -589,10 +591,14 @@ function ProjectCard({ project, onRefresh }: { project: AudiobookProject; onRefr
<div className="space-y-4 pt-2 border-t">
{detail && detail.characters.length > 0 && (
<div>
<div className="text-xs font-medium text-muted-foreground mb-2">
<button
className="flex items-center gap-1 text-xs font-medium text-muted-foreground mb-2 hover:text-foreground transition-colors w-full text-left"
onClick={() => setCharsCollapsed(v => !v)}
>
{charsCollapsed ? <ChevronDown className="h-3 w-3" /> : <ChevronUp className="h-3 w-3" />}
{detail.characters.length}
</div>
<div className="space-y-1.5">
</button>
{!charsCollapsed && <div className="space-y-1.5 max-h-72 overflow-y-auto pr-1">
{detail.characters.map(char => (
<div key={char.id} className="border rounded px-3 py-2">
{editingCharId === char.id ? (
@@ -643,7 +649,7 @@ function ProjectCard({ project, onRefresh }: { project: AudiobookProject; onRefr
)}
</div>
))}
</div>
</div>}
{status === 'characters_ready' && (
<Button
className="w-full mt-3"
@@ -659,9 +665,13 @@ function ProjectCard({ project, onRefresh }: { project: AudiobookProject; onRefr
{detail && detail.chapters.length > 0 && ['ready', 'generating', 'done'].includes(status) && (
<div>
<div className="flex items-center justify-between mb-2">
<div className="text-xs font-medium text-muted-foreground">
<button
className="flex items-center gap-1 text-xs font-medium text-muted-foreground hover:text-foreground transition-colors text-left"
onClick={() => setChaptersCollapsed(v => !v)}
>
{chaptersCollapsed ? <ChevronDown className="h-3 w-3" /> : <ChevronUp className="h-3 w-3" />}
{detail.chapters.length}
</div>
</button>
{detail.chapters.some(c => ['pending', 'error', 'ready'].includes(c.status)) && (
<Button
size="sm"
@@ -673,7 +683,7 @@ function ProjectCard({ project, onRefresh }: { project: AudiobookProject; onRefr
</Button>
)}
</div>
<div className="space-y-2">
{!chaptersCollapsed && <div className="space-y-2 max-h-96 overflow-y-auto pr-1">
{detail.chapters.map(ch => {
const chSegs = segments.filter(s => s.chapter_index === ch.chapter_index)
const chDone = chSegs.filter(s => s.status === 'done').length
@@ -729,8 +739,8 @@ function ProjectCard({ project, onRefresh }: { project: AudiobookProject; onRefr
</div>
)
})}
</div>
{doneCount > 0 && (
</div>}
{!chaptersCollapsed && doneCount > 0 && (
<div className="mt-2">
<SequentialPlayer segments={segments} projectId={project.id} onPlayingChange={setSequentialPlayingId} />
</div>