sifa-classification-agentic-rag
/
src
/components
/playground
/ChatArea
/Messages
/Multimedia
/Audios
/Audios.tsx
| 'use client' | |
| import { memo, useMemo } from 'react' | |
| import { type AudioData } from '@/types/playground' | |
| import { decodeBase64Audio } from '@/lib/audio' | |
| /** | |
| * Renders a single audio item with controls | |
| * @param audio - AudioData object containing url or base64 audio data | |
| */ | |
| const AudioItem = memo(({ audio }: { audio: AudioData }) => { | |
| const audioUrl = useMemo(() => { | |
| if (audio?.url) { | |
| return audio.url | |
| } | |
| if (audio.base64_audio) { | |
| return decodeBase64Audio( | |
| audio.base64_audio, | |
| audio.mime_type || 'audio/wav' | |
| ) | |
| } | |
| if (audio.content) { | |
| return decodeBase64Audio( | |
| audio.content, | |
| 'audio/pcm16', | |
| audio.sample_rate, | |
| audio.channels | |
| ) | |
| } | |
| return null | |
| }, [audio]) | |
| if (!audioUrl) return null | |
| return ( | |
| <audio | |
| src={audioUrl} | |
| controls | |
| className="w-full rounded-lg" | |
| preload="metadata" | |
| /> | |
| ) | |
| }) | |
| AudioItem.displayName = 'AudioItem' | |
| /** | |
| * Renders a list of audio elements | |
| * @param audio - Array of AudioData objects | |
| */ | |
| const Audios = memo(({ audio }: { audio: AudioData[] }) => ( | |
| <div className="flex flex-col gap-4"> | |
| {audio.map((audio_item, index) => ( | |
| // TODO :: find a better way to handle the key | |
| <AudioItem key={audio_item.id ?? `audio-${index}`} audio={audio_item} /> | |
| ))} | |
| </div> | |
| )) | |
| Audios.displayName = 'Audios' | |
| export default Audios | |