react-voice-visualizer
Version:
React library for audio recording and visualization using Web Audio API
829 lines (828 loc) • 35.5 kB
JavaScript
(function(){"use strict";(r=>{var o;try{if(typeof window>"u")return;var e=document.createElement("style");e.appendChild(document.createTextNode(r));const i=(o=document.querySelector('meta[property="csp-nonce"]'))==null?void 0:o.getAttribute("nonce");i&&e.setAttribute("nonce",i),document.head.appendChild(e)}catch(i){console.error("vite-plugin-css-injected-by-js",i)}})(".voice-visualizer__buttons-container{display:flex;justify-content:center;align-items:center;column-gap:20px;row-gap:15px;flex-wrap:wrap;margin-bottom:40px}.voice-visualizer__btn-center{box-sizing:border-box;flex-shrink:0;width:60px;height:60px;padding:0;display:flex;justify-content:center;align-items:center;border-radius:50%;background-color:#fff;border:4px solid #c5c5c5;outline:none;cursor:pointer;transition:border-color .3s,background-color .3s}.voice-visualizer__btn-center:disabled{opacity:.85;cursor:default}.voice-visualizer__btn-center:hover{background-color:#eaeaea;border:4px solid #9f9f9f}.voice-visualizer__btn-center>img{width:auto;height:50%;max-height:30px}.voice-visualizer__btn-center.voice-visualizer__btn-center-pause{background-color:#ff3030}.voice-visualizer__btn-center.voice-visualizer__btn-center-pause:hover{background-color:#ff4f4f}.voice-visualizer__btn-center.voice-visualizer__btn-center-pause>img{height:50%;max-height:16px}.voice-visualizer__btn-center.voice-visualizer__btn-center--border-transparent{border-color:transparent}.voice-visualizer__btn-center.voice-visualizer__btn-center--border-transparent:hover{background-color:#fff}.voice-visualizer__btn-left{box-sizing:border-box;flex-shrink:0;width:60px;height:60px;padding:0;display:flex;justify-content:center;align-items:center;border-radius:50%;background-color:#ff3030;border:4px solid #c5c5c5;outline:none;cursor:pointer;transition:border-color .3s,background-color .3s,opacity .3s}.voice-visualizer__btn-container{min-width:100px;display:flex;justify-content:flex-end}.voice-visualizer__btn-left:hover{background-color:#ff4f4f}.voice-visualizer__btn-left:disabled{opacity:.6;background-color:#ff3030;cursor:default}.voice-visualizer__btn-left.voice-visualizer__btn-left-microphone{background-color:#fff}.voice-visualizer__btn-left.voice-visualizer__btn-left-microphone>img{width:auto;height:50%;max-height:30px}.voice-visualizer__btn-left>img{width:auto;height:50%;max-height:16px}.voice-visualizer__btn-left:hover{border:4px solid #9f9f9f}.voice-visualizer__btn{box-sizing:border-box;min-width:100px;min-height:60px;padding:5px 20px;border-radius:40px;font-size:15px;background-color:#f0f0f0;transition:background-color .3s,opacity .3s}.voice-visualizer__btn:disabled{opacity:.8;background-color:#f0f0f0;cursor:default}.voice-visualizer__btn:hover{background-color:#bebebe}.voice-visualizer__canvas-container{position:relative;width:fit-content;margin:0 auto;overflow:hidden}.voice-visualizer__canvas-container canvas{display:block}.voice-visualizer__canvas-microphone-btn{position:absolute;top:50%;left:50%;width:auto;max-width:12%;min-width:24px;height:50%;max-height:100px;background-color:transparent;border:none;outline:none;transform:translate(-50%,-50%)}.voice-visualizer__canvas-microphone-icon{width:100%;height:100%;will-change:transform;transition:transform .3s}.voice-visualizer__canvas-microphone-btn:hover .voice-visualizer__canvas-microphone-icon{transform:scale(1.03)}.voice-visualizer__canvas-audio-wave-icon{position:absolute;top:50%;left:50%;width:auto;max-width:40%;height:40%;max-height:100px;transform:translate(-118%,-50%) scale(-1)}.voice-visualizer__canvas-audio-wave-icon2{transform:translate(18%,-50%)}.voice-visualizer__canvas-audio-processing{position:absolute;top:50%;left:50%;margin:0;transform:translate(-50%,-50%)}.voice-visualizer__progress-indicator-hovered{position:absolute;top:0;pointer-events:none;height:100%;width:1px;background-color:#85858599}.voice-visualizer__progress-indicator-hovered-time{position:absolute;top:3%;left:1px;width:fit-content;margin:0;padding:0 7px;opacity:.8;font-size:12px;border-radius:0 4px 4px 0;background-color:#575757;text-align:left}.voice-visualizer__progress-indicator-hovered-time.voice-visualizer__progress-indicator-hovered-time-left{left:unset;right:1px;border-radius:4px 0 0 4px}.voice-visualizer__progress-indicator{position:absolute;top:0;pointer-events:none;height:100%;width:1px;background-color:#efefef}.voice-visualizer__progress-indicator-time{position:absolute;top:3%;left:1px;width:fit-content;box-sizing:border-box;min-width:37px;margin:0;padding:0 7px;font-size:12px;border-radius:0 4px 4px 0;text-align:left;color:#000;font-weight:500;background-color:#efefef}.voice-visualizer__progress-indicator-time.voice-visualizer__progress-indicator-time-left{left:unset;right:1px;border-radius:4px 0 0 4px}.voice-visualizer__audio-info-container{box-sizing:border-box;height:55px;display:flex;align-items:center;justify-content:center;gap:30px}.voice-visualizer__audio-info-time{margin:15px 0;min-width:38px;text-align:left}.voice-visualizer__visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:4px solid #c5c5c5;white-space:nowrap;clip-path:inset(100%);clip:rect(0 0 0 0);overflow:hidden}.voice-visualizer__relative{position:relative}.voice-visualizer__spinner-wrapper{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:52px;height:52px;display:flex;justify-content:center;align-items:center}.voice-visualizer__spinner{flex-shrink:0;width:100%;height:100%;border:4px solid rgba(197,197,197,.5);border-radius:50%;border-top-color:#b7b7b7;animation:voice-visualizer__spin 1s ease-in-out infinite;-webkit-animation:voice-visualizer__spin 1s ease-in-out infinite}@keyframes voice-visualizer__spin{to{transform:rotate(360deg)}}@-webkit-keyframes voice-visualizer__spin{to{transform:rotate(360deg)}}")})();
import { jsx as u, jsxs as ee, Fragment as ke } from "react/jsx-runtime";
import { useState as l, useRef as y, useCallback as tt, useEffect as P, useLayoutEffect as rt } from "react";
const Oe = ({
canvas: e,
backgroundColor: t
}) => {
const r = e.height, n = e.width, c = Math.round(n / 2), h = e.getContext("2d");
return h ? (h.clearRect(0, 0, n, r), t !== "transparent" && (h.fillStyle = t, h.fillRect(0, 0, n, r)), { context: h, height: r, width: n, halfWidth: c }) : null;
}, Ee = ({
context: e,
color: t,
rounded: r,
x: n,
y: c,
w: h,
h: L
}) => {
e.fillStyle = t, e.beginPath(), e.roundRect ? (e.roundRect(n, c, h, L, r), e.fill()) : e.fillRect(n, c, h, L);
}, nt = ({
barsData: e,
canvas: t,
barWidth: r,
gap: n,
backgroundColor: c,
mainBarColor: h,
secondaryBarColor: L,
currentAudioTime: v = 0,
rounded: I,
duration: f
}) => {
const S = Oe({ canvas: t, backgroundColor: c });
if (!S)
return;
const { context: w, height: z } = S, A = v / f;
e.forEach((a, g) => {
const M = g / e.length, s = A > M;
Ee({
context: w,
color: s ? L : h,
rounded: I,
x: g * (r + n * r),
y: z / 2 - a.max,
h: a.max * 2,
w: r
});
});
};
function it({
context: e,
color: t,
rounded: r,
width: n,
height: c,
barWidth: h
}) {
Ee({
context: e,
color: t,
rounded: r,
x: n / 2 + h / 2,
y: c / 2 - 1,
h: 2,
w: n - (n / 2 + h / 2)
});
}
const ct = ({
audioData: e,
unit: t,
index: r,
index2: n,
canvas: c,
isRecordingInProgress: h,
isPausedRecording: L,
picks: v,
backgroundColor: I,
barWidth: f,
mainBarColor: S,
secondaryBarColor: w,
rounded: z,
animateCurrentPick: A,
fullscreen: a
}) => {
const g = Oe({ canvas: c, backgroundColor: I });
if (!g)
return;
const { context: M, height: s, width: j, halfWidth: B } = g;
if (e != null && e.length && h) {
const H = Math.max(...e);
if (!L) {
if (n.current >= f) {
n.current = 0;
const N = (s - H / 258 * s) / s * 100, te = (-s + H / 258 * s * 2) / s * 100, J = r.current === f ? {
startY: N,
barHeight: te
} : null;
r.current >= t ? r.current = f : r.current += f, v.length > (a ? j : B) / f && v.pop(), v.unshift(J);
}
n.current += 1;
}
!a && ue(), A && Ee({
context: M,
rounded: z,
color: S,
x: a ? j : B,
y: s - H / 258 * s,
h: -s + H / 258 * s * 2,
w: f
});
let R = (a ? j : B) - n.current;
v.forEach((N) => {
N && Ee({
context: M,
color: S,
rounded: z,
x: R,
y: N.startY * s / 100 > s / 2 - 1 ? s / 2 - 1 : N.startY * s / 100,
h: N.barHeight * s / 100 > 2 ? N.barHeight * s / 100 : 2,
w: f
}), R -= f;
});
} else
v.length = 0;
function ue() {
it({
context: M,
color: w,
rounded: z,
width: j,
height: s,
barWidth: f
});
}
}, qe = (e) => {
const t = Math.floor(e / 3600), r = Math.floor(e % 3600 / 60), n = e % 60, c = Math.floor(
(n - Math.floor(n)) * 1e3
);
return t > 0 ? `${String(t).padStart(2, "0")}:${String(r).padStart(
2,
"0"
)}:${String(Math.floor(n)).padStart(2, "0")}:${String(
c
).charAt(0)}` : r > 0 ? `${String(r).padStart(2, "0")}:${String(
Math.floor(n)
).padStart(2, "0")}:${String(c).charAt(0)}` : `${String(Math.floor(n)).padStart(2, "0")}:${String(
c
).charAt(0)}`;
}, st = (e) => {
const t = Math.floor(e / 1e3), r = Math.floor(t / 3600), n = Math.floor(t % 3600 / 60), c = t % 60;
return r > 0 ? `${String(r).padStart(2, "0")}:${String(n).padStart(
2,
"0"
)}:${String(c).padStart(2, "0")}` : `${String(n).padStart(2, "0")}:${String(c).padStart(2, "0")}`;
};
function Re(e) {
if (typeof e == "string") {
const t = Number(e);
if (!Number.isNaN(t))
return `${Math.trunc(t / 2) * 2}px`;
}
return e;
}
const ot = ({
bufferData: e,
height: t,
width: r,
barWidth: n,
gap: c
}) => {
const h = r / (n + c * n), L = Math.floor(e.length / h), v = t / 2;
let I = [], f = 0;
for (let S = 0; S < h; S++) {
const w = [];
let z = 0;
for (let a = 0; a < L && S * L + a < e.length; a++) {
const g = e[S * L + a];
g > 0 && (w.push(g), z++);
}
const A = w.reduce((a, g) => a + g, 0) / z;
A > f && (f = A), I.push({ max: A });
}
if (v * 0.95 > f * v) {
const S = v * 0.95 / f;
I = I.map((w) => ({
max: w.max > 0.01 ? w.max * S : 1
}));
}
return I;
}, at = (e) => {
if (!e)
return "";
const t = e.match(/audio\/([^;]+)/);
return t && t.length >= 2 ? `.${t[1]}` : "";
}, ut = (e) => {
const t = Math.floor(e / 3600), r = Math.floor(e % 3600 / 60), n = e % 60, c = Math.floor(
(n - Math.floor(n)) * 1e3
);
return t > 0 ? `${String(t).padStart(2, "0")}:${String(r).padStart(
2,
"0"
)}:${String(Math.floor(n)).padStart(2, "0")}}h` : r > 0 ? `${String(r).padStart(2, "0")}:${String(
Math.floor(n)
).padStart(2, "0")}m` : `${String(Math.floor(n)).padStart(2, "0")}:${String(
c
).charAt(0)}${String(c).charAt(1)}s`;
}, ht = (e) => {
onmessage = (t) => {
postMessage(e(t.data));
};
};
function lt({
fn: e,
initialValue: t,
onMessageReceived: r
}) {
const [n, c] = l(t);
return {
result: n,
setResult: c,
run: (L) => {
const v = new Worker(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
URL.createObjectURL(new Blob([`(${ht})(${e})`]))
);
v.onmessage = (I) => {
I.data && (c(I.data), r && r(), v.terminate());
}, v.onerror = (I) => {
console.error(I.message), v.terminate();
}, v.postMessage(L);
}
};
}
const mt = (e, t = 250) => {
const r = y();
return tt(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(...n) => {
const c = () => {
clearTimeout(r.current), e(...n);
};
clearTimeout(r.current), r.current = setTimeout(c, t);
},
[e, t]
);
};
const vt = ({
color: e = "#000000",
stroke: t = 2,
className: r
}) => /* @__PURE__ */ u(
"svg",
{
viewBox: "0 0 23 33",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
className: r,
children: /* @__PURE__ */ u(
"path",
{
d: "M1.1 16.72c0 3 .96 5.8 3.61 7.95a9.96 9.96 0 0 0 6.5 2.17m0 0v4.34h4.34-8.67m4.34-4.34c2.35 0 4.42-.48 6.5-2.17a9.87 9.87 0 0 0 3.61-7.95M11.22 1.82c-1.45 0-2.5.37-3.3.93a5.6 5.6 0 0 0-1.84 2.4c-.9 2.06-1.1 4.77-1.1 7.24 0 2.46.2 5.17 1.1 7.24a5.6 5.6 0 0 0 1.84 2.4c.8.55 1.85.92 3.3.92 1.44 0 2.5-.37 3.29-.93a5.6 5.6 0 0 0 1.84-2.4c.9-2.06 1.1-4.77 1.1-7.23 0-2.47-.2-5.18-1.1-7.24a5.6 5.6 0 0 0-1.84-2.4 5.52 5.52 0 0 0-3.3-.93Z",
stroke: e,
strokeWidth: t,
strokeLinecap: "round",
strokeLinejoin: "round"
}
)
}
), Je = ({
color: e = "#FFFFFF",
reflect: t
}) => /* @__PURE__ */ u(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0.92 17.54 48.27 14.92",
className: `voice-visualizer__canvas-audio-wave-icon ${t ? "voice-visualizer__canvas-audio-wave-icon2" : ""}`,
children: /* @__PURE__ */ u(
"path",
{
d: "M.92 24.63h.21v.75H.92zm.42-1.39h.21v3.52h-.21zm.43.68h.21v2.17h-.21zM2.2 22h.21v6.01H2.2zm.43-1.27h.21v8.55h-.21zm.43 2.07h.21v4.4h-.21zm.43 1.22h.21v1.97h-.21zm.43.47h.21v1.03h-.21zm.43-1.66h.21v4.35h-.21zm.43-1.74h.21v7.82h-.21zm.43 1.94h.21v3.94h-.21zm.43 1.07h.21v1.81h-.21zm.42-.94h.21v3.68h-.21zm.43.91h.21v1.86h-.21zm.43-.23h.21v2.33h-.21zm.43.46h.21v1.4h-.21zm.43-.7h.21v2.8h-.21zm.43-1.6h.21v6.01h-.21zm.43-2.23h.21v10.46h-.21zm.43-1.4h.21v13.26h-.21zm.43.62h.21v12.02H9.5zm.43 1.64h.21v8.75h-.21zm.43 1.37h.21v6.01h-.21zm.43-1.87H11v9.74h-.21zm.42 1.32h.21v7.1h-.21zm.43-2.64h.21v12.38h-.21zm.43 1.61h.21v9.17h-.21zM12.5 22h.21v6.01h-.21zm.43 1.32h.21v3.37h-.21zm.43-2.51h.21v8.39h-.21zm.43.59H14v7.2h-.21zm.43 1.79h.21v3.62h-.21zm.43.41h.21v2.8h-.21zm.43.57h.21v1.66h-.21zm.43-1.11h.21v3.88h-.21zm.42-2.98h.21v9.84h-.21zm.43 1.06h.21v7.72h-.21zm.43 3.19H17v1.35h-.21zm.86-2.33h.21v6.01h-.21zm-.43 1.4h.21v3.21h-.21zm1.29.15h.21v2.9h-.21zm.43.68h.21v1.55h-.21zm-.86-.76h.21v3.05h-.21zm1.29-.05h.21v3.16h-.21zm.43-.64h.21v4.45h-.21zm.43.38h.21v3.68h-.21zm.42-.49h.21v4.66h-.21zm.43 1.32h.21v2.02h-.21zm.43.37h.21v1.29h-.21zm.43.31h.21v.67h-.21zm.43-.39h.21v1.45h-.21zm.43-1.35h.21v4.14h-.21zm.86.73h.21v2.69h-.21zm-.43.44h.21v1.81h-.21zm1.29-3.45h.21v8.7h-.21zm.43 1.71h.21v5.28h-.21zm-.86-2.3h.21v9.89h-.21zm1.29 3.36h.21v3.16h-.21zM25.8 22h.21v6.01h-.21zm.43 1.42h.21v3.16h-.21zm.43.88h.21v1.4h-.21zm.43-.93h.21v3.26h-.21zm.43-1.37h.21v6.01h-.21zm.43-.93h.21v7.87h-.21zm.43-.76h.21v9.38h-.21zm.43 1.69h.21v6.01h-.21zm.86 1.92h.21v2.17h-.21zm-.43-.6h.21v3.37h-.21zm1.28.05h.21v3.26h-.21zm.43.67h.21v1.91h-.21zm-.85-.51h.21v2.95h-.21zm1.28-.13h.21v3.21h-.21zm.43-1.4h.21v6.01h-.21zm.43-.99h.21v7.98h-.21zm.43 1.77h.21v4.45h-.21zm.43-1.22h.21v6.89h-.21zm.43 1.6h.21v3.68h-.21zm.43-.28h.21v4.25h-.21zm.43-.6h.21v5.44h-.21zm.43-.28h.21v6.01h-.21zm.85 2.02h.21v1.97h-.21zm-.43-.57h.21v3.11h-.21zm1.29.93h.21v1.24h-.21zm.43-.65h.21v2.54h-.21zm-.86-.28h.21v3.11h-.21zm1.29.83h.21v1.45h-.21zm.43-.99h.21v3.42h-.21zm.43-.1h.21v3.62h-.21zm.43-.7h.21v5.02h-.21zm.43.8h.21v3.42h-.21zm.43-1.29h.21v6.01h-.21zm.42-1.71h.21v9.43h-.21zm.43 2.38h.21v4.66h-.21zm.43.65h.21v3.37h-.21zm.86.08h.21v3.21h-.21zm-.43.54h.21v2.12h-.21zm1.29-.05h.21v2.23h-.21zm.43.28h.21v1.66h-.21zm-.86.16h.21v1.35h-.21zm1.29.21h.21v.93h-.21zm.43-6.04h.21v13h-.21zm.43.8h.21v11.4h-.21zm.43-1.76h.21v14.92h-.21zm.42 1.09h.21v12.74h-.21zm.43 1.17h.21v10.41h-.21zm.43 1.32h.21v7.77h-.21zm.43 1.6h.21v4.56h-.21zm.43 1.17h.21v2.23h-.21zm.86-.08h.21v2.38h-.21zm-.43-.34h.21v3.05h-.21zm1.29-.1h.21v3.26h-.21zm.43.93h.21v1.4h-.21zm-.86-.02h.21v1.45h-.21z",
fill: e
}
)
}
), Qe = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjMiIGhlaWdodD0iMzMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEuMSAxNi43MmMwIDMgLjk2IDUuOCAzLjYxIDcuOTVhOS45NiA5Ljk2IDAgMCAwIDYuNSAyLjE3bTAgMHY0LjM0aDQuMzQtOC42N200LjM0LTQuMzRjMi4zNSAwIDQuNDItLjQ4IDYuNS0yLjE3YTkuODcgOS44NyAwIDAgMCAzLjYxLTcuOTVNMTEuMjIgMS44MmMtMS40NSAwLTIuNS4zNy0zLjMuOTNhNS42IDUuNiAwIDAgMC0xLjg0IDIuNGMtLjkgMi4wNi0xLjEgNC43Ny0xLjEgNy4yNCAwIDIuNDYuMiA1LjE3IDEuMSA3LjI0YTUuNiA1LjYgMCAwIDAgMS44NCAyLjRjLjguNTUgMS44NS45MiAzLjMuOTIgMS40NCAwIDIuNS0uMzcgMy4yOS0uOTNhNS42IDUuNiAwIDAgMCAxLjg0LTIuNGMuOS0yLjA2IDEuMS00Ljc3IDEuMS03LjIzIDAtMi40Ny0uMi01LjE4LTEuMS03LjI0YTUuNiA1LjYgMCAwIDAtMS44NC0yLjQgNS41MiA1LjUyIDAgMCAwLTMuMy0uOTNaIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L3N2Zz4K", ft = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjYiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTE4Ljc1IDYuMTZjNC4zMSAyLjYgNi40NiAzLjkgNi40NiA1Ljg0IDAgMS45NS0yLjE1IDMuMjQtNi40NiA1Ljg0bC00Ljg0IDIuOTJjLTQuMzEgMi42LTYuNDYgMy44OS04LjA4IDIuOTItMS42Mi0uOTgtMS42Mi0zLjU3LTEuNjItOC43NlY5LjA4YzAtNS4xOSAwLTcuNzggMS42Mi04Ljc2IDEuNjItLjk3IDMuNzcuMzMgOC4wOCAyLjkybDQuODQgMi45MloiIGZpbGw9IiNmZmYiLz4KPC9zdmc+Cg==", Ve = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTE0IDMuNWEzLjUgMy41IDAgMSAxIDcgMHYyMmEzLjUgMy41IDAgMSAxLTcgMHYtMjJaIiBmaWxsPSIjZmZmIi8+CiAgPHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjkiIHJ4PSIzLjUiIGZpbGw9IiNmZmYiLz4KPC9zdmc+Cg==", dt = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjciIGhlaWdodD0iMjUiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3QgeD0iLjIxIiB3aWR0aD0iMjYiIGhlaWdodD0iMjUiIHJ4PSI1IiBmaWxsPSIjZmZmIi8+Cjwvc3ZnPgo=", Mt = ({
controls: {
audioRef: e,
audioData: t,
isRecordingInProgress: r,
recordedBlob: n,
duration: c,
currentAudioTime: h,
audioSrc: L,
bufferFromRecordedBlob: v,
togglePauseResume: I,
startRecording: f,
stopRecording: S,
saveAudioFile: w,
isAvailableRecordedAudio: z,
isPausedRecordedAudio: A,
isPausedRecording: a,
isProcessingStartRecording: g,
isProcessingRecordedAudio: M,
isCleared: s,
formattedDuration: j,
formattedRecordingTime: B,
formattedRecordedAudioCurrentTime: ue,
clearCanvas: H,
setCurrentAudioTime: R,
isProcessingOnResize: N,
_setIsProcessingOnResize: te,
_setIsProcessingAudioOnComplete: J
},
width: he = "100%",
height: Ie = 200,
speed: we = 3,
backgroundColor: C = "transparent",
mainBarColor: x = "#FFFFFF",
secondaryBarColor: U = "#5e5e5e",
barWidth: re = 2,
gap: le = 1,
rounded: Y = 5,
isControlPanelShown: Le = !0,
isDownloadAudioButtonShown: Ce = !1,
animateCurrentPick: ne = !0,
fullscreen: Q = !1,
onlyRecording: Z = !1,
isDefaultUIShown: V = !0,
defaultMicrophoneIconColor: me = x,
defaultAudioWaveIconColor: ve = x,
mainContainerClassName: Se,
canvasContainerClassName: xe,
isProgressIndicatorShown: ye = !Z,
progressIndicatorClassName: fe,
isProgressIndicatorTimeShown: ie = !0,
progressIndicatorTimeClassName: Ne,
isProgressIndicatorOnHoverShown: ce = !Z,
progressIndicatorOnHoverClassName: p,
isProgressIndicatorTimeOnHoverShown: G = !0,
progressIndicatorTimeOnHoverClassName: q,
isAudioProcessingTextShown: se = !0,
audioProcessingTextClassName: X,
controlButtonsClassName: b
}) => {
const [_, o] = l(0), [T, $e] = l(0), [de, He] = l(0), [ze, Ae] = l(0), [K, je] = l(!1), [Ze, ge] = l(window.innerWidth), [oe, Me] = l(!1), Te = Ze < 768, ae = Math.trunc(we), F = Math.trunc(le), O = Math.trunc(
Te && F > 0 ? re + 1 : re
), De = O + F * O, d = y(null), be = y([]), W = y(ae), Fe = y(O), i = y(O), m = y(null), {
result: D,
setResult: k,
run: _e
} = lt({
fn: ot,
initialValue: [],
onMessageReceived: Ke
}), Xe = mt(Ue);
P(() => {
if (!m.current)
return;
const E = () => {
ge(window.innerWidth), z ? (te(!0), Me(!0), Xe()) : Ue();
}, $ = new ResizeObserver(E);
return $.observe(m.current), () => {
$.disconnect();
};
}, [he, z]), rt(() => {
d.current && ((W.current >= ae || !t.length) && (W.current = t.length ? 0 : ae, ct({
audioData: t,
unit: De,
index: Fe,
index2: i,
canvas: d.current,
picks: be.current,
isRecordingInProgress: r,
isPausedRecording: a,
backgroundColor: C,
mainBarColor: x,
secondaryBarColor: U,
barWidth: O,
rounded: Y,
animateCurrentPick: ne,
fullscreen: Q
})), W.current += 1);
}, [
d.current,
t,
O,
C,
x,
U,
Y,
Q,
V,
ze
]), P(() => {
var E, $;
if (z)
return K ? (E = d.current) == null || E.addEventListener("mouseleave", Ge) : ($ = d.current) == null || $.addEventListener("mouseenter", Ye), () => {
var pe, We;
K ? (pe = d.current) == null || pe.removeEventListener("mouseleave", Ge) : (We = d.current) == null || We.removeEventListener("mouseenter", Ye);
};
}, [K, z]), P(() => {
var $;
if (!v || !d.current || r || oe)
return;
if (Z) {
H();
return;
}
be.current = [];
const E = v.getChannelData(0);
return _e({
bufferData: E,
height: de,
width: ze,
barWidth: O,
gap: F
}), ($ = d.current) == null || $.addEventListener("mousemove", Pe), () => {
var pe;
(pe = d.current) == null || pe.removeEventListener(
"mousemove",
Pe
);
};
}, [
v,
T,
de,
le,
re,
oe
]), P(() => {
if (!(Z || !(D != null && D.length) || !d.current || M)) {
if (s) {
k([]);
return;
}
nt({
barsData: D,
canvas: d.current,
barWidth: O,
gap: F,
backgroundColor: C,
mainBarColor: x,
secondaryBarColor: U,
currentAudioTime: h,
rounded: Y,
duration: c
});
}
}, [
D,
h,
s,
Y,
C,
x,
U
]), P(() => {
M && d.current && Oe({
canvas: d.current,
backgroundColor: C
});
}, [M]);
function Ue() {
if (!m.current || !d.current)
return;
W.current = ae;
const E = Math.trunc(
m.current.clientHeight * window.devicePixelRatio / 2
) * 2;
$e(m.current.clientWidth), He(E), Ae(
Math.round(
m.current.clientWidth * window.devicePixelRatio
)
), Me(!1);
}
function Ke() {
te(!1), J(!1), e != null && e.current && !N && (e.current.src = L);
}
const Ye = () => {
je(!0);
}, Ge = () => {
je(!1);
}, Pe = (E) => {
o(E.offsetX);
}, et = (E) => {
if (e != null && e.current && d.current) {
const $ = c / T * (E.clientX - d.current.getBoundingClientRect().left);
e.current.currentTime = $, R($);
}
}, Be = h / c * T;
return /* @__PURE__ */ ee("div", { className: `voice-visualizer ${Se ?? ""}`, children: [
/* @__PURE__ */ ee(
"div",
{
className: `voice-visualizer__canvas-container ${xe ?? ""}`,
ref: m,
style: { width: Re(he) },
children: [
/* @__PURE__ */ u(
"canvas",
{
ref: d,
width: ze,
height: de,
onClick: et,
style: {
height: Re(Ie),
width: T
},
children: "Your browser does not support HTML5 Canvas."
}
),
V && s && /* @__PURE__ */ ee(ke, { children: [
/* @__PURE__ */ u(Je, { color: ve }),
/* @__PURE__ */ u(Je, { color: ve, reflect: !0 }),
/* @__PURE__ */ u(
"button",
{
type: "button",
onClick: f,
className: "voice-visualizer__canvas-microphone-btn",
children: /* @__PURE__ */ u(
vt,
{
color: me,
stroke: 0.5,
className: "voice-visualizer__canvas-microphone-icon"
}
)
}
)
] }),
se && M && /* @__PURE__ */ u(
"p",
{
className: `voice-visualizer__canvas-audio-processing ${X ?? ""}`,
style: { color: x },
children: "Processing Audio..."
}
),
K && z && !M && !Te && ce && /* @__PURE__ */ u(
"div",
{
className: `voice-visualizer__progress-indicator-hovered ${p ?? ""}`,
style: {
left: _
},
children: G && /* @__PURE__ */ u(
"p",
{
className: `voice-visualizer__progress-indicator-hovered-time
${T - _ < 70 ? "voice-visualizer__progress-indicator-hovered-time-left" : ""}
${q ?? ""}`,
children: qe(
c / T * _
)
}
)
}
),
ye && z && !M && c ? /* @__PURE__ */ u(
"div",
{
className: `voice-visualizer__progress-indicator ${fe ?? ""}`,
style: {
left: Be < T - 1 ? Be : T - 1
},
children: ie && /* @__PURE__ */ u(
"p",
{
className: `voice-visualizer__progress-indicator-time ${T - h * T / c < 70 ? "voice-visualizer__progress-indicator-time-left" : ""} ${Ne ?? ""}`,
children: ue
}
)
}
) : null
]
}
),
Le && /* @__PURE__ */ ee(ke, { children: [
/* @__PURE__ */ ee("div", { className: "voice-visualizer__audio-info-container", children: [
r && /* @__PURE__ */ u("p", { className: "voice-visualizer__audio-info-time", children: B }),
c && !M ? /* @__PURE__ */ u("p", { children: j }) : null
] }),
/* @__PURE__ */ ee("div", { className: "voice-visualizer__buttons-container", children: [
r && /* @__PURE__ */ u("div", { className: "voice-visualizer__btn-container", children: /* @__PURE__ */ u(
"button",
{
type: "button",
className: `voice-visualizer__btn-left ${a ? "voice-visualizer__btn-left-microphone" : ""}`,
onClick: I,
children: /* @__PURE__ */ u(
"img",
{
src: a ? Qe : Ve,
alt: a ? "Play" : "Pause"
}
)
}
) }),
!s && /* @__PURE__ */ u(
"button",
{
type: "button",
className: `voice-visualizer__btn-left ${r || g ? "voice-visualizer__visually-hidden" : ""}`,
onClick: I,
disabled: M,
children: /* @__PURE__ */ u(
"img",
{
src: A ? ft : Ve,
alt: A ? "Play" : "Pause"
}
)
}
),
s && /* @__PURE__ */ ee(
"button",
{
type: "button",
className: `voice-visualizer__btn-center voice-visualizer__relative ${g ? "voice-visualizer__btn-center--border-transparent" : ""}`,
onClick: f,
disabled: g,
children: [
g && /* @__PURE__ */ u("div", { className: "voice-visualizer__spinner-wrapper", children: /* @__PURE__ */ u("div", { className: "voice-visualizer__spinner" }) }),
/* @__PURE__ */ u("img", { src: Qe, alt: "Microphone" })
]
}
),
/* @__PURE__ */ u(
"button",
{
type: "button",
className: `voice-visualizer__btn-center voice-visualizer__btn-center-pause ${r ? "" : "voice-visualizer__visually-hidden"}`,
onClick: S,
children: /* @__PURE__ */ u("img", { src: dt, alt: "Stop" })
}
),
!s && /* @__PURE__ */ u(
"button",
{
type: "button",
onClick: H,
className: `voice-visualizer__btn ${b ?? ""}`,
disabled: M,
children: "Clear"
}
),
Ce && n && /* @__PURE__ */ u(
"button",
{
type: "button",
onClick: w,
className: `voice-visualizer__btn ${b ?? ""}`,
disabled: M,
children: "Download Audio"
}
)
] })
] })
] });
};
function pt({
onStartRecording: e,
onStopRecording: t,
onPausedRecording: r,
onResumedRecording: n,
onClearCanvas: c,
onEndAudioPlayback: h,
onStartAudioPlayback: L,
onPausedAudioPlayback: v,
onResumedAudioPlayback: I,
onErrorPlayingAudio: f,
shouldHandleBeforeUnload: S = !0,
mediaRecorderOptions: w,
timeslice: z,
onChunkAvailable: A
} = {}) {
const [a, g] = l(!1), [M, s] = l(!1), [j, B] = l(null), [ue, H] = l(new Uint8Array(0)), [R, N] = l(!1), [te, J] = l(null), [he, Ie] = l(null), [we, C] = l(0), [x, U] = l(0), [re, le] = l(0), [Y, Le] = l(""), [Ce, ne] = l(!0), [Q, Z] = l(0), [V, me] = l(!0), [ve, Se] = l(!1), [xe, ye] = l(!1), [fe, ie] = l(null), [Ne, ce] = l(!1), p = y(null), G = y(null), q = y(null), se = y(null), X = y(null), b = y(null), _ = y(null), o = y(null), T = !!(he && !R), $e = ut(re), de = st(we), He = qe(Q), ze = ve || R;
P(() => {
if (!a || M)
return;
const m = setInterval(() => {
const D = performance.now();
C((k) => k + (D - x)), U(D);
}, 1e3);
return () => clearInterval(m);
}, [x, M, a]), P(() => {
if (fe) {
F();
return;
}
}, [fe]), P(() => () => {
F();
}, []), P(() => (!V && S && window.addEventListener("beforeunload", Ae), () => {
window.removeEventListener("beforeunload", Ae);
}), [V, S]);
const Ae = (i) => {
i.preventDefault(), i.returnValue = "";
}, K = async (i) => {
if (i)
try {
if (i.size === 0)
throw new Error("Error: The audio blob is empty");
const m = URL.createObjectURL(i);
Le(m);
const D = await i.arrayBuffer(), _e = await new AudioContext().decodeAudioData(D);
Ie(_e), le(_e.duration - 0.06), ie(null);
} catch (m) {
console.error("Error processing the audio blob:", m), ie(
m instanceof Error ? m : new Error("Error processing the audio blob")
);
}
}, je = (i) => {
i instanceof Blob && (F(), ye(!0), me(!1), N(!0), g(!1), C(0), s(!1), o.current = new Audio(), J(i), K(i));
}, Ze = () => {
ce(!0), navigator.mediaDevices.getUserMedia({ audio: !0 }).then((i) => {
if (me(!1), ce(!1), g(!0), U(performance.now()), B(i), G.current = new window.AudioContext(), q.current = G.current.createAnalyser(), se.current = new Uint8Array(
q.current.frequencyBinCount
), X.current = G.current.createMediaStreamSource(i), X.current.connect(q.current), w != null && w.mimeType && !MediaRecorder.isTypeSupported(w.mimeType))
throw new Error(`The specified mime type "${w.mimeType}" is not supported by this browser.`);
p.current = new MediaRecorder(i, w), p.current.addEventListener(
"dataavailable",
oe
), z ? p.current.start(z) : p.current.start(), e && e(), ge();
}).catch((i) => {
ce(!1), ie(
i instanceof Error ? i : new Error("Error starting audio recording")
);
});
}, ge = () => {
q.current.getByteTimeDomainData(se.current), H(new Uint8Array(se.current)), b.current = requestAnimationFrame(ge);
}, oe = (i) => {
if (z && A) {
A(i.data);
return;
}
p.current && (p.current = null, o.current = new Audio(), J(i.data), K(i.data));
}, Me = () => {
o.current && (Z(o.current.currentTime), _.current = requestAnimationFrame(Me));
}, Te = () => {
a || Ne || (V || F(), Ze());
}, ae = () => {
a && (g(!1), p.current && (p.current.stop(), p.current.removeEventListener(
"dataavailable",
oe
)), j == null || j.getTracks().forEach((i) => i.stop()), b.current && cancelAnimationFrame(b.current), X.current && X.current.disconnect(), G.current && G.current.state !== "closed" && G.current.close(), z || N(!0), C(0), s(!1), t && t());
}, F = () => {
b.current && (cancelAnimationFrame(b.current), b.current = null), _.current && (cancelAnimationFrame(_.current), _.current = null), p.current && (p.current.removeEventListener(
"dataavailable",
oe
), p.current.stop(), p.current = null), j == null || j.getTracks().forEach((i) => i.stop()), o != null && o.current && (o.current.removeEventListener("ended", W), o.current.pause(), o.current.src = "", o.current = null), G.current = null, q.current = null, se.current = null, X.current = null, B(null), ce(!1), g(!1), ye(!1), N(!1), J(null), Ie(null), C(0), U(0), le(0), Le(""), Z(0), ne(!0), s(!1), Se(!1), H(new Uint8Array(0)), ie(null), me(!0), c && c();
}, O = () => {
if (o.current && o.current.paused) {
const i = o.current.play();
i !== void 0 && i.catch((m) => {
console.error(m), f && f(
m instanceof Error ? m : new Error("Error playing audio")
);
});
}
}, De = () => {
!o.current || a || (requestAnimationFrame(Me), O(), o.current.addEventListener("ended", W), ne(!1), L && Q === 0 && L(), I && Q !== 0 && I());
}, d = () => {
if (!o.current || a)
return;
_.current && cancelAnimationFrame(_.current), o.current.removeEventListener("ended", W), o.current.pause(), ne(!0);
const i = o.current.currentTime;
Z(i), o.current.currentTime = i, v && v();
}, be = () => {
var i, m, D;
if (a) {
s((k) => !k), ((i = p.current) == null ? void 0 : i.state) === "recording" ? ((m = p.current) == null || m.pause(), C((k) => k + (performance.now() - x)), b.current && cancelAnimationFrame(b.current), r && r()) : (b.current = requestAnimationFrame(ge), (D = p.current) == null || D.resume(), U(performance.now()), n && n());
return;
}
o.current && T && (o.current.paused ? De() : d());
}, W = () => {
_.current && cancelAnimationFrame(_.current), ne(!0), o != null && o.current && (o.current.currentTime = 0, Z(0), h && h());
}, Fe = () => {
var m;
if (!Y)
return;
const i = document.createElement("a");
i.href = Y, i.download = `recorded_audio${at(
(m = p.current) == null ? void 0 : m.mimeType
)}`, document.body.appendChild(i), i.click(), document.body.removeChild(i), URL.revokeObjectURL(Y);
};
return {
audioRef: o,
isRecordingInProgress: a,
isPausedRecording: M,
audioData: ue,
recordingTime: we,
isProcessingRecordedAudio: ze,
recordedBlob: te,
mediaRecorder: p.current,
duration: re,
currentAudioTime: Q,
audioSrc: Y,
isPausedRecordedAudio: Ce,
bufferFromRecordedBlob: he,
isCleared: V,
isAvailableRecordedAudio: T,
formattedDuration: $e,
formattedRecordingTime: de,
formattedRecordedAudioCurrentTime: He,
startRecording: Te,
togglePauseResume: be,
startAudioPlayback: De,
stopAudioPlayback: d,
stopRecording: ae,
saveAudioFile: Fe,
clearCanvas: F,
setCurrentAudioTime: Z,
error: fe,
isProcessingOnResize: ve,
isProcessingStartRecording: Ne,
isPreloadedBlob: xe,
setPreloadedAudioBlob: je,
_setIsProcessingAudioOnComplete: N,
_setIsProcessingOnResize: Se
};
}
export {
Mt as VoiceVisualizer,
pt as useVoiceVisualizer
};