streamlit-bar-visualizer 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -60,4 +60,4 @@ Error generating stack: `+s.message+`
60
60
  background-color: var(--background-color);
61
61
  color: var(--text-color);
62
62
  }
63
- `)};function j1(e){var t=!1;try{t=e instanceof BigInt64Array||e instanceof BigUint64Array}catch{}return e instanceof Int8Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array||t}var sg=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,i){r.__proto__=i}||function(r,i){for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(r[s]=i[s])},e(t,n)};return function(t,n){if(typeof n!="function"&&n!==null)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");e(t,n);function r(){this.constructor=t}t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),V1=function(e){sg(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.componentDidMount=function(){$e.setFrameHeight()},t.prototype.componentDidUpdate=function(){$e.setFrameHeight()},t}(fr.PureComponent);function $1(e){var t=function(n){sg(r,n);function r(i){var s=n.call(this,i)||this;return s.componentDidMount=function(){$e.events.addEventListener($e.RENDER_EVENT,s.onRenderEvent),$e.setComponentReady()},s.componentDidUpdate=function(){s.state.componentError!=null&&$e.setFrameHeight()},s.componentWillUnmount=function(){$e.events.removeEventListener($e.RENDER_EVENT,s.onRenderEvent)},s.onRenderEvent=function(o){s.setState({renderData:o.detail})},s.state={renderData:void 0,componentError:void 0},s}return r.prototype.render=function(){return this.state.componentError!=null?fr.createElement("div",null,fr.createElement("h1",null,"Component Error"),fr.createElement("span",null,this.state.componentError.message)):this.state.renderData==null?null:fr.createElement(e,{width:window.innerWidth,disabled:this.state.renderData.disabled,args:this.state.renderData.args,theme:this.state.renderData.theme})},r.getDerivedStateFromError=function(i){return{componentError:i}},r}(fr.PureComponent);return ew(t,e)}function og(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+=e;else if(typeof e=="object")if(Array.isArray(e)){var i=e.length;for(t=0;t<i;t++)e[t]&&(n=og(e[t]))&&(r&&(r+=" "),r+=n)}else for(n in e)e[n]&&(r&&(r+=" "),r+=n);return r}function W1(){for(var e,t,n=0,r="",i=arguments.length;n<i;n++)(e=arguments[n])&&(t=og(e))&&(r&&(r+=" "),r+=t);return r}function lg(...e){return W1(e)}function H1(e,t={}){const n=new(window.AudioContext||window.webkitAudioContext),r=n.createMediaStreamSource(e),i=n.createAnalyser();return t.fftSize&&(i.fftSize=t.fftSize),t.smoothingTimeConstant!==void 0&&(i.smoothingTimeConstant=t.smoothingTimeConstant),t.minDecibels!==void 0&&(i.minDecibels=t.minDecibels),t.maxDecibels!==void 0&&(i.maxDecibels=t.maxDecibels),r.connect(i),{analyser:i,audioContext:n,cleanup:()=>{r.disconnect(),n.close()}}}const Y1={bands:5,loPass:100,hiPass:600,updateInterval:32,analyserOptions:{fftSize:2048}},Q1=e=>{if(e===-1/0)return 0;const r=1-Math.max(-100,Math.min(-10,e))*-1/100;return Math.sqrt(r)};function K1(e,t={}){var l,a,u,c;const n=ht.useMemo(()=>({...Y1,...t}),[t.bands,t.loPass,t.hiPass,t.updateInterval,(l=t.analyserOptions)==null?void 0:l.fftSize,(a=t.analyserOptions)==null?void 0:a.smoothingTimeConstant,(u=t.analyserOptions)==null?void 0:u.minDecibels,(c=t.analyserOptions)==null?void 0:c.maxDecibels]),[r,i]=ht.useState(()=>new Array(n.bands).fill(0)),s=ht.useRef(new Array(n.bands).fill(0)),o=ht.useRef(void 0);return ht.useEffect(()=>{if(!e){const b=new Array(n.bands).fill(0);i(b),s.current=b;return}const{analyser:f,cleanup:m}=H1(e,n.analyserOptions),g=f.frequencyBinCount,v=new Float32Array(g),S=n.loPass,Q=n.hiPass,h=Q-S,d=Math.ceil(h/n.bands);let y=0;const w=n.updateInterval,I=b=>{if(b-y>=w){f.getFloatFrequencyData(v);const E=new Array(n.bands);for(let W=0;W<n.bands;W++){let A=0,Nt=0;const sn=S+W*d,on=Math.min(S+(W+1)*d,Q);for(let Mr=sn;Mr<on;Mr++)A+=Q1(v[Mr]),Nt++;E[W]=Nt>0?A/Nt:0}let O=!1;for(let W=0;W<E.length;W++)if(Math.abs(E[W]-s.current[W])>.01){O=!0;break}O&&(s.current=E,i(E)),y=b}o.current=requestAnimationFrame(I)};return o.current=requestAnimationFrame(I),()=>{m(),o.current&&cancelAnimationFrame(o.current)}},[e,n]),r}const J1=(e,t,n)=>{const r=ht.useRef(0),[i,s]=ht.useState([]),o=ht.useRef(null),l=ht.useMemo(()=>e==="thinking"||e==="listening"?X1(t):e==="connecting"||e==="initializing"?G1(t):e===void 0||e==="speaking"?[new Array(t).fill(0).map((a,u)=>u)]:[[]],[e,t]);return ht.useEffect(()=>{r.current=0,s(l[0]||[])},[l]),ht.useEffect(()=>{let a=performance.now();const u=c=>{c-a>=n&&(r.current=(r.current+1)%l.length,s(l[r.current]||[]),a=c),o.current=requestAnimationFrame(u)};return o.current=requestAnimationFrame(u),()=>{o.current!==null&&cancelAnimationFrame(o.current)}},[n,l]),i},G1=e=>{const t=[];for(let n=0;n<e;n++)t.push([n,e-1-n]);return t},X1=e=>[[Math.floor(e/2)],[-1]],ag=ht.forwardRef(({state:e,barCount:t=15,mediaStream:n,minHeight:r=20,maxHeight:i=100,demo:s=!1,centerAlign:o=!1,className:l,style:a,...u},c)=>{const f=K1(n,{bands:t,loPass:100,hiPass:200}),m=ht.useRef(new Array(t).fill(.2)),[g,v]=ht.useState(()=>new Array(t).fill(.2)),S=ht.useRef(void 0);ht.useEffect(()=>{if(!s)return;if(e!=="speaking"&&e!=="listening"){const b=new Array(t).fill(.2);m.current=b,v(b);return}let d=0;const y=50,w=Date.now()/1e3,I=b=>{if(b-d>=y){const E=Date.now()/1e3-w,O=new Array(t);for(let A=0;A<t;A++){const Nt=A*.5,sn=Math.sin(E*2+Nt)*.3+.5,on=Math.random()*.2;O[A]=Math.max(.1,Math.min(1,sn+on))}let W=!1;for(let A=0;A<t;A++)if(Math.abs(O[A]-m.current[A])>.05){W=!0;break}W&&(m.current=O,v(O)),d=b}S.current=requestAnimationFrame(I)};return S.current=requestAnimationFrame(I),()=>{S.current&&cancelAnimationFrame(S.current)}},[s,e,t]);const Q=ht.useMemo(()=>s?g:f,[s,g,f]),h=J1(e,t,e==="connecting"?2e3/t:e==="thinking"?150:e==="listening"?500:1e3);return Un.jsx("div",{ref:c,"data-state":e,className:lg("relative flex justify-center gap-1.5",o?"items-center":"items-end","bg-muted h-28 w-full overflow-hidden rounded-lg",l),style:{...a},...u,children:Q.map((d,y)=>{const w=Math.min(i,Math.max(r,d*100+5)),I=(h==null?void 0:h.includes(y))??!1;return Un.jsx(ug,{heightPct:w,isHighlighted:I,state:e},y)})})}),ug=ht.memo(({heightPct:e,isHighlighted:t,state:n})=>Un.jsx("div",{"data-highlighted":t,className:lg("max-w-[12px] min-w-[8px] flex-1 transition-all duration-150","rounded-full","bg-border data-[highlighted=true]:bg-primary",n==="speaking"&&"bg-primary",n==="thinking"&&t&&"animate-pulse"),style:{height:`${e}%`,animationDuration:n==="thinking"?"300ms":void 0}}));ug.displayName="Bar";const cg=ht.memo(ag,(e,t)=>e.state===t.state&&e.barCount===t.barCount&&e.mediaStream===t.mediaStream&&e.minHeight===t.minHeight&&e.maxHeight===t.maxHeight&&e.demo===t.demo&&e.centerAlign===t.centerAlign&&e.className===t.className&&JSON.stringify(e.style)===JSON.stringify(t.style));ag.displayName="BarVisualizerComponent";cg.displayName="BarVisualizer";class Z1 extends V1{constructor(){super(...arguments);Re(this,"state",{mediaStream:null,audioState:"idle"});Re(this,"audioRef",ht.createRef());Re(this,"render",()=>{const n=this.props.args.state||"listening",r=this.props.args.barCount||20,i=this.props.args.minHeight||15,s=this.props.args.maxHeight||90,o=this.props.args.demo!==!1,l=this.props.args.centerAlign||!1,a=this.props.args.streamUrl;let u;if(n==="auto"){switch(this.state.audioState){case"loading":u="thinking";break;case"playing":u="speaking";break;case"ended":u="initializing";break;case"idle":default:u="listening";break}console.log("🤖 Auto mode: audioState =",this.state.audioState,"→ displayState =",u)}else u=n;const c=o||a&&!this.state.mediaStream;return a&&!this.state.mediaStream&&console.log("⏳ 音頻加載中... (UI 已顯示,使用假數據動畫,狀態:",u,")"),Un.jsxs("div",{className:"streamlit-bar-visualizer",children:[a&&Un.jsx("audio",{ref:this.audioRef,src:a,controls:!1,autoPlay:!0,crossOrigin:"anonymous",style:{display:"none"}}),Un.jsx(cg,{mediaStream:this.state.mediaStream,state:u,barCount:r,minHeight:i,maxHeight:s,demo:c,centerAlign:l})]})});Re(this,"componentDidMount",async()=>{const n=this.props.args.streamUrl;if(this.props.args.demo,n&&this.audioRef.current){console.log("🎵 Attempting to load audio stream:",n);const r=this.audioRef.current;this.setState({audioState:"loading"}),r.addEventListener("loadstart",this.handleLoadStart),r.addEventListener("playing",this.handlePlaying),r.addEventListener("ended",this.handleEnded);try{await new Promise((s,o)=>{const l=setTimeout(()=>o(new Error("Audio load timeout")),1e4);r.oncanplay=()=>{clearTimeout(l),s(!0)},r.onerror=a=>{var u,c,f;clearTimeout(l),console.error("❌ Audio element error event:",a),console.error(" Error code:",(u=r.error)==null?void 0:u.code),console.error(" Error message:",(c=r.error)==null?void 0:c.message),console.error(" Network state:",r.networkState),console.error(" Ready state:",r.readyState),o(new Error(`Audio load error: ${((f=r.error)==null?void 0:f.message)||"Unknown error"}`))}}),r.muted=!0,await r.play(),console.log("✅ Audio stream is playing (initially muted)"),await new Promise(s=>setTimeout(s,100));const i=r;if(typeof i.captureStream=="function"){const s=i.captureStream();this.setState({mediaStream:s}),console.log("✅ Audio stream captured successfully via captureStream()"),r.muted=!1,console.log("🔊 Audio unmuted - you should now hear the sound")}else if(typeof i.mozCaptureStream=="function"){const s=i.mozCaptureStream();this.setState({mediaStream:s}),console.log("✅ Audio stream captured successfully via mozCaptureStream() (Firefox)"),r.muted=!1,console.log("🔊 Audio unmuted - you should now hear the sound")}else console.error("❌ HTMLAudioElement.captureStream() is not supported in this browser.")}catch(i){console.error("❌ Error playing or capturing audio stream:",i),console.warn("⚠️ Audio stream failed. Not falling back to microphone. Check console for errors.")}}else console.log("🎭 No audio stream provided - running in demo mode (using fake audio data)");$e.setFrameHeight()});Re(this,"componentWillUnmount",()=>{if(this.state.mediaStream&&!this.props.args.streamUrl&&this.state.mediaStream.getTracks().forEach(n=>n.stop()),this.audioRef.current){const n=this.audioRef.current;n.pause(),n.removeEventListener("loadstart",this.handleLoadStart),n.removeEventListener("playing",this.handlePlaying),n.removeEventListener("ended",this.handleEnded)}});Re(this,"componentDidUpdate",async n=>{const r=n.args.streamUrl,i=this.props.args.streamUrl;if(i&&r!==i&&this.audioRef.current){console.log("🔄 Stream URL changed, updating audio source..."),this.setState({mediaStream:null,audioState:"loading"});const s=this.audioRef.current;s.removeEventListener("loadstart",this.handleLoadStart),s.removeEventListener("playing",this.handlePlaying),s.removeEventListener("ended",this.handleEnded),s.addEventListener("loadstart",this.handleLoadStart),s.addEventListener("playing",this.handlePlaying),s.addEventListener("ended",this.handleEnded),s.src=i;try{s.muted=!0,await s.play();const o=s;if(typeof o.captureStream=="function"){const l=o.captureStream();this.setState({mediaStream:l}),console.log("✅ Audio stream updated and captured successfully"),s.muted=!1,console.log("🔊 Audio unmuted")}else if(typeof o.mozCaptureStream=="function"){const l=o.mozCaptureStream();this.setState({mediaStream:l}),console.log("✅ Audio stream updated and captured successfully (Firefox)"),s.muted=!1,console.log("🔊 Audio unmuted")}}catch(o){console.error("❌ Error updating audio stream:",o)}}$e.setFrameHeight()});Re(this,"handleLoadStart",()=>{console.log("📥 Audio loadstart"),this.setState({audioState:"loading"})});Re(this,"handlePlaying",()=>{console.log("▶️ Audio playing"),this.setState({audioState:"playing"})});Re(this,"handleEnded",()=>{console.log("⏹️ Audio ended"),this.setState({audioState:"ended"})})}}const q1=$1(Z1);zv.render(Un.jsx(fr.StrictMode,{children:Un.jsx(q1,{})}),document.getElementById("root"));
63
+ `)};function j1(e){var t=!1;try{t=e instanceof BigInt64Array||e instanceof BigUint64Array}catch{}return e instanceof Int8Array||e instanceof Uint8Array||e instanceof Uint8ClampedArray||e instanceof Int16Array||e instanceof Uint16Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Float32Array||e instanceof Float64Array||t}var sg=function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,i){r.__proto__=i}||function(r,i){for(var s in i)Object.prototype.hasOwnProperty.call(i,s)&&(r[s]=i[s])},e(t,n)};return function(t,n){if(typeof n!="function"&&n!==null)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");e(t,n);function r(){this.constructor=t}t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}}(),V1=function(e){sg(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.componentDidMount=function(){$e.setFrameHeight()},t.prototype.componentDidUpdate=function(){$e.setFrameHeight()},t}(fr.PureComponent);function $1(e){var t=function(n){sg(r,n);function r(i){var s=n.call(this,i)||this;return s.componentDidMount=function(){$e.events.addEventListener($e.RENDER_EVENT,s.onRenderEvent),$e.setComponentReady()},s.componentDidUpdate=function(){s.state.componentError!=null&&$e.setFrameHeight()},s.componentWillUnmount=function(){$e.events.removeEventListener($e.RENDER_EVENT,s.onRenderEvent)},s.onRenderEvent=function(o){s.setState({renderData:o.detail})},s.state={renderData:void 0,componentError:void 0},s}return r.prototype.render=function(){return this.state.componentError!=null?fr.createElement("div",null,fr.createElement("h1",null,"Component Error"),fr.createElement("span",null,this.state.componentError.message)):this.state.renderData==null?null:fr.createElement(e,{width:window.innerWidth,disabled:this.state.renderData.disabled,args:this.state.renderData.args,theme:this.state.renderData.theme})},r.getDerivedStateFromError=function(i){return{componentError:i}},r}(fr.PureComponent);return ew(t,e)}function og(e){var t,n,r="";if(typeof e=="string"||typeof e=="number")r+=e;else if(typeof e=="object")if(Array.isArray(e)){var i=e.length;for(t=0;t<i;t++)e[t]&&(n=og(e[t]))&&(r&&(r+=" "),r+=n)}else for(n in e)e[n]&&(r&&(r+=" "),r+=n);return r}function W1(){for(var e,t,n=0,r="",i=arguments.length;n<i;n++)(e=arguments[n])&&(t=og(e))&&(r&&(r+=" "),r+=t);return r}function lg(...e){return W1(e)}function H1(e,t={}){const n=new(window.AudioContext||window.webkitAudioContext),r=n.createMediaStreamSource(e),i=n.createAnalyser();return t.fftSize&&(i.fftSize=t.fftSize),t.smoothingTimeConstant!==void 0&&(i.smoothingTimeConstant=t.smoothingTimeConstant),t.minDecibels!==void 0&&(i.minDecibels=t.minDecibels),t.maxDecibels!==void 0&&(i.maxDecibels=t.maxDecibels),r.connect(i),{analyser:i,audioContext:n,cleanup:()=>{r.disconnect(),n.close()}}}const Y1={bands:5,loPass:100,hiPass:600,updateInterval:32,analyserOptions:{fftSize:2048}},Q1=e=>{if(e===-1/0)return 0;const r=1-Math.max(-100,Math.min(-10,e))*-1/100;return Math.sqrt(r)};function K1(e,t={}){var l,a,u,c;const n=ht.useMemo(()=>({...Y1,...t}),[t.bands,t.loPass,t.hiPass,t.updateInterval,(l=t.analyserOptions)==null?void 0:l.fftSize,(a=t.analyserOptions)==null?void 0:a.smoothingTimeConstant,(u=t.analyserOptions)==null?void 0:u.minDecibels,(c=t.analyserOptions)==null?void 0:c.maxDecibels]),[r,i]=ht.useState(()=>new Array(n.bands).fill(0)),s=ht.useRef(new Array(n.bands).fill(0)),o=ht.useRef(void 0);return ht.useEffect(()=>{if(!e){const b=new Array(n.bands).fill(0);i(b),s.current=b;return}const{analyser:f,cleanup:m}=H1(e,n.analyserOptions),g=f.frequencyBinCount,v=new Float32Array(g),S=n.loPass,Q=n.hiPass,h=Q-S,d=Math.ceil(h/n.bands);let y=0;const w=n.updateInterval,I=b=>{if(b-y>=w){f.getFloatFrequencyData(v);const E=new Array(n.bands);for(let W=0;W<n.bands;W++){let A=0,Nt=0;const sn=S+W*d,on=Math.min(S+(W+1)*d,Q);for(let Mr=sn;Mr<on;Mr++)A+=Q1(v[Mr]),Nt++;E[W]=Nt>0?A/Nt:0}let O=!1;for(let W=0;W<E.length;W++)if(Math.abs(E[W]-s.current[W])>.01){O=!0;break}O&&(s.current=E,i(E)),y=b}o.current=requestAnimationFrame(I)};return o.current=requestAnimationFrame(I),()=>{m(),o.current&&cancelAnimationFrame(o.current)}},[e,n]),r}const J1=(e,t,n)=>{const r=ht.useRef(0),[i,s]=ht.useState([]),o=ht.useRef(null),l=ht.useMemo(()=>e==="thinking"||e==="listening"?X1(t):e==="connecting"||e==="initializing"?G1(t):e===void 0||e==="speaking"?[new Array(t).fill(0).map((a,u)=>u)]:[[]],[e,t]);return ht.useEffect(()=>{r.current=0,s(l[0]||[])},[l]),ht.useEffect(()=>{let a=performance.now();const u=c=>{c-a>=n&&(r.current=(r.current+1)%l.length,s(l[r.current]||[]),a=c),o.current=requestAnimationFrame(u)};return o.current=requestAnimationFrame(u),()=>{o.current!==null&&cancelAnimationFrame(o.current)}},[n,l]),i},G1=e=>{const t=[];for(let n=0;n<e;n++)t.push([n,e-1-n]);return t},X1=e=>[[Math.floor(e/2)],[-1]],ag=ht.forwardRef(({state:e,barCount:t=15,mediaStream:n,minHeight:r=20,maxHeight:i=100,demo:s=!1,centerAlign:o=!1,className:l,style:a,...u},c)=>{const f=K1(n,{bands:t,loPass:100,hiPass:200}),m=ht.useRef(new Array(t).fill(.2)),[g,v]=ht.useState(()=>new Array(t).fill(.2)),S=ht.useRef(void 0);ht.useEffect(()=>{if(!s)return;if(e!=="speaking"&&e!=="listening"){const b=new Array(t).fill(.2);m.current=b,v(b);return}let d=0;const y=50,w=Date.now()/1e3,I=b=>{if(b-d>=y){const E=Date.now()/1e3-w,O=new Array(t);for(let A=0;A<t;A++){const Nt=A*.5,sn=Math.sin(E*2+Nt)*.3+.5,on=Math.random()*.2;O[A]=Math.max(.1,Math.min(1,sn+on))}let W=!1;for(let A=0;A<t;A++)if(Math.abs(O[A]-m.current[A])>.05){W=!0;break}W&&(m.current=O,v(O)),d=b}S.current=requestAnimationFrame(I)};return S.current=requestAnimationFrame(I),()=>{S.current&&cancelAnimationFrame(S.current)}},[s,e,t]);const Q=ht.useMemo(()=>s?g:f,[s,g,f]),h=J1(e,t,e==="connecting"?2e3/t:e==="thinking"?150:e==="listening"?500:1e3);return Un.jsx("div",{ref:c,"data-state":e,className:lg("relative flex justify-center gap-1.5",o?"items-center":"items-end","bg-muted h-28 w-full overflow-hidden rounded-lg",l),style:{...a},...u,children:Q.map((d,y)=>{const w=Math.min(i,Math.max(r,d*100+5)),I=(h==null?void 0:h.includes(y))??!1;return Un.jsx(ug,{heightPct:w,isHighlighted:I,state:e},y)})})}),ug=ht.memo(({heightPct:e,isHighlighted:t,state:n})=>Un.jsx("div",{"data-highlighted":t,className:lg("max-w-[12px] min-w-[8px] flex-1 transition-all duration-150","rounded-full","bg-border data-[highlighted=true]:bg-primary",n==="speaking"&&"bg-primary",n==="thinking"&&t&&"animate-pulse"),style:{height:`${e}%`,animationDuration:n==="thinking"?"300ms":void 0}}));ug.displayName="Bar";const cg=ht.memo(ag,(e,t)=>e.state===t.state&&e.barCount===t.barCount&&e.mediaStream===t.mediaStream&&e.minHeight===t.minHeight&&e.maxHeight===t.maxHeight&&e.demo===t.demo&&e.centerAlign===t.centerAlign&&e.className===t.className&&JSON.stringify(e.style)===JSON.stringify(t.style));ag.displayName="BarVisualizerComponent";cg.displayName="BarVisualizer";class Z1 extends V1{constructor(){super(...arguments);Re(this,"state",{mediaStream:null,audioState:"idle"});Re(this,"audioRef",ht.createRef());Re(this,"render",()=>{const n=this.props.args.state||"listening",r=this.props.args.barCount||20,i=this.props.args.minHeight||15,s=this.props.args.maxHeight||90,o=this.props.args.demo!==!1,l=this.props.args.centerAlign||!1,a=this.props.args.streamUrl;let u;if(n==="auto"){switch(this.state.audioState){case"loading":u="thinking";break;case"playing":u="speaking";break;case"ended":u="initializing";break;case"idle":default:u="listening";break}console.log("🤖 Auto mode: audioState =",this.state.audioState,"→ displayState =",u)}else u=n;const c=o||a&&!this.state.mediaStream;return a&&!this.state.mediaStream&&console.log("⏳ 音頻加載中... (UI 已顯示,使用假數據動畫,狀態:",u,")"),Un.jsxs("div",{className:"streamlit-bar-visualizer",children:[a&&Un.jsx("audio",{ref:this.audioRef,src:a,controls:!1,autoPlay:!0,crossOrigin:"anonymous",style:{display:"none"}}),Un.jsx(cg,{mediaStream:this.state.mediaStream,state:u,barCount:r,minHeight:i,maxHeight:s,demo:c,centerAlign:l})]})});Re(this,"componentDidMount",async()=>{const n=this.props.args.streamUrl;if(this.props.args.demo,n&&this.audioRef.current){console.log("🎵 Attempting to load audio stream:",n);const r=this.audioRef.current;this.setState({audioState:"loading"}),r.addEventListener("loadstart",this.handleLoadStart),r.addEventListener("playing",this.handlePlaying),r.addEventListener("ended",this.handleEnded);try{await new Promise((s,o)=>{const l=setTimeout(()=>o(new Error("Audio load timeout")),1e4);r.oncanplay=()=>{clearTimeout(l),s(!0)},r.onerror=a=>{var u,c,f;clearTimeout(l),console.error("❌ Audio element error event:",a),console.error(" Error code:",(u=r.error)==null?void 0:u.code),console.error(" Error message:",(c=r.error)==null?void 0:c.message),console.error(" Network state:",r.networkState),console.error(" Ready state:",r.readyState),o(new Error(`Audio load error: ${((f=r.error)==null?void 0:f.message)||"Unknown error"}`))}}),r.muted=!0,await r.play(),console.log("✅ Audio stream is playing (initially muted)"),await new Promise(s=>setTimeout(s,100));const i=r;if(typeof i.captureStream=="function"){const s=i.captureStream();this.setState({mediaStream:s}),console.log("✅ Audio stream captured successfully via captureStream()"),r.muted=!1,console.log("🔊 Audio unmuted - you should now hear the sound")}else if(typeof i.mozCaptureStream=="function"){const s=i.mozCaptureStream();this.setState({mediaStream:s}),console.log("✅ Audio stream captured successfully via mozCaptureStream() (Firefox)"),r.muted=!1,console.log("🔊 Audio unmuted - you should now hear the sound")}else console.error("❌ HTMLAudioElement.captureStream() is not supported in this browser."),r.muted=!1,console.warn("⚠️ Audio unmuted but visualization will use demo mode")}catch(i){console.error("❌ Error playing or capturing audio stream:",i),console.warn("⚠️ Audio stream failed. Not falling back to microphone. Check console for errors.")}}else console.log("🎭 No audio stream provided - running in demo mode (using fake audio data)");$e.setFrameHeight()});Re(this,"componentWillUnmount",()=>{if(this.state.mediaStream&&!this.props.args.streamUrl&&this.state.mediaStream.getTracks().forEach(n=>n.stop()),this.audioRef.current){const n=this.audioRef.current;n.pause(),n.removeEventListener("loadstart",this.handleLoadStart),n.removeEventListener("playing",this.handlePlaying),n.removeEventListener("ended",this.handleEnded)}});Re(this,"componentDidUpdate",async n=>{const r=n.args.streamUrl,i=this.props.args.streamUrl,s=r!==i;if(i&&this.audioRef.current&&(s||this.state.audioState==="ended")){console.log("🔄 Reloading audio:",s?"URL changed":"Replay same URL"),this.setState({mediaStream:null,audioState:"loading"});const l=this.audioRef.current;l.removeEventListener("loadstart",this.handleLoadStart),l.removeEventListener("playing",this.handlePlaying),l.removeEventListener("ended",this.handleEnded),l.addEventListener("loadstart",this.handleLoadStart),l.addEventListener("playing",this.handlePlaying),l.addEventListener("ended",this.handleEnded),s?l.src=i:l.load();try{l.muted=!0,await l.play();const a=l;if(typeof a.captureStream=="function"){const u=a.captureStream();this.setState({mediaStream:u}),console.log("✅ Audio stream updated and captured successfully"),l.muted=!1,console.log("🔊 Audio unmuted")}else if(typeof a.mozCaptureStream=="function"){const u=a.mozCaptureStream();this.setState({mediaStream:u}),console.log("✅ Audio stream updated and captured successfully (Firefox)"),l.muted=!1,console.log("🔊 Audio unmuted")}else l.muted=!1,console.warn("⚠️ captureStream not supported, audio unmuted but using demo visualization")}catch(a){console.error("❌ Error updating audio stream:",a)}}$e.setFrameHeight()});Re(this,"handleLoadStart",()=>{console.log("📥 Audio loadstart"),this.setState({audioState:"loading"})});Re(this,"handlePlaying",()=>{console.log("▶️ Audio playing"),this.setState({audioState:"playing"})});Re(this,"handleEnded",()=>{console.log("⏹️ Audio ended"),this.setState({audioState:"ended"})})}}const q1=$1(Z1);zv.render(Un.jsx(fr.StrictMode,{children:Un.jsx(q1,{})}),document.getElementById("root"));
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: streamlit-bar-visualizer
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Beautiful audio frequency visualizer component for Streamlit with multiple state animations
5
5
  Home-page: https://github.com/bensonbs/streamlit-bar-visualizer
6
6
  Author: Benson Sung
@@ -35,24 +35,46 @@ pip install streamlit-bar-visualizer
35
35
  ## Quick Start
36
36
 
37
37
  ```python
38
+ import streamlit as st
38
39
  from streamlit_bar_visualizer import bar_visualizer
39
-
40
- # Basic usage
41
- bar_visualizer(state="listening")
42
-
43
- # With audio stream
44
- bar_visualizer(
45
- state="speaking",
46
- stream_url="https://stream.live.vc.bbcmedia.co.uk/bbc_world_service"
47
- )
48
-
49
- # Auto mode - automatically changes state based on audio playback
50
- bar_visualizer(
51
- state="auto",
52
- stream_url="https://stream.live.vc.bbcmedia.co.uk/bbc_world_service"
53
- )
40
+ import time
41
+
42
+ st.title("🎵 Audio Stream Visualizer Test")
43
+
44
+ # Session state
45
+ if 'play_count' not in st.session_state:
46
+ st.session_state.play_count = 0
47
+
48
+ # Audio stream options
49
+ stream_options = {
50
+ "Radio Paradise (MP3)": "https://stream.radioparadise.com/mp3-128",
51
+ "BBC World Service": "https://stream.live.vc.bbcmedia.co.uk/bbc_world_service",
52
+ "Custom URL": "custom"
53
+ }
54
+
55
+ selected_stream = st.selectbox("Select Audio Stream", list(stream_options.keys()))
56
+
57
+ if selected_stream == "Custom URL":
58
+ stream_url = st.text_input("Enter Audio Stream URL", value="https://stream.radioparadise.com/mp3-128")
59
+ else:
60
+ stream_url = stream_options[selected_stream]
61
+
62
+ st.info(f"🎧 Current Audio Stream: {stream_url}")
63
+
64
+ # Display visualizer
65
+ if stream_url:
66
+ bar_visualizer(
67
+ state="auto",
68
+ stream_url=stream_url,
69
+ key=f"visualizer_{st.session_state.play_count}"
70
+ )
71
+
72
+ st.markdown("---")
73
+ st.caption("💡 Tip: If you don't hear sound, check the browser console (F12) for error messages and verify the audio stream URL is valid.")
54
74
  ```
55
75
 
76
+ > ⚠️ **Browser Compatibility Warning**: Safari may have issues with audio streaming due to CORS restrictions. For best results, use **Chrome** or **Firefox**.
77
+
56
78
  ## API
57
79
 
58
80
  ### `bar_visualizer(state, stream_url, key)`
@@ -1,9 +1,9 @@
1
1
  streamlit_bar_visualizer/__init__.py,sha256=bDQ10bZ1IsdfnbBkB-y0O4Uj1fP3PTQEcTfVf3qBE8M,2013
2
2
  streamlit_bar_visualizer/frontend/build/index.html,sha256=TqAEiSYvx2vAtYQx9r2i0dsah95I4WdfdCW2JV_O1vM,598
3
3
  streamlit_bar_visualizer/frontend/build/static/css/index.css,sha256=M205TwzT_QEOI6uyDeRzooIp2urgja9MYT6ikpZNre8,6039
4
- streamlit_bar_visualizer/frontend/build/static/js/index.js,sha256=YN5RuJWW3WdUZjLGry_dB0tZJH7Qs-1e2Q_c1ZJ2hMA,331640
5
- streamlit_bar_visualizer-0.1.2.dist-info/licenses/LICENSE,sha256=oBpTnAC3ct8S_vuOoH35czaCc1bSnaais7nHEMXmYEU,1057
6
- streamlit_bar_visualizer-0.1.2.dist-info/METADATA,sha256=ky1osuT4VcAlQFXlm_Jgges1ZaIDA8cFRudV25sL2kk,2307
7
- streamlit_bar_visualizer-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- streamlit_bar_visualizer-0.1.2.dist-info/top_level.txt,sha256=R4FUZSzrl89iY_k-j8NYeJ7PMEjY570wyJsIeTMHcVQ,25
9
- streamlit_bar_visualizer-0.1.2.dist-info/RECORD,,
4
+ streamlit_bar_visualizer/frontend/build/static/js/index.js,sha256=RdxE9sfdAR-2icdqJ2N2l2Tc3jZ5MK2mp3nHV52tJ9g,331891
5
+ streamlit_bar_visualizer-0.1.4.dist-info/licenses/LICENSE,sha256=oBpTnAC3ct8S_vuOoH35czaCc1bSnaais7nHEMXmYEU,1057
6
+ streamlit_bar_visualizer-0.1.4.dist-info/METADATA,sha256=8Oguo_b2aA86pJrCsdIpVq7U_MY3hWPFV-he4KxnI-w,3190
7
+ streamlit_bar_visualizer-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ streamlit_bar_visualizer-0.1.4.dist-info/top_level.txt,sha256=R4FUZSzrl89iY_k-j8NYeJ7PMEjY570wyJsIeTMHcVQ,25
9
+ streamlit_bar_visualizer-0.1.4.dist-info/RECORD,,