refactor: upgrade wavesurfer.js

This commit is contained in:
Tristan Yang
2023-07-10 18:18:21 +08:00
parent e911c35869
commit 1b06aa6894
4 changed files with 382 additions and 220 deletions
+38 -62
View File
@@ -17,62 +17,47 @@ export type VoiceMessageProps = {
// 全局存储Voice信息
const VoiceMap: { [key: string]: WaveSurfer | null } = {};
const VoiceMessage = ({ file_path }: { file_path: string }) => {
// const waveRef = useRef<WaveSurfer | null>(null);
const containerRef = useRef(null);
const [status, setStatus] = useState<"loading" | "error" | "ready">("loading");
const [playing, setPlaying] = useState(false);
const [duration, setDuration] = useState("");
// const [audio, setAudio] = useState<HTMLAudioElement>(new Audio(`${BASE_URL}/resource/file?file_path=${encodeURIComponent(
// file_path
// )}`));
const initWave = (file_path: string) => {
const initWave = async (file_path: string) => {
let wave: WaveSurfer | null = null;
const audioSrc = `${BASE_URL}/resource/file?file_path=${encodeURIComponent(file_path)}`;
wave = WaveSurfer.create({
container: containerRef.current ?? "",
// maxCanvasWidth: 200,
height: 32,
waveColor: "#0BA5EC",
cursorColor: "#0BA5AA",
progressColor: "#0BA5AA",
hideScrollbar: true,
// mediaControls: true,
normalize: true,
responsive: true
});
wave.load(audioSrc);
wave.on("error", function (err) {
console.log("voice message error", err);
console.log("audioSrc", audioSrc);
try {
// 先检测资源是否存在
await fetch(audioSrc);
wave = WaveSurfer.create({
container: containerRef.current ?? "",
height: 32,
waveColor: "#0BA5EC",
cursorColor: "#0BA5AA",
progressColor: "#0BA5AA",
hideScrollbar: true,
normalize: true
});
wave.load(audioSrc);
wave.on("play", function () {
setPlaying(true);
});
wave.on("pause", function () {
setPlaying(false);
});
wave.on("ready", function () {
setStatus("ready");
const current = VoiceMap[file_path];
if (current) {
const dur = current.getDuration();
const num = Math.ceil(dur);
const durDisplay = dayjs.duration(num, "seconds").format("mm:ss");
setDuration(durDisplay);
}
});
VoiceMap[file_path] = wave;
} catch (error) {
setStatus("error");
const current = VoiceMap[file_path];
if (current) {
current.destroy();
}
});
wave.on("play", function () {
setPlaying(true);
});
wave.on("pause", function () {
setPlaying(false);
});
wave.on("ready", function () {
setStatus("ready");
const current = VoiceMap[file_path];
if (current) {
const dur = current.getDuration();
const num = Math.ceil(dur);
const durDisplay = dayjs.duration(num, "seconds").format("mm:ss");
setDuration(durDisplay);
}
// tricky
if (containerRef.current) {
const container = containerRef.current as HTMLDivElement;
const w = (container.querySelector("wave>canvas") as HTMLCanvasElement)?.width;
container.style.width = `${w}px`;
}
});
VoiceMap[file_path] = wave;
}
};
useEffect(() => {
if (containerRef.current && file_path) {
@@ -93,7 +78,7 @@ const VoiceMessage = ({ file_path }: { file_path: string }) => {
Object.keys(VoiceMap).forEach((key) => {
try {
const item = VoiceMap[key];
if (item && item.backend && item.isPlaying()) {
if (item && item.isPlaying()) {
item.stop();
}
} catch (error) {
@@ -104,9 +89,7 @@ const VoiceMessage = ({ file_path }: { file_path: string }) => {
current.playPause();
}
};
// const handleReload = () => {
// initWave(file_path);
// };
const notReady = status !== "ready";
if (status == "error") return <ExpiredMessage type="audio" />;
return (
@@ -123,17 +106,10 @@ const VoiceMessage = ({ file_path }: { file_path: string }) => {
<IconPlay className="stroke-primary-500" />
)}
</button>
<div ref={containerRef} className={clsx("flex-1 h-8 min-w-[100px]")}>
{status == "loading" && <span className="text-xs">Loading voice message...</span>}
<div ref={containerRef} className={clsx("flex-1 h-8 min-w-[150px]")}>
{status == "loading" && <span className="text-xs leading-8">Loading voice message...</span>}
</div>
<time className="text-primary-500 text-xs whitespace-nowrap text-left">{duration}</time>
{/* {status === "error" && (
<IconRefresh
role="button"
className="absolute -right-6 top-1/2 -translate-y-1/2 w-4 h-4 stroke-primary-600"
onClick={handleReload}
/>
)} */}
</div>
);
};