[{"data":1,"prerenderedAt":586},["ShallowReactive",2],{"navigation_docs":3,"-getting-started-data-modes":47,"-getting-started-data-modes-surround":581},[4,26],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting Started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Data modes","\u002Fgetting-started\u002Fdata-modes","1.getting-started\u002F3.data-modes","i-lucide-git-fork",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Reference","i-lucide-book-open","\u002Freference","2.reference",[32,37,42],{"title":33,"path":34,"stem":35,"icon":36},"Props, events & methods","\u002Freference\u002Fprops","2.reference\u002F1.props","i-lucide-sliders-horizontal",{"title":38,"path":39,"stem":40,"icon":41},"Gradients","\u002Freference\u002Fgradients","2.reference\u002F2.gradients","i-lucide-palette",{"title":43,"path":44,"stem":45,"icon":46},"Composables & protocol","\u002Freference\u002Fcomposables","2.reference\u002F3.composables","i-lucide-plug",{"id":48,"title":21,"body":49,"description":574,"extension":575,"links":576,"meta":577,"navigation":578,"path":22,"seo":579,"stem":23,"__hash__":580},"docs\u002F1.getting-started\u002F3.data-modes.md",{"type":50,"value":51,"toc":569},"minimark",[52,61,148,153,221,228,232,316,329,343,347,362,543,565],[53,54,55,56,60],"p",{},"The component has one job — render a spectrum — and three ways to get the data, selected\nwith the ",[57,58,59],"code",{},"mode"," prop.",[62,63,64,80],"table",{},[65,66,67],"thead",{},[68,69,70,74,77],"tr",{},[71,72,73],"th",{},"Mode",[71,75,76],{},"How data arrives",[71,78,79],{},"Use when",[81,82,83,97,124],"tbody",{},[68,84,85,91,94],{},[86,87,88],"td",{},[57,89,90],{},"local",[86,92,93],{},"Captures mic or display audio and computes the FFT in-browser (Rust\u002FWASM)",[86,95,96],{},"You want a zero-backend, client-side visualizer",[68,98,99,109,121],{},[86,100,101,104,105],{},[57,102,103],{},"websocket"," ",[106,107,108],"em",{},"(default)",[86,110,111,112,115,116,120],{},"Connects to ",[57,113,114],{},"websocketUrl"," and reads ",[117,118,119],"strong",{},"pre-computed"," FFT frames",[86,122,123],{},"A server\u002Fdevice already produces FFT data (e.g. a Raspberry Pi)",[68,125,126,131,145],{},[86,127,128],{},[57,129,130],{},"external",[86,132,133,134,137,138,137,141,144],{},"You pass FFT magnitudes via the ",[57,135,136],{},"data"," \u002F ",[57,139,140],{},"dataLeft",[57,142,143],{},"dataRight"," props",[86,146,147],{},"You have your own audio pipeline (Web Audio, another analyser, etc.)",[149,150,152],"h2",{"id":151},"local-mode","Local mode",[154,155,160],"pre",{"className":156,"code":157,"language":158,"meta":159,"style":159},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003CFFTVisualizer mode=\"local\" audio-source=\"mic\" :bands=\"80\" \u002F>\n","vue","",[57,161,162],{"__ignoreMap":159},[163,164,167,171,175,179,182,185,188,190,193,195,197,200,202,205,208,210,212,216,218],"span",{"class":165,"line":166},"line",1,[163,168,170],{"class":169},"sMK4o","\u003C",[163,172,174],{"class":173},"swJcz","FFTVisualizer",[163,176,178],{"class":177},"spNyl"," mode",[163,180,181],{"class":169},"=",[163,183,184],{"class":169},"\"",[163,186,90],{"class":187},"sfazB",[163,189,184],{"class":169},[163,191,192],{"class":177}," audio-source",[163,194,181],{"class":169},[163,196,184],{"class":169},[163,198,199],{"class":187},"mic",[163,201,184],{"class":169},[163,203,204],{"class":169}," :",[163,206,207],{"class":177},"bands",[163,209,181],{"class":169},[163,211,184],{"class":169},[163,213,215],{"class":214},"sbssI","80",[163,217,184],{"class":169},[163,219,220],{"class":169}," \u002F>\n",[53,222,223,224,227],{},"Set ",[57,225,226],{},"audio-source=\"display\""," to capture tab\u002Fsystem audio via screen sharing instead of the\nmicrophone.",[149,229,231],{"id":230},"websocket-mode","WebSocket mode",[154,233,235],{"className":156,"code":234,"language":158,"meta":159,"style":159},"\u003CFFTVisualizer\n  mode=\"websocket\"\n  websocket-url=\"wss:\u002F\u002Fyour-server\u002Ffft\"\n  :bands=\"40\"\n  :auto-reconnect=\"true\"\n\u002F>\n",[57,236,237,244,259,274,291,309],{"__ignoreMap":159},[163,238,239,241],{"class":165,"line":166},[163,240,170],{"class":169},[163,242,243],{"class":173},"FFTVisualizer\n",[163,245,247,250,252,254,256],{"class":165,"line":246},2,[163,248,249],{"class":177},"  mode",[163,251,181],{"class":169},[163,253,184],{"class":169},[163,255,103],{"class":187},[163,257,258],{"class":169},"\"\n",[163,260,262,265,267,269,272],{"class":165,"line":261},3,[163,263,264],{"class":177},"  websocket-url",[163,266,181],{"class":169},[163,268,184],{"class":169},[163,270,271],{"class":187},"wss:\u002F\u002Fyour-server\u002Ffft",[163,273,258],{"class":169},[163,275,277,280,282,284,286,289],{"class":165,"line":276},4,[163,278,279],{"class":169},"  :",[163,281,207],{"class":177},[163,283,181],{"class":169},[163,285,184],{"class":169},[163,287,288],{"class":214},"40",[163,290,258],{"class":169},[163,292,294,296,299,301,303,307],{"class":165,"line":293},5,[163,295,279],{"class":169},[163,297,298],{"class":177},"auto-reconnect",[163,300,181],{"class":169},[163,302,184],{"class":169},[163,304,306],{"class":305},"sfNiH","true",[163,308,258],{"class":169},[163,310,312],{"class":165,"line":311},6,[163,313,315],{"class":314},"sTEyZ","\u002F>\n",[53,317,318,319,324,325,328],{},"The server streams a small config message then binary FFT frames — see the\n",[320,321,323],"a",{"href":322},"\u002Freference\u002Fcomposables#websocket-protocol","WebSocket protocol"," guide. Reference servers\nfor Python, Node.js and Rust are in the repository's ",[57,326,327],{},"backend-examples\u002F",".",[330,331,332,333,338,339,342],"warning",{},"On an HTTPS page you must use a ",[117,334,335],{},[57,336,337],{},"wss:\u002F\u002F"," URL — browsers block insecure ",[57,340,341],{},"ws:\u002F\u002F"," from\nsecure pages as mixed content.",[149,344,346],{"id":345},"external-mode","External mode",[53,348,349,350,353,354,356,357,359,360,328],{},"Pass a ",[57,351,352],{},"Uint8Array"," of magnitudes (0–255); update it and the visual follows. For stereo,\npass ",[57,355,140],{}," and ",[57,358,143],{}," instead of ",[57,361,136],{},[154,363,365],{"className":156,"code":364,"language":158,"meta":159,"style":159},"\u003Cscript setup>\nimport { ref } from 'vue'\nimport { FFTVisualizer } from 'vue-fft-visualizer'\n\nconst data = ref(new Uint8Array(80))\n\u002F\u002F ...fill data.value from your own analyser each frame\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CFFTVisualizer mode=\"external\" :data=\"data\" :bands=\"40\" \u002F>\n\u003C\u002Ftemplate>\n",[57,366,367,380,406,426,432,461,467,477,482,492,534],{"__ignoreMap":159},[163,368,369,371,374,377],{"class":165,"line":166},[163,370,170],{"class":169},[163,372,373],{"class":173},"script",[163,375,376],{"class":177}," setup",[163,378,379],{"class":169},">\n",[163,381,382,386,389,392,395,398,401,403],{"class":165,"line":246},[163,383,385],{"class":384},"s7zQu","import",[163,387,388],{"class":169}," {",[163,390,391],{"class":314}," ref",[163,393,394],{"class":169}," }",[163,396,397],{"class":384}," from",[163,399,400],{"class":169}," '",[163,402,158],{"class":187},[163,404,405],{"class":169},"'\n",[163,407,408,410,412,415,417,419,421,424],{"class":165,"line":261},[163,409,385],{"class":384},[163,411,388],{"class":169},[163,413,414],{"class":314}," FFTVisualizer",[163,416,394],{"class":169},[163,418,397],{"class":384},[163,420,400],{"class":169},[163,422,423],{"class":187},"vue-fft-visualizer",[163,425,405],{"class":169},[163,427,428],{"class":165,"line":276},[163,429,431],{"emptyLinePlaceholder":430},true,"\n",[163,433,434,437,440,442,445,448,451,454,456,458],{"class":165,"line":293},[163,435,436],{"class":177},"const",[163,438,439],{"class":314}," data ",[163,441,181],{"class":169},[163,443,391],{"class":444},"s2Zo4",[163,446,447],{"class":314},"(",[163,449,450],{"class":169},"new",[163,452,453],{"class":444}," Uint8Array",[163,455,447],{"class":314},[163,457,215],{"class":214},[163,459,460],{"class":314},"))\n",[163,462,463],{"class":165,"line":311},[163,464,466],{"class":465},"sHwdD","\u002F\u002F ...fill data.value from your own analyser each frame\n",[163,468,470,473,475],{"class":165,"line":469},7,[163,471,472],{"class":169},"\u003C\u002F",[163,474,373],{"class":173},[163,476,379],{"class":169},[163,478,480],{"class":165,"line":479},8,[163,481,431],{"emptyLinePlaceholder":430},[163,483,485,487,490],{"class":165,"line":484},9,[163,486,170],{"class":169},[163,488,489],{"class":173},"template",[163,491,379],{"class":169},[163,493,495,498,500,502,504,506,508,510,513,515,517,519,521,524,526,528,530,532],{"class":165,"line":494},10,[163,496,497],{"class":169},"  \u003C",[163,499,174],{"class":173},[163,501,178],{"class":177},[163,503,181],{"class":169},[163,505,184],{"class":169},[163,507,130],{"class":187},[163,509,184],{"class":169},[163,511,512],{"class":177}," :data",[163,514,181],{"class":169},[163,516,184],{"class":169},[163,518,136],{"class":187},[163,520,184],{"class":169},[163,522,523],{"class":177}," :bands",[163,525,181],{"class":169},[163,527,184],{"class":169},[163,529,288],{"class":187},[163,531,184],{"class":169},[163,533,220],{"class":169},[163,535,537,539,541],{"class":165,"line":536},11,[163,538,472],{"class":169},[163,540,489],{"class":173},[163,542,379],{"class":169},[544,545,546,547,549,550,553,554,556,557,560,561,328],"tip",{},"The ",[57,548,136],{}," prop is watched ",[117,551,552],{},"by reference",". If you mutate the same ",[57,555,352],{}," in place\neach frame, Vue won't detect the change — either assign a fresh array, or call the exposed\n",[57,558,559],{},"feedData()"," method (which copies the data). See ",[320,562,564],{"href":563},"\u002Freference\u002Fprops#exposed-methods","Events & methods",[566,567,568],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":159,"searchDepth":246,"depth":246,"links":570},[571,572,573],{"id":151,"depth":246,"text":152},{"id":230,"depth":246,"text":231},{"id":345,"depth":246,"text":346},"The three ways to get audio data into the visualizer — local, WebSocket, and external.","md",null,{},{"icon":24},{"title":21,"description":574},"Fj5cqutur2_lr2zx82xJ-ZUy_sMbpiwRWA-f7A0s-yk",[582,584],{"title":16,"path":17,"stem":18,"description":583,"icon":19,"children":-1},"Install the package and render your first spectrum in under a minute.",{"title":33,"path":34,"stem":35,"description":585,"icon":36,"children":-1},"The complete component API — every prop, event, exposed method, and slot.",1784469224092]