File size: 7,617 Bytes
5e80190
1
{"version":3,"sources":["StreamlitAudioRecorder.tsx","index.tsx"],"names":["StAudioRec","state","isFocused","recordState","audioDataURL","reset","render","theme","props","style","borderStyling","primaryColor","border","outline","id","onClick","onClick_start","onClick_stop","onClick_reset","onClick_continue","onStop","onStop_audio","type","backgroundColor","foregroundColor","canvasWidth","canvasHeight","controls","src","setState","RecordState","START","Streamlit","setComponentValue","STOP","datetime","Date","toLocaleString","filename","replace","a","document","createElement","display","href","download","body","appendChild","click","data","url","fetch","then","ctx","blob","Response","arrayBuffer","buffer","Uint8Array","StreamlitComponentBase","withStreamlitConnection","setComponentReady","setFrameHeight","ReactDOM","StrictMode","getElementById"],"mappings":"wQAiBMA,G,kNACGC,MAAQ,CAAEC,WAAW,EAAOC,YAAa,KAAMC,aAAc,GAAIC,OAAO,G,EAExEC,OAAS,WAMd,IAAQC,EAAU,EAAKC,MAAfD,MACFE,EAA6B,GAE3BN,EAAgB,EAAKF,MAArBE,YAGR,GAAII,EAAO,CAGT,IAAMG,EAAa,oBACjB,EAAKT,MAAMC,UAAYK,EAAMI,aAAe,QAC9CF,EAAMG,OAASF,EACfD,EAAMI,QAAUH,EAGlB,OACE,8BACE,6BACE,4BAAQI,GAAG,SAASC,QAAS,EAAKC,eAAlC,mBAGA,4BAAQF,GAAG,OAAOC,QAAS,EAAKE,cAAhC,QAGA,4BAAQH,GAAG,QAAQC,QAAS,EAAKG,eAAjC,SAIA,4BAAQJ,GAAG,WAAWC,QAAS,EAAKI,kBAApC,YAIA,kBAAC,IAAD,CACElB,MAAOE,EACPiB,OAAQ,EAAKC,aACbC,KAAK,YACLC,gBAAgB,qBAChBC,gBAAgB,iBAChBC,YAAa,IACbC,aAAc,MAGhB,2BACEZ,GAAG,QACHa,UAAQ,EACRC,IAAK,EAAK3B,MAAMG,kB,EASlBY,cAAgB,WACtB,EAAKa,SAAS,CACZxB,OAAO,EACPD,aAAc,GACdD,YAAa2B,IAAYC,QAE3BC,IAAUC,kBAAkB,K,EAGtBhB,aAAe,WACrB,EAAKY,SAAS,CACZxB,OAAO,EACPF,YAAa2B,IAAYI,Q,EAIrBhB,cAAgB,WACtB,EAAKW,SAAS,CACZxB,OAAO,EACPD,aAAc,GACdD,YAAa2B,IAAYI,OAE3BF,IAAUC,kBAAkB,K,EAGtBd,iBAAmB,WACzB,GAAgC,KAA5B,EAAKlB,MAAMG,aACf,CAEE,IAAI+B,GAAW,IAAIC,MAAOC,iBAItBC,EAAW,oBADfH,GADAA,GADAA,EAAWA,EAASI,QAAQ,IAAK,KACbA,QAAQ,KAAM,KACdA,QAAQ,IAAK,KACc,OAGzCC,EAAIC,SAASC,cAAc,KACjCF,EAAE/B,MAAMkC,QAAU,OAClBH,EAAEI,KAAO,EAAK3C,MAAMG,aACpBoC,EAAEK,SAAWP,EACbG,SAASK,KAAKC,YAAYP,GAC1BA,EAAEQ,U,EAIE3B,aAAe,SAAC4B,IACG,IAArB,EAAKhD,MAAMI,OAEb,EAAKwB,SAAS,CACZzB,aAAc,KAEhB4B,IAAUC,kBAAkB,MAE5B,EAAKJ,SAAS,CACZzB,aAAc6C,EAAKC,MAGrBC,MAAMF,EAAKC,KAAKE,MAAK,SAASC,GAC5B,OAAOA,EAAIC,UACVF,MAAK,SAASE,GAGf,OAAQ,IAAIC,SAASD,GAAOE,iBAC3BJ,MAAK,SAASK,GACfzB,IAAUC,kBAAkB,CAC1B,IAAO,IAAIyB,WAAWD,U,yBAhIPE,MA8IVC,cAAwB5D,GAIvCgC,IAAU6B,oBAIV7B,IAAU8B,iBCnKVC,IAASzD,OACP,kBAAC,IAAM0D,WAAP,KACE,kBAAC,EAAD,OAEFvB,SAASwB,eAAe,W","file":"static/js/main.833ba252.chunk.js","sourcesContent":["import {\n  Streamlit,\n  StreamlitComponentBase,\n  withStreamlitConnection,\n} from \"streamlit-component-lib\"\nimport React, { ReactNode } from \"react\"\n\nimport AudioReactRecorder, { RecordState } from 'audio-react-recorder'\nimport 'audio-react-recorder/dist/index.css'\n\ninterface State {\n  isFocused: boolean\n  recordState: null\n  audioDataURL: string\n  reset: boolean\n}\n\nclass StAudioRec extends StreamlitComponentBase<State> {\n  public state = { isFocused: false, recordState: null, audioDataURL: '', reset: false}\n\n  public render = (): ReactNode => {\n    // Arguments that are passed to the plugin in Python are accessible\n\n    // Streamlit sends us a theme object via props that we can use to ensure\n    // that our component has visuals that match the active theme in a\n    // streamlit app.\n    const { theme } = this.props\n    const style: React.CSSProperties = {}\n\n    const { recordState } = this.state\n\n    // compatibility with older vers of Streamlit that don't send theme object.\n    if (theme) {\n      // Use the theme object to style our button border. Alternatively, the\n      // theme style is defined in CSS vars.\n      const borderStyling = `1px solid ${\n        this.state.isFocused ? theme.primaryColor : \"gray\"}`\n      style.border = borderStyling\n      style.outline = borderStyling\n    }\n\n    return (\n      <span>\n        <div>\n          <button id='record' onClick={this.onClick_start}>\n            Start Recording\n          </button>\n          <button id='stop' onClick={this.onClick_stop}>\n            Stop\n          </button>\n          <button id='reset' onClick={this.onClick_reset}>\n            Reset\n          </button>\n\n          <button id='continue' onClick={this.onClick_continue}>\n            Download\n          </button>\n\n          <AudioReactRecorder\n            state={recordState}\n            onStop={this.onStop_audio}\n            type='audio/wav'\n            backgroundColor='rgb(255, 255, 255)'\n            foregroundColor='rgb(255,76,75)'\n            canvasWidth={450}\n            canvasHeight={100}\n          />\n\n          <audio\n            id='audio'\n            controls\n            src={this.state.audioDataURL}\n          />\n\n        </div>\n      </span>\n    )\n  }\n\n\n  private onClick_start = () => {\n    this.setState({\n      reset: false,\n      audioDataURL: '',\n      recordState: RecordState.START\n    })\n    Streamlit.setComponentValue('')\n  }\n\n  private onClick_stop = () => {\n    this.setState({\n      reset: false,\n      recordState: RecordState.STOP\n    })\n  }\n\n  private onClick_reset = () => {\n    this.setState({\n      reset: true,\n      audioDataURL: '',\n      recordState: RecordState.STOP\n    })\n    Streamlit.setComponentValue('')\n  }\n\n  private onClick_continue = () => {\n    if (this.state.audioDataURL !== '')\n    {\n      // get datetime string for filename\n      let datetime = new Date().toLocaleString();\n      datetime = datetime.replace(' ', '');\n      datetime = datetime.replace(/_/g, '');\n      datetime = datetime.replace(',', '');\n      var filename = 'streamlit_audio_' + datetime + '.wav';\n\n      // auromatically trigger download\n      const a = document.createElement('a');\n      a.style.display = 'none';\n      a.href = this.state.audioDataURL;\n      a.download = filename;\n      document.body.appendChild(a);\n      a.click();\n    }\n  }\n\n  private onStop_audio = (data) => {\n    if (this.state.reset === true)\n    {\n      this.setState({\n        audioDataURL: ''\n      })\n      Streamlit.setComponentValue('')\n    }else{\n      this.setState({\n        audioDataURL: data.url\n      })\n\n      fetch(data.url).then(function(ctx){\n        return ctx.blob()\n      }).then(function(blob){\n        // converting blob to arrayBuffer, this process step needs to be be improved\n        // this operation's time complexity scales exponentially with audio length\n        return (new Response(blob)).arrayBuffer()\n      }).then(function(buffer){\n        Streamlit.setComponentValue({\n          \"arr\": new Uint8Array(buffer)\n        })\n      })\n\n    }\n\n\n  }\n}\n\n// \"withStreamlitConnection\" is a wrapper function. It bootstraps the\n// connection between your component and the Streamlit app, and handles\n// passing arguments from Python -> Component.\n// You don't need to edit withStreamlitConnection (but you're welcome to!).\nexport default withStreamlitConnection(StAudioRec)\n\n// Tell Streamlit we're ready to start receiving data. We won't get our\n// first RENDER_EVENT until we call this function.\nStreamlit.setComponentReady()\n\n// Finally, tell Streamlit to update our initial height. We omit the\n// `height` parameter here to have it default to our scrollHeight.\nStreamlit.setFrameHeight()\n","import React from \"react\"\nimport ReactDOM from \"react-dom\"\nimport StAudioRec from \"./StreamlitAudioRecorder\"\n\nReactDOM.render(\n  <React.StrictMode>\n    <StAudioRec />\n  </React.StrictMode>,\n  document.getElementById(\"root\")\n)\n"],"sourceRoot":""}