Audio-in in DB2

Hi All,

Can I capture audio from Dashboard 2? I can see that a node was created for dashboard 1 (node-red-node-ui-microphone), and for DB2, I found @5minds/node-red-dashboard-2-processcube-audio-capture which seems to work (generates the UI), but does absolutely nothing when I click on Start.

Any pointers would be appreciated.

Regards,
Csongor

If you follow the link from the node's page on the flows site to its github repository you will see that does not exist, which suggests that the node is abandoned. I think you will have to find an alternative route. I don't know the solution myself.

[Edit] Copilot does suggest a solution using the browser MediaRecorder API in a ui-template node, but I can't vouch for whether it works.

1 Like

As colin said, this is easy to achieve in a ui-template with the MediaRecorder API

chrome_xNdG6LpFuF

NOTE: the MediaRecorder API requires a secure secure origin e.g. HTTPS or localhost

[{"id":"2a5f4c2cb6f860ad","type":"ui-template","z":"b4c00b43f02f573a","group":"7a30a31af6818ce4","page":"","ui":"","name":"","order":1,"width":0,"height":0,"head":"","format":"<template>\n  <div class=\"d-flex flex-column align-center\">\n    <v-btn color=\"red\" class=\"mb-4\" @click=\"startRecording\" :disabled=\"isRecording\">\n      <v-icon left>mdi-microphone</v-icon>\n      Start Recording\n    </v-btn>\n    <v-btn color=\"grey\" class=\"mb-4\" @click=\"stopRecording\" :disabled=\"!isRecording\">\n      <v-icon left>mdi-stop</v-icon>\n      Stop Recording\n    </v-btn>\n    <v-btn color=\"green\" class=\"mb-4\" @click=\"playback\" :disabled=\"!lastRecordingBlob\">\n      <v-icon left>mdi-play</v-icon>\n      Play Recording\n    </v-btn>\n    <v-icon :color=\"isRecording ? 'red' : 'grey'\" size=\"48\">\n      {{ isRecording ? 'mdi-record-circle' : 'mdi-record-circle-outline' }}\n    </v-icon>\n  </div>\n</template>\n\n<script>\nexport default {\n  data() {\n    return {\n      isRecording: false,\n      mediaRecorder: null,\n      audioChunks: [],\n      lastRecordingBlob: null\n    };\n  },\n  methods: {\n    startRecording() {\n      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n        alert('getUserMedia not supported in this browser.');\n        return;\n      }\n      navigator.mediaDevices.getUserMedia({ audio: true })\n        .then(stream => {\n          this.isRecording = true;\n          this.audioChunks = [];\n          this.mediaRecorder = new MediaRecorder(stream);\n          this.mediaRecorder.ondataavailable = event => {\n            if (event.data.size > 0) {\n              this.audioChunks.push(event.data);\n            }\n          };\n          this.mediaRecorder.onstop = () => {\n            const audioBlob = new Blob(this.audioChunks, { type: 'audio/webm' });\n            this.lastRecordingBlob = audioBlob;\n            // Send audio data as blob to node-red\n            this.send({ payload: audioBlob });\n            stream.getTracks().forEach(track => track.stop());\n            this.mediaRecorder = null;\n          };\n          this.mediaRecorder.start();\n        })\n        .catch(err => {\n          alert('Error accessing microphone: ' + err.message);\n        });\n    },\n    stopRecording() {\n      if (this.mediaRecorder && this.isRecording) {\n        this.isRecording = false;\n        this.mediaRecorder.stop();\n      }\n    },\n    playback() {\n      if (this.lastRecordingBlob) {\n        const audioURL = URL.createObjectURL(this.lastRecordingBlob);\n        const audio = new Audio(audioURL);\n        audio.play();\n      } else {\n        alert('No recording available to play back.');\n      }\n    }\n  }\n};\n</script>\n\n<style scoped>\n.v-btn {\n  min-width: 180px;\n}\n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":320,"y":200,"wires":[["68df473e351117a6"]]},{"id":"586f7deeb3d6102e","type":"ui-notification","z":"b4c00b43f02f573a","ui":"ba750d2403672175","position":"top right","colorDefault":true,"color":"#000000","displayTime":"3","showCountdown":true,"outputs":1,"allowDismiss":true,"dismissText":"Close","allowConfirm":false,"confirmText":"Confirm","raw":false,"className":"","name":"","x":950,"y":160,"wires":[[]]},{"id":"a74ff11982d7aa43","type":"debug","z":"b4c00b43f02f573a","name":"debug 20","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":920,"y":220,"wires":[]},{"id":"68df473e351117a6","type":"change","z":"b4c00b43f02f573a","name":"","rules":[{"t":"set","p":"recording","pt":"flow","to":"payload","tot":"msg","dc":true}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":200,"wires":[["961edd74b2774d1f"]]},{"id":"961edd74b2774d1f","type":"change","z":"b4c00b43f02f573a","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"Captured recording","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":200,"wires":[["a74ff11982d7aa43","586f7deeb3d6102e"]]},{"id":"7a30a31af6818ce4","type":"ui-group","name":"Rec","page":"6db7daf1529deea2","width":6,"height":1,"order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"ba750d2403672175","type":"ui-base","name":"My Dashboard","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"headerContent":"page","navigationStyle":"default","titleBarStyle":"default","showReconnectNotification":true,"notificationDisplayTime":1,"showDisconnectNotification":true},{"id":"6db7daf1529deea2","type":"ui-page","name":"Recorder","ui":"ba750d2403672175","path":"/page4","icon":"home","layout":"grid","theme":"645ffb825f13937f","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":1,"className":"","visible":"true","disabled":"false"},{"id":"645ffb825f13937f","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094CE","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"density":"default","pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}},{"id":"7c070d39e243656c","type":"global-config","env":[],"modules":{"@flowfuse/node-red-dashboard":"1.30.2"}}]
1 Like

Wow thanks, this works. Let me dig into the details and see how I can get the recording out and save it as a file.

Btw, I found this workaround so it works on HTTP as well:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.