|
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]); |
|
|
|
|
|
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); |
|
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> |
|
); |
|
}; |
|
|