More work on audio recording

Issue #95. Use a post processing step to fix chromium bug of not having a valid cues section in the metadata (=browser did not know length of audio!). Also, set more constraints in the call to getUserMedia to fix Android problem of really sh*tty audio in the default mode (More info on github.com slash processing/p5.js-sound/issues/346
This commit is contained in:
N-Pex 2021-03-24 10:45:35 +01:00
parent b6ac6ec881
commit b8aeb02b50
3 changed files with 833 additions and 140 deletions

884
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -24,6 +24,7 @@
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"recordrtc": "^5.6.2", "recordrtc": "^5.6.2",
"roboto-fontface": "*", "roboto-fontface": "*",
"ts-ebml": "^2.0.2",
"v-emoji-picker": "^2.3.1", "v-emoji-picker": "^2.3.1",
"vue": "^2.6.11", "vue": "^2.6.11",
"vue-clipboard2": "^0.3.1", "vue-clipboard2": "^0.3.1",

View file

@ -147,6 +147,7 @@ import util from "../plugins/utils";
import VoiceRecorderLock from "./VoiceRecorderLock"; import VoiceRecorderLock from "./VoiceRecorderLock";
require("md-gum-polyfill"); require("md-gum-polyfill");
import RecordRTC from "recordrtc"; import RecordRTC from "recordrtc";
import {Decoder, tools, Reader} from 'ts-ebml';
export default { export default {
name: "VoiceRecorder", name: "VoiceRecorder",
@ -321,15 +322,23 @@ export default {
}, },
startRecording() { startRecording() {
var constraints = {
audio: {
channelCount: 1,
sampleRate: 16000,
echoCancellation: false,
autoGainControl: true,
noiseSuppression: true,
volume: 1.0,
},
video: false,
};
navigator.mediaDevices navigator.mediaDevices
.getUserMedia({ .getUserMedia(constraints)
video: false,
audio: true,
})
.then((stream) => { .then((stream) => {
this.recorder = RecordRTC(stream, { this.recorder = RecordRTC(stream, {
type: "audio", type: "audio",
mimeType: "audio/webm" mimeType: "audio/webm",
}); });
this.recorder.startRecording(); this.recorder.startRecording();
this.state = State.RECORDING; this.state = State.RECORDING;
@ -373,27 +382,29 @@ export default {
this.recordingTime = String.fromCharCode(160); // nbsp; this.recordingTime = String.fromCharCode(160); // nbsp;
}, },
send() { send() {
//console.log("Send:", this.recordedFile);
this.$emit("file", { file: this.recordedFile }); this.$emit("file", { file: this.recordedFile });
// const player = new Audio(URL.createObjectURL(file));
// player.play();
}, },
getFile(send) { getFile(send) {
this.recorder.stopRecording(function () this.recorder.stopRecording(
{ function () {
const blob = this.recorder.getBlob(); this.correctMetadata(this.recorder.getBlob()).then((blob) => {
this.recordedFile = new File( this.recordedFile = new File(
[blob], [blob],
util.formatRecordStartTime(this.recordStartedAt) + ".webm", util.formatRecordStartTime(this.recordStartedAt) + ".webm",
{ {
type: blob.type, type: blob.type,
lastModified: Date.now() lastModified: Date.now(),
} }
); );
if (send) { //const player = new Audio(URL.createObjectURL(this.recordedFile));
this.send(); //player.play();
} if (send) {
}.bind(this)); //console.log("send");
this.send();
}
});
}.bind(this)
);
}, },
startRecordTimer() { startRecordTimer() {
this.stopRecordTimer(); this.stopRecordTimer();
@ -411,6 +422,37 @@ export default {
this.recordTimer = null; this.recordTimer = null;
} }
}, },
/*
* There is an issue with browsers not setting correct metadata in the generated webm file.
* See here: https://bugs.chromium.org/p/chromium/issues/detail?id=642012
* Use es-embl to try to update the cues section.
*/
async correctMetadata(blob) {
try {
const decoder = new Decoder();
const reader = new Reader();
reader.logging = true;
reader.logGroup = "Raw WebM file";
reader.drop_default_duration = false;
const webMBuf = await blob.arrayBuffer();
const elms = decoder.decode(webMBuf);
elms.forEach((elm) => {
reader.read(elm);
});
reader.stop();
const refinedMetadataBuf = tools.makeMetadataSeekable(
reader.metadatas,
reader.duration,
reader.cues
);
const body = webMBuf.slice(reader.metadataSize);
return new Blob([refinedMetadataBuf, body], { type: blob.type });
} catch (err) {
console.err(err);
return blob;
}
},
}, },
}; };
</script> </script>