react-voice-visualizer
Version:
React library for audio recording and visualization using Web Audio API
820 lines (819 loc) • 35.2 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 a, jsxs as ne, Fragment as Re } from "react/jsx-runtime";
import { useState as h, useRef as N, useCallback as tt, useEffect as Y, useLayoutEffect as rt } from "react";
const Oe = ({
canvas: e,
backgroundColor: t
}) => {
const r = e.height, n = e.width, c = Math.round(n / 2), u = e.getContext("2d");
return u ? (u.clearRect(0, 0, n, r), t !== "transparent" && (u.fillStyle = t, u.fillRect(0, 0, n, r)), { context: u, height: r, width: n, halfWidth: c }) : null;
}, _e = ({
context: e,
color: t,
rounded: r,
x: n,
y: c,
w: u,
h: w
}) => {
e.fillStyle = t, e.beginPath(), e.roundRect ? (e.roundRect(n, c, u, w, r), e.fill()) : e.fillRect(n, c, u, w);
}, nt = ({
barsData: e,
canvas: t,
barWidth: r,
gap: n,
backgroundColor: c,
mainBarColor: u,
secondaryBarColor: w,
currentAudioTime: l = 0,
rounded: p,
duration: v
}) => {
const S = Oe({ canvas: t, backgroundColor: c });
if (!S)
return;
const { context: z, height: g } = S, y = l / v;
e.forEach((m, d) => {
const I = d / e.length, o = y > I;
_e({
context: z,
color: o ? w : u,
rounded: p,
x: d * (r + n * r),
y: g / 2 - m.max,
h: m.max * 2,
w: r
});
});
};
function it({
context: e,
color: t,
rounded: r,
width: n,
height: c,
barWidth: u
}) {
_e({
context: e,
color: t,
rounded: r,
x: n / 2 + u / 2,
y: c / 2 - 1,
h: 2,
w: n - (n / 2 + u / 2)
});
}
const ct = ({
audioData: e,
unit: t,
index: r,
index2: n,
canvas: c,
isRecordingInProgress: u,
isPausedRecording: w,
picks: l,
backgroundColor: p,
barWidth: v,
mainBarColor: S,
secondaryBarColor: z,
rounded: g,
animateCurrentPick: y,
fullscreen: m
}) => {
const d = Oe({ canvas: c, backgroundColor: p });
if (!d)
return;
const { context: I, height: o, width: H, halfWidth: G } = d;
if (e != null && e.length && u) {
const $ = Math.max(...e);
if (!w) {
if (n.current >= v) {
n.current = 0;
const A = (o - $ / 258 * o) / o * 100, V = (-o + $ / 258 * o * 2) / o * 100, ie = r.current === v ? {
startY: A,
barHeight: V
} : null;
r.current >= t ? r.current = v : r.current += v, l.length > (m ? H : G) / v && l.pop(), l.unshift(ie);
}
n.current += 1;
}
!m && P(), y && _e({
context: I,
rounded: g,
color: S,
x: m ? H : G,
y: o - $ / 258 * o,
h: -o + $ / 258 * o * 2,
w: v
});
let R = (m ? H : G) - n.current;
l.forEach((A) => {
A && _e({
context: I,
color: S,
rounded: g,
x: R,
y: A.startY * o / 100 > o / 2 - 1 ? o / 2 - 1 : A.startY * o / 100,
h: A.barHeight * o / 100 > 2 ? A.barHeight * o / 100 : 2,
w: v
}), R -= v;
});
} else
l.length = 0;
function P() {
it({
context: I,
color: z,
rounded: g,
width: H,
height: o,
barWidth: v
});
}
}, 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 Be(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 u = r / (n + c * n), w = Math.floor(e.length / u), l = t / 2;
let p = [], v = 0;
for (let S = 0; S < u; S++) {
const z = [];
let g = 0;
for (let m = 0; m < w && S * w + m < e.length; m++) {
const d = e[S * w + m];
d > 0 && (z.push(d), g++);
}
const y = z.reduce((m, d) => m + d, 0) / g;
y > v && (v = y), p.push({ max: y });
}
if (l * 0.95 > v * l) {
const S = l * 0.95 / v;
p = p.map((z) => ({
max: z.max > 0.01 ? z.max * S : 1
}));
}
return p;
}, 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] = h(t);
return {
result: n,
setResult: c,
run: (w) => {
const l = new Worker(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
URL.createObjectURL(new Blob([`(${ht})(${e})`]))
);
l.onmessage = (p) => {
p.data && (c(p.data), r && r(), l.terminate());
}, l.onerror = (p) => {
console.error(p.message), l.terminate();
}, l.postMessage(w);
}
};
}
const mt = (e, t = 250) => {
const r = N();
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__ */ a(
"svg",
{
viewBox: "0 0 23 33",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
className: r,
children: /* @__PURE__ */ a(
"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"
}
)
}
), We = ({
color: e = "#FFFFFF",
reflect: t
}) => /* @__PURE__ */ a(
"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__ */ a(
"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
}
)
}
), ke = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjMiIGhlaWdodD0iMzMiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTEuMSAxNi43MmMwIDMgLjk2IDUuOCAzLjYxIDcuOTVhOS45NiA5Ljk2IDAgMCAwIDYuNSAyLjE3bTAgMHY0LjM0aDQuMzQtOC42N200LjM0LTQuMzRjMi4zNSAwIDQuNDItLjQ4IDYuNS0yLjE3YTkuODcgOS44NyAwIDAgMCAzLjYxLTcuOTVNMTEuMjIgMS44MmMtMS40NSAwLTIuNS4zNy0zLjMuOTNhNS42IDUuNiAwIDAgMC0xLjg0IDIuNGMtLjkgMi4wNi0xLjEgNC43Ny0xLjEgNy4yNCAwIDIuNDYuMiA1LjE3IDEuMSA3LjI0YTUuNiA1LjYgMCAwIDAgMS44NCAyLjRjLjguNTUgMS44NS45MiAzLjMuOTIgMS40NCAwIDIuNS0uMzcgMy4yOS0uOTNhNS42IDUuNiAwIDAgMCAxLjg0LTIuNGMuOS0yLjA2IDEuMS00Ljc3IDEuMS03LjIzIDAtMi40Ny0uMi01LjE4LTEuMS03LjI0YTUuNiA1LjYgMCAwIDAtMS44NC0yLjQgNS41MiA1LjUyIDAgMCAwLTMuMy0uOTNaIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPgo8L3N2Zz4K", dt = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjYiIGhlaWdodD0iMjQiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTE4Ljc1IDYuMTZjNC4zMSAyLjYgNi40NiAzLjkgNi40NiA1Ljg0IDAgMS45NS0yLjE1IDMuMjQtNi40NiA1Ljg0bC00Ljg0IDIuOTJjLTQuMzEgMi42LTYuNDYgMy44OS04LjA4IDIuOTItMS42Mi0uOTgtMS42Mi0zLjU3LTEuNjItOC43NlY5LjA4YzAtNS4xOSAwLTcuNzggMS42Mi04Ljc2IDEuNjItLjk3IDMuNzcuMzMgOC4wOCAyLjkybDQuODQgMi45MloiIGZpbGw9IiNmZmYiLz4KPC9zdmc+Cg==", Je = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEiIGhlaWdodD0iMjkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTTE0IDMuNWEzLjUgMy41IDAgMSAxIDcgMHYyMmEzLjUgMy41IDAgMSAxLTcgMHYtMjJaIiBmaWxsPSIjZmZmIi8+CiAgPHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjkiIHJ4PSIzLjUiIGZpbGw9IiNmZmYiLz4KPC9zdmc+Cg==", ft = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjciIGhlaWdodD0iMjUiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHJlY3QgeD0iLjIxIiB3aWR0aD0iMjYiIGhlaWdodD0iMjUiIHJ4PSI1IiBmaWxsPSIjZmZmIi8+Cjwvc3ZnPgo=", Mt = ({
controls: {
audioRef: e,
audioData: t,
isRecordingInProgress: r,
recordedBlob: n,
duration: c,
currentAudioTime: u,
audioSrc: w,
bufferFromRecordedBlob: l,
togglePauseResume: p,
startRecording: v,
stopRecording: S,
saveAudioFile: z,
isAvailableRecordedAudio: g,
isPausedRecordedAudio: y,
isPausedRecording: m,
isProcessingStartRecording: d,
isProcessingRecordedAudio: I,
isCleared: o,
formattedDuration: H,
formattedRecordingTime: G,
formattedRecordedAudioCurrentTime: P,
clearCanvas: $,
setCurrentAudioTime: R,
isProcessingOnResize: A,
_setIsProcessingOnResize: V,
_setIsProcessingAudioOnComplete: ie
},
width: B = "100%",
height: fe = 200,
speed: ce = 3,
backgroundColor: W = "transparent",
mainBarColor: _ = "#FFFFFF",
secondaryBarColor: O = "#5e5e5e",
barWidth: se = 2,
gap: ye = 1,
rounded: Z = 5,
isControlPanelShown: oe = !0,
isDownloadAudioButtonShown: q = !1,
animateCurrentPick: ae = !0,
fullscreen: ue = !1,
onlyRecording: X = !1,
isDefaultUIShown: ze = !0,
defaultMicrophoneIconColor: Ee = _,
defaultAudioWaveIconColor: ge = _,
mainContainerClassName: Me,
canvasContainerClassName: he,
isProgressIndicatorShown: Ae = !X,
progressIndicatorClassName: le,
isProgressIndicatorTimeShown: L = !0,
progressIndicatorTimeClassName: F,
isProgressIndicatorOnHoverShown: K = !X,
progressIndicatorOnHoverClassName: me,
isProgressIndicatorTimeOnHoverShown: ee = !0,
progressIndicatorTimeOnHoverClassName: T,
isAudioProcessingTextShown: E = !0,
audioProcessingTextClassName: s,
controlButtonsClassName: pe
}) => {
const [Ie, Ce] = h(0), [j, xe] = h(0), [ve, je] = h(0), [Le, He] = h(0), [k, de] = h(!1), [De, $e] = h(window.innerWidth), [Te, J] = h(!1), be = De < 768, te = Math.trunc(ce), re = Math.trunc(ye), C = Math.trunc(
be && re > 0 ? se + 1 : se
), we = C + re * C, M = N(null), i = N([]), f = N(te), U = N(C), Q = N(C), x = N(null), {
result: Se,
setResult: Ve,
run: qe
} = lt({
fn: ot,
initialValue: [],
onMessageReceived: Ke
}), Xe = mt(Ze);
Y(() => {
if (!x.current)
return;
const D = () => {
$e(window.innerWidth), g ? (V(!0), J(!0), Xe()) : Ze();
}, b = new ResizeObserver(D);
return b.observe(x.current), () => {
b.disconnect();
};
}, [B, g]), rt(() => {
M.current && ((f.current >= te || !t.length) && (f.current = t.length ? 0 : te, ct({
audioData: t,
unit: we,
index: U,
index2: Q,
canvas: M.current,
picks: i.current,
isRecordingInProgress: r,
isPausedRecording: m,
backgroundColor: W,
mainBarColor: _,
secondaryBarColor: O,
barWidth: C,
rounded: Z,
animateCurrentPick: ae,
fullscreen: ue
})), f.current += 1);
}, [
M.current,
t,
C,
W,
_,
O,
Z,
ue,
ze,
Le
]), Y(() => {
var D, b;
if (g)
return k ? (D = M.current) == null || D.addEventListener("mouseleave", Ue) : (b = M.current) == null || b.addEventListener("mouseenter", Fe), () => {
var Ne, Pe;
k ? (Ne = M.current) == null || Ne.removeEventListener("mouseleave", Ue) : (Pe = M.current) == null || Pe.removeEventListener("mouseenter", Fe);
};
}, [k, g]), Y(() => {
var b;
if (!l || !M.current || r || Te)
return;
if (X) {
$();
return;
}
i.current = [];
const D = l.getChannelData(0);
return qe({
bufferData: D,
height: ve,
width: Le,
barWidth: C,
gap: re
}), (b = M.current) == null || b.addEventListener("mousemove", Ye), () => {
var Ne;
(Ne = M.current) == null || Ne.removeEventListener(
"mousemove",
Ye
);
};
}, [
l,
j,
ve,
ye,
se,
Te
]), Y(() => {
if (!(X || !(Se != null && Se.length) || !M.current || I)) {
if (o) {
Ve([]);
return;
}
nt({
barsData: Se,
canvas: M.current,
barWidth: C,
gap: re,
backgroundColor: W,
mainBarColor: _,
secondaryBarColor: O,
currentAudioTime: u,
rounded: Z,
duration: c
});
}
}, [
Se,
u,
o,
Z,
W,
_,
O
]), Y(() => {
I && M.current && Oe({
canvas: M.current,
backgroundColor: W
});
}, [I]);
function Ze() {
if (!x.current || !M.current)
return;
f.current = te;
const D = Math.trunc(
x.current.clientHeight * window.devicePixelRatio / 2
) * 2;
xe(x.current.clientWidth), je(D), He(
Math.round(
x.current.clientWidth * window.devicePixelRatio
)
), J(!1);
}
function Ke() {
V(!1), ie(!1), e != null && e.current && !A && (e.current.src = w);
}
const Fe = () => {
de(!0);
}, Ue = () => {
de(!1);
}, Ye = (D) => {
Ce(D.offsetX);
}, et = (D) => {
if (e != null && e.current && M.current) {
const b = c / j * (D.clientX - M.current.getBoundingClientRect().left);
e.current.currentTime = b, R(b);
}
}, Ge = u / c * j;
return /* @__PURE__ */ ne("div", { className: `voice-visualizer ${Me ?? ""}`, children: [
/* @__PURE__ */ ne(
"div",
{
className: `voice-visualizer__canvas-container ${he ?? ""}`,
ref: x,
style: { width: Be(B) },
children: [
/* @__PURE__ */ a(
"canvas",
{
ref: M,
width: Le,
height: ve,
onClick: et,
style: {
height: Be(fe),
width: j
},
children: "Your browser does not support HTML5 Canvas."
}
),
ze && o && /* @__PURE__ */ ne(Re, { children: [
/* @__PURE__ */ a(We, { color: ge }),
/* @__PURE__ */ a(We, { color: ge, reflect: !0 }),
/* @__PURE__ */ a(
"button",
{
type: "button",
onClick: v,
className: "voice-visualizer__canvas-microphone-btn",
children: /* @__PURE__ */ a(
vt,
{
color: Ee,
stroke: 0.5,
className: "voice-visualizer__canvas-microphone-icon"
}
)
}
)
] }),
E && I && /* @__PURE__ */ a(
"p",
{
className: `voice-visualizer__canvas-audio-processing ${s ?? ""}`,
style: { color: _ },
children: "Processing Audio..."
}
),
k && g && !I && !be && K && /* @__PURE__ */ a(
"div",
{
className: `voice-visualizer__progress-indicator-hovered ${me ?? ""}`,
style: {
left: Ie
},
children: ee && /* @__PURE__ */ a(
"p",
{
className: `voice-visualizer__progress-indicator-hovered-time
${j - Ie < 70 ? "voice-visualizer__progress-indicator-hovered-time-left" : ""}
${T ?? ""}`,
children: Qe(
c / j * Ie
)
}
)
}
),
Ae && g && !I && c ? /* @__PURE__ */ a(
"div",
{
className: `voice-visualizer__progress-indicator ${le ?? ""}`,
style: {
left: Ge < j - 1 ? Ge : j - 1
},
children: L && /* @__PURE__ */ a(
"p",
{
className: `voice-visualizer__progress-indicator-time ${j - u * j / c < 70 ? "voice-visualizer__progress-indicator-time-left" : ""} ${F ?? ""}`,
children: P
}
)
}
) : null
]
}
),
oe && /* @__PURE__ */ ne(Re, { children: [
/* @__PURE__ */ ne("div", { className: "voice-visualizer__audio-info-container", children: [
r && /* @__PURE__ */ a("p", { className: "voice-visualizer__audio-info-time", children: G }),
c && !I ? /* @__PURE__ */ a("p", { children: H }) : null
] }),
/* @__PURE__ */ ne("div", { className: "voice-visualizer__buttons-container", children: [
r && /* @__PURE__ */ a("div", { className: "voice-visualizer__btn-container", children: /* @__PURE__ */ a(
"button",
{
type: "button",
className: `voice-visualizer__btn-left ${m ? "voice-visualizer__btn-left-microphone" : ""}`,
onClick: p,
children: /* @__PURE__ */ a(
"img",
{
src: m ? ke : Je,
alt: m ? "Play" : "Pause"
}
)
}
) }),
!o && /* @__PURE__ */ a(
"button",
{
type: "button",
className: `voice-visualizer__btn-left ${r || d ? "voice-visualizer__visually-hidden" : ""}`,
onClick: p,
disabled: I,
children: /* @__PURE__ */ a(
"img",
{
src: y ? dt : Je,
alt: y ? "Play" : "Pause"
}
)
}
),
o && /* @__PURE__ */ ne(
"button",
{
type: "button",
className: `voice-visualizer__btn-center voice-visualizer__relative ${d ? "voice-visualizer__btn-center--border-transparent" : ""}`,
onClick: v,
disabled: d,
children: [
d && /* @__PURE__ */ a("div", { className: "voice-visualizer__spinner-wrapper", children: /* @__PURE__ */ a("div", { className: "voice-visualizer__spinner" }) }),
/* @__PURE__ */ a("img", { src: ke, alt: "Microphone" })
]
}
),
/* @__PURE__ */ a(
"button",
{
type: "button",
className: `voice-visualizer__btn-center voice-visualizer__btn-center-pause ${r ? "" : "voice-visualizer__visually-hidden"}`,
onClick: S,
children: /* @__PURE__ */ a("img", { src: ft, alt: "Stop" })
}
),
!o && /* @__PURE__ */ a(
"button",
{
type: "button",
onClick: $,
className: `voice-visualizer__btn ${pe ?? ""}`,
disabled: I,
children: "Clear"
}
),
q && n && /* @__PURE__ */ a(
"button",
{
type: "button",
onClick: z,
className: `voice-visualizer__btn ${pe ?? ""}`,
disabled: I,
children: "Download Audio"
}
)
] })
] })
] });
};
function pt({
onStartRecording: e,
onStopRecording: t,
onPausedRecording: r,
onResumedRecording: n,
onClearCanvas: c,
onEndAudioPlayback: u,
onStartAudioPlayback: w,
onPausedAudioPlayback: l,
onResumedAudioPlayback: p,
onErrorPlayingAudio: v,
shouldHandleBeforeUnload: S = !0
} = {}) {
const [z, g] = h(!1), [y, m] = h(!1), [d, I] = h(null), [o, H] = h(new Uint8Array(0)), [G, P] = h(!1), [$, R] = h(null), [A, V] = h(null), [ie, B] = h(0), [fe, ce] = h(0), [W, _] = h(0), [O, se] = h(""), [ye, Z] = h(!0), [oe, q] = h(0), [ae, ue] = h(!0), [X, ze] = h(!1), [Ee, ge] = h(!1), [Me, he] = h(null), [Ae, le] = h(!1), L = N(null), F = N(null), K = N(null), me = N(null), ee = N(null), T = N(null), E = N(null), s = N(null), pe = !!(A && !G), Ie = ut(W), Ce = st(ie), j = Qe(oe), xe = X || G;
Y(() => {
if (!z || y)
return;
const f = setInterval(() => {
const U = performance.now();
B((Q) => Q + (U - fe)), ce(U);
}, 1e3);
return () => clearInterval(f);
}, [fe, y, z]), Y(() => {
if (Me) {
J();
return;
}
}, [Me]), Y(() => () => {
J();
}, []), Y(() => (!ae && S && window.addEventListener("beforeunload", ve), () => {
window.removeEventListener("beforeunload", ve);
}), [ae, S]);
const ve = (i) => {
i.preventDefault(), i.returnValue = "";
}, je = async (i) => {
if (i)
try {
if (i.size === 0)
throw new Error("Error: The audio blob is empty");
const f = URL.createObjectURL(i);
se(f);
const U = await i.arrayBuffer(), x = await new AudioContext().decodeAudioData(U);
V(x), _(x.duration - 0.06), he(null);
} catch (f) {
console.error("Error processing the audio blob:", f), he(
f instanceof Error ? f : new Error("Error processing the audio blob")
);
}
}, Le = (i) => {
i instanceof Blob && (J(), ge(!0), ue(!1), P(!0), g(!1), B(0), m(!1), s.current = new Audio(), R(i), je(i));
}, He = () => {
le(!0), navigator.mediaDevices.getUserMedia({ audio: !0 }).then((i) => {
ue(!1), le(!1), g(!0), ce(performance.now()), I(i), F.current = new window.AudioContext(), K.current = F.current.createAnalyser(), me.current = new Uint8Array(
K.current.frequencyBinCount
), ee.current = F.current.createMediaStreamSource(i), ee.current.connect(K.current), L.current = new MediaRecorder(i), L.current.addEventListener(
"dataavailable",
de
), L.current.start(), e && e(), k();
}).catch((i) => {
le(!1), he(
i instanceof Error ? i : new Error("Error starting audio recording")
);
});
}, k = () => {
K.current.getByteTimeDomainData(me.current), H(new Uint8Array(me.current)), T.current = requestAnimationFrame(k);
}, de = (i) => {
L.current && (L.current = null, s.current = new Audio(), R(i.data), je(i.data));
}, De = () => {
s.current && (q(s.current.currentTime), E.current = requestAnimationFrame(De));
}, $e = () => {
z || Ae || (ae || J(), He());
}, Te = () => {
z && (g(!1), L.current && (L.current.stop(), L.current.removeEventListener(
"dataavailable",
de
)), d == null || d.getTracks().forEach((i) => i.stop()), T.current && cancelAnimationFrame(T.current), ee.current && ee.current.disconnect(), F.current && F.current.state !== "closed" && F.current.close(), P(!0), B(0), m(!1), t && t());
}, J = () => {
T.current && (cancelAnimationFrame(T.current), T.current = null), E.current && (cancelAnimationFrame(E.current), E.current = null), L.current && (L.current.removeEventListener(
"dataavailable",
de
), L.current.stop(), L.current = null), d == null || d.getTracks().forEach((i) => i.stop()), s != null && s.current && (s.current.removeEventListener("ended", we), s.current.pause(), s.current.src = "", s.current = null), F.current = null, K.current = null, me.current = null, ee.current = null, I(null), le(!1), g(!1), ge(!1), P(!1), R(null), V(null), B(0), ce(0), _(0), se(""), q(0), Z(!0), m(!1), ze(!1), H(new Uint8Array(0)), he(null), ue(!0), c && c();
}, be = () => {
if (s.current && s.current.paused) {
const i = s.current.play();
i !== void 0 && i.catch((f) => {
console.error(f), v && v(
f instanceof Error ? f : new Error("Error playing audio")
);
});
}
}, te = () => {
!s.current || z || (requestAnimationFrame(De), be(), s.current.addEventListener("ended", we), Z(!1), w && oe === 0 && w(), p && oe !== 0 && p());
}, re = () => {
if (!s.current || z)
return;
E.current && cancelAnimationFrame(E.current), s.current.removeEventListener("ended", we), s.current.pause(), Z(!0);
const i = s.current.currentTime;
q(i), s.current.currentTime = i, l && l();
}, C = () => {
var i, f, U;
if (z) {
m((Q) => !Q), ((i = L.current) == null ? void 0 : i.state) === "recording" ? ((f = L.current) == null || f.pause(), B((Q) => Q + (performance.now() - fe)), T.current && cancelAnimationFrame(T.current), r && r()) : (T.current = requestAnimationFrame(k), (U = L.current) == null || U.resume(), ce(performance.now()), n && n());
return;
}
s.current && pe && (s.current.paused ? te() : re());
}, we = () => {
E.current && cancelAnimationFrame(E.current), Z(!0), s != null && s.current && (s.current.currentTime = 0, q(0), u && u());
}, M = () => {
var f;
if (!O)
return;
const i = document.createElement("a");
i.href = O, i.download = `recorded_audio${at(
(f = L.current) == null ? void 0 : f.mimeType
)}`, document.body.appendChild(i), i.click(), document.body.removeChild(i), URL.revokeObjectURL(O);
};
return {
audioRef: s,
isRecordingInProgress: z,
isPausedRecording: y,
audioData: o,
recordingTime: ie,
isProcessingRecordedAudio: xe,
recordedBlob: $,
mediaRecorder: L.current,
duration: W,
currentAudioTime: oe,
audioSrc: O,
isPausedRecordedAudio: ye,
bufferFromRecordedBlob: A,
isCleared: ae,
isAvailableRecordedAudio: pe,
formattedDuration: Ie,
formattedRecordingTime: Ce,
formattedRecordedAudioCurrentTime: j,
startRecording: $e,
togglePauseResume: C,
startAudioPlayback: te,
stopAudioPlayback: re,
stopRecording: Te,
saveAudioFile: M,
clearCanvas: J,
setCurrentAudioTime: q,
error: Me,
isProcessingOnResize: X,
isProcessingStartRecording: Ae,
isPreloadedBlob: Ee,
setPreloadedAudioBlob: Le,
_setIsProcessingAudioOnComplete: P,
_setIsProcessingOnResize: ze
};
}
export {
Mt as VoiceVisualizer,
pt as useVoiceVisualizer
};