Skip to content

Commit d7f6433

Browse files
authored
add push to talk option to ui microphone (#46)
* add push to talk option to ui microphone * remove superfluous config.log * Update ui_microphone.js
1 parent 8bbe241 commit d7f6433

File tree

4 files changed

+56
-42
lines changed

4 files changed

+56
-42
lines changed

node-red-node-ui-microphone/README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@ Either use the Editor - Menu - Manage Palette - Install option, or run the follo
1414
The node provides a single button that, when clicked, will begin to capture audio.
1515

1616
This node provides a single button widget in the dashboard that, when pressed,
17-
will begin to capture audio. It will continue to capture audio until the button
18-
is pressed again, or it reaches its configured maximum duration.
17+
will begin to capture audio.
18+
The button can be configured in two modes.
19+
20+
- Click begins to capture audio, and then continues to capture audio until the button is pressed again, or it reaches its configured maximum duration.
21+
- Or the button can be configured to record only while the button is pressed.
1922

2023
The audio is captured in WAV format and published by the node as a Buffer object.
2124
This can be written straight to a file or passed to any other node that expects

node-red-node-ui-microphone/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "node-red-node-ui-microphone",
3-
"version": "0.1.4",
3+
"version": "0.2.0",
44
"description": "A Node-RED ui node to record audio on a dashboard.",
55
"author": "Nick O'Leary",
66
"license": "Apache-2.0",

node-red-node-ui-microphone/ui_microphone.html

+32-23
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
category: 'dashboard',
1717
color: 'rgb( 63, 173, 181)',
1818
defaults: {
19+
name: {value: ''},
1920
group: {type: 'ui_group', required:true},
2021
order: {value: 0},
2122
width: {
@@ -30,9 +31,9 @@
3031
return valid;
3132
}},
3233
height: {value: 0},
33-
name: {value: ''},
3434
maxLength: { value: 5 },
35-
timeslice: { value: 0 }
35+
timeslice: { value: 0 },
36+
press : { value: "click" }
3637
},
3738
inputs:0,
3839
outputs:1,
@@ -45,6 +46,17 @@
4546
return this.name?"node_label_italic":"";
4647
},
4748
oneditprepare: function() {
49+
if (this.press === undefined) {
50+
$("#node-input-press").val("click");
51+
}
52+
$("#node-input-press").change( function() {
53+
if ($("#node-input-press").val() === "press") {
54+
$("#node-rec-max-length").hide();
55+
}
56+
else {
57+
$("#node-rec-max-length").show();
58+
}
59+
});
4860
$("#node-input-size").elementSizer({
4961
width: "#node-input-width",
5062
height: "#node-input-height",
@@ -78,7 +90,7 @@
7890
});
7991
</script>
8092

81-
<script type="text/x-red" data-template-name="ui_microphone">
93+
<script type="text/html" data-template-name="ui_microphone">
8294
<div class="form-row" id="template-row-group">
8395
<label for="node-input-group"><i class="fa fa-table"></i> Group</span></label>
8496
<input type="text" id="node-input-group">
@@ -89,39 +101,36 @@
89101
<input type="hidden" id="node-input-height">
90102
<button class="editor-button" id="node-input-size"></button>
91103
</div>
92-
<br />
93-
<div class="form-row" style="min-width: 470px">
94-
<label style="vertical-align: top"><i class="fa fa-cog"></i> Options</label>
95-
<div style="display: inline-block; min-width: 350px; width: calc(100% - 120px);">
96-
<ul>
97-
<li style="margin: 0 0 8px">Click button to start recording</li>
98-
<li style="margin: 8px 0 4px">Click again to stop recording</li>
99-
<li style="margin: 4px 0 4px">Maximum length of recording: <input style="width: 50px" type="text" id="node-input-maxLength"> seconds
100-
<!-- <li style="margin: 4px 0 4px">Send message <select style="width: auto" id="node-input-select-timeslice"><option value="once">once recording stops</option><option value="interval">at regular interval of</option></select>
101-
<div id="node-input-row-timeslice"><input style="margin-left: 20px; width: 50px" type="text" id="node-input-timeslice"> seconds</div>
102-
</li> -->
103-
</ul>
104-
</div>
105-
104+
<div class="form-row" style="min-width:470px">
105+
<label><i class="fa fa-cog"></i> Record</label>
106+
<select type="text" id="node-input-press" style="width:70%;">
107+
<option value="click">Click to start, click to stop</option>
108+
<option value="press">Press to start, release to stop</option>
109+
</select>
110+
</div>
111+
<div class="form-row" id="node-rec-max-length">
112+
<label></labeL>
113+
Maximum length of recording: <input style="width:50px" type="text" id="node-input-maxLength"> seconds
106114
</div>
107115
<div class="form-row">
108116
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
109117
<input type="text" id="node-input-name" placeholder="Name">
110118
</div>
111119
</script>
112120

113-
<script type="text/x-red" data-help-name="ui_microphone">
121+
<script type="text/html" data-help-name="ui_microphone">
114122
<p>A Node Red dashboard ui node to capture audio from the brower's microphone.</p>
115123
<h3>Outputs</h3>
116124
<dl class="message-properties">
117125
<dt>payload<span class="property-type">Buffer</span></dt>
118126
<dd>The captured audio in the required format.</dd>
119127
</dl>
120128
<h3>Details</h3>
121-
<p>This node provides a single button widget in the dashboard that, when pressed,
122-
will begin to capture audio. It will continue to capture audio until the button
123-
is pressed again , or it reaches its configured maximum duration.</p>
124-
<p>The audio is captured in WAV format and published by the node as a Buffer
125-
object.</p>
129+
<p>This node provides a single button widget in the dashboard.
130+
The audio is captured in WAV format and published by the node as a Buffer object.</p>
131+
<p>The button can be configured in two modes. Either click begin to capture audio, and then
132+
continue to capture audio until the button is pressed again, or it reaches its configured
133+
maximum duration. Or the button can be configured to record only while the button is pressed.</p>
134+
<p></p>
126135
<p></p>
127136
</script>

node-red-node-ui-microphone/ui_microphone.js

+18-16
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
const path = require('path');
1919

2020
module.exports = function(RED) {
21-
2221
function HTML(config) {
2322
var configAsJson = JSON.stringify(config);
24-
var html = String.raw`
25-
<input type='hidden' ng-init='init(` + configAsJson + `)'>
26-
<md-button aria-label="capture audio" id="microphone_control_{{$id}}" class="nr-ui-microphone-button" ng-disabled="!enabled" ng-click="toggleMicrophone()"><i class="fa fa-2x fa-microphone"></i></md-button>
27-
`;
23+
var html = String.raw`<input type='hidden' ng-init='init(` + configAsJson + `)'>`;
24+
if (config.press && config.press === "press") {
25+
html += String.raw`<md-button aria-label="capture audio" id="microphone_control_{{$id}}" class="nr-ui-microphone-button" ng-disabled="!enabled" ng-mousedown="toggleMicrophone()" ng-mouseup="toggleMicrophone()"><i class="fa fa-2x fa-microphone"></i></md-button>`;
26+
}
27+
else {
28+
html += String.raw`<md-button aria-label="capture audio" id="microphone_control_{{$id}}" class="nr-ui-microphone-button" ng-disabled="!enabled" ng-click="toggleMicrophone()"><i class="fa fa-2x fa-microphone"></i></md-button>`;
29+
}
2830
return html;
2931
}
3032

@@ -82,7 +84,7 @@ module.exports = function(RED) {
8284
initController: function($scope) {
8385

8486
$scope.init = function (config) {
85-
console.log("ui_microphone: initialised config:",config);
87+
//console.log("ui_microphone: initialised config:",config);
8688
$scope.config = config;
8789
}
8890

@@ -105,7 +107,7 @@ module.exports = function(RED) {
105107
if (!$scope.enabled) return;
106108
if (!active) {
107109
active = true;
108-
$("#microphone_control_"+$scope.$id+" i").removeClass("fa-microphone fa-2x").addClass("fa-circle-o-notch fa-spin");
110+
$("#microphone_control_"+$scope.$id+" i").removeClass("fa-microphone fa-2x").addClass("fa-rotate-right fa-2x fa-spin");
109111
navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(handleSuccess).catch(handleError);
110112
} else {
111113
if (mediaRecorder) {
@@ -121,7 +123,7 @@ module.exports = function(RED) {
121123
var handleError = function(err) {
122124
console.warn("Failed to access microphone:",err);
123125
active = false;
124-
$("#microphone_control_"+$scope.$id+" i").addClass("fa-microphone fa-2x").removeClass("fa-circle-o-notch fa-spin");
126+
$("#microphone_control_"+$scope.$id+" i").addClass("fa-microphone fa-2x").removeClass("fa-rotate-right fa-2x fa-spin");
125127
}
126128
var handleSuccess = function(stream) {
127129
mediaRecorder = new MediaRecorder(stream, {mimeType: 'audio/webm'});
@@ -134,7 +136,7 @@ module.exports = function(RED) {
134136
mediaRecorder.onstop = function() {
135137
if (active) {
136138
active = false;
137-
$("#microphone_control_"+$scope.$id+" i").addClass("fa-microphone fa-2x").removeClass("fa-circle-o-notch fa-spin");
139+
$("#microphone_control_"+$scope.$id+" i").addClass("fa-microphone fa-2x").removeClass("fa-rotate-right fa-spin");
138140
if (stopTimeout) {
139141
clearTimeout(stopTimeout);
140142
stopTimeout = null;
@@ -151,10 +153,10 @@ module.exports = function(RED) {
151153
// if (timeslice) {
152154
// mediaRecorder.start(timeslice);
153155
// } else {
154-
mediaRecorder.start();
156+
mediaRecorder.start();
155157
// }
156158

157-
if ($scope.config && $scope.config.maxLength) {
159+
if ($scope.config && $scope.config.maxLength && ($scope.config.press !== "press")) {
158160
stopTimeout = setTimeout(function() {
159161
if (active) {
160162
mediaRecorder.stop();
@@ -189,11 +191,11 @@ module.exports = function(RED) {
189191
worker.postMessage({ command: 'clear' });
190192
};
191193
worker.postMessage({
192-
command: 'record',
193-
buffer: [
194-
buffer.getChannelData(0),
195-
buffer.getChannelData(0)
196-
]
194+
command: 'record',
195+
buffer: [
196+
buffer.getChannelData(0),
197+
buffer.getChannelData(0)
198+
]
197199
});
198200
worker.postMessage({ command: 'exportMonoWAV', type: 'audio/wav' });
199201
}

0 commit comments

Comments
 (0)