Spaces:
Running
Running
import React, { useMemo, useEffect, useState } from 'react'; | |
import { | |
audioBufferToMp3, | |
blobFromAudioBuffer, | |
cleanupFilename, | |
delay, | |
} from '../utils/utils'; | |
interface AudioPlayerProps { | |
audioBuffer: AudioBuffer; | |
title: string; | |
} | |
export const AudioPlayer: React.FC<AudioPlayerProps> = ({ | |
audioBuffer, | |
title, | |
}) => { | |
const [isConverting, setIsConverting] = useState(false); | |
const [mp3Buffer, setMp3Buffer] = useState<ArrayBuffer | null>(null); | |
const blobUrl = useMemo(() => { | |
const wavBlob = blobFromAudioBuffer(audioBuffer); | |
return URL.createObjectURL(wavBlob); | |
}, [audioBuffer]); | |
const downloadWavUrl = useMemo(() => { | |
const wavBlob = blobFromAudioBuffer(audioBuffer); | |
return URL.createObjectURL(wavBlob); | |
}, [audioBuffer]); | |
const downloadMp3Url = useMemo(() => { | |
if (!mp3Buffer) return ''; | |
const mp3Blob = new Blob([mp3Buffer], { type: 'audio/mp3' }); | |
return URL.createObjectURL(mp3Blob); | |
}, [audioBuffer]); | |
// Clean up the object URL when the component unmounts or audioBuffer changes. | |
useEffect(() => { | |
return () => URL.revokeObjectURL(blobUrl); | |
}, [blobUrl]); | |
useEffect(() => { | |
return () => URL.revokeObjectURL(downloadWavUrl); | |
}, [downloadWavUrl]); | |
useEffect(() => { | |
return () => URL.revokeObjectURL(downloadMp3Url); | |
}, [downloadMp3Url]); | |
const convertToMp3 = async () => { | |
setIsConverting(true); | |
await delay(10); // wait a bit for the button to be rendered | |
setMp3Buffer(audioBufferToMp3(audioBuffer)); | |
setIsConverting(false); | |
}; | |
return ( | |
<div className="mt-4 flex items-center"> | |
<audio controls src={blobUrl}> | |
Your browser does not support the audio element. | |
</audio> | |
<a | |
className="btn btn-sm btn-primary ml-2" | |
href={downloadWavUrl} | |
download={`Podcast_${cleanupFilename(title)}.wav`} | |
> | |
Download WAV | |
</a> | |
{mp3Buffer ? ( | |
<a | |
className="btn btn-sm btn-primary ml-2" | |
href={downloadMp3Url} | |
download={`Podcast_${cleanupFilename(title)}.mp3`} | |
> | |
Download MP3 | |
</a> | |
) : ( | |
<button | |
className="btn btn-sm ml-2" | |
disabled={isConverting} | |
onClick={convertToMp3} | |
> | |
{isConverting | |
? 'Converting...' | |
: 'Convert to MP3 (may take ~10 seconds)'} | |
</button> | |
)} | |
</div> | |
); | |
}; | |