File: /var/www/html/voice/index.php
<?php
session_start();
$_SESSION['nonce'] = substr(str_shuffle(MD5(microtime())), 0, 10);
?>
<!DOCYTPE html>
<html>
<head>
<title>Simple audio recording demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<input type="button" class="btn" value="click and hold to record" />
<script type="text/javascript">
window.nonce = "<?php echo $_SESSION['nonce']; ?>"
// courtesy https://medium.com/@bryanjenningz/how-to-record-and-play-audio-in-javascript-faa1b2b3e49b
var constraints = {
video: false,
audio: false
}
navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
/* do stuff */
}).catch(function(err) {
//log to console first
console.log(err); /* handle the error */
if (err.name == "NotFoundError" || err.name == "DevicesNotFoundError") {
//required track is missing
} else if (err.name == "NotReadableError" || err.name == "TrackStartError") {
//webcam or mic are already in use
} else if (err.name == "OverconstrainedError" || err.name == "ConstraintNotSatisfiedError") {
//constraints can not be satisfied by avb. devices
} else if (err.name == "NotAllowedError" || err.name == "PermissionDeniedError") {
//permission denied in browser
} else if (err.name == "TypeError" || err.name == "TypeError") {
//empty constraints object
} else {
//other errors
}
});
const recordAudio = () => {
return new Promise(async resolve => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
const audioChunks = [];
mediaRecorder.addEventListener("dataavailable", event => {
audioChunks.push(event.data);
});
const start = () => mediaRecorder.start();
const stop = () =>
new Promise(resolve => {
mediaRecorder.addEventListener("stop", () => {
const audioBlob = new Blob(audioChunks);
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
const play = () => audio.play();
resolve({ audioBlob, audioUrl, play });
});
mediaRecorder.stop();
});
resolve({ start, stop });
});
}
/* simple timeout */
const sleep = time => new Promise(resolve => setTimeout(resolve, time));
/* init */
(async () => {
const btn = document.querySelector("input");
const recorder = await recordAudio();
let audio; // filled in end cb
const recStart = e => {
recorder.start();
btn.initialValue = btn.value;
btn.value = "recording...";
}
const recEnd = async e => {
btn.value = btn.initialValue;
audio = await recorder.stop();
audio.play();
uploadAudio(audio.audioBlob);
}
const uploadAudio = a => {
if (a.size > (10 * Math.pow(1024, 2))) {
document.body.innerHTML += "Too big; could not upload";
return;
}
const f = new FormData();
f.append("nonce", window.nonce);
f.append("payload", a);
fetch("save_audio.php", {
method: "POST",
body: f
})
.then(_ => {
document.body.innerHTML += `
<br/> <a href="audio.wav">saved; click here</a>
`
});
}
btn.addEventListener("mousedown", recStart);
btn.addEventListener("touchstart", recStart);
window.addEventListener("mouseup", recEnd);
window.addEventListener("touchend", recEnd);
})();
</script>
</body>
</html>