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