Viele Browser können jetzt auf Video- und Audioeingaben des Nutzers zugreifen. Je nach Browser kann es sich jedoch um eine vollständig dynamische und Inline-Erfahrung handeln oder die Aufgabe kann an eine andere App auf dem Gerät des Nutzers delegiert werden.
Einfach und schrittweise beginnen
Am einfachsten ist es, den Nutzer einfach nach einer vorab aufgezeichneten Datei zu fragen. Erstellen Sie dazu ein einfaches Dateieingabeelement und fügen Sie einen accept
-Filter hinzu, der angibt, dass nur Audiodateien akzeptiert werden, sowie ein capture
-Attribut, das angibt, dass die Datei direkt vom Mikrofon stammen soll.
<input type="file" accept="audio/*" capture />
Diese Methode funktioniert auf allen Plattformen. Auf dem Computer wird der Nutzer aufgefordert, eine Datei aus dem Dateisystem hochzuladen (das Attribut capture
wird ignoriert). In Safari unter iOS wird die Mikrofon-App geöffnet, sodass Sie Audio aufnehmen und dann an die Webseite zurücksenden können. Unter Android kann der Nutzer auswählen, mit welcher App er Audio aufnehmen möchte, bevor es an die Webseite zurückgesendet wird.
Sobald der Nutzer die Aufnahme beendet hat und wieder auf der Website ist, müssen Sie irgendwie an die Dateidaten gelangen. Sie können schnell darauf zugreifen, indem Sie dem Eingabeelement ein onchange
-Ereignis zuweisen und dann die files
-Eigenschaft des Ereignisobjekts lesen.
<input type="file" accept="audio/*" capture id="recorder" />
<audio id="player" controls></audio>
<script>
const recorder = document.getElementById('recorder');
const player = document.getElementById('player');
recorder.addEventListener('change', function (e) {
const file = e.target.files[0];
const url = URL.createObjectURL(file);
// Do something with the audio file.
player.src = url;
});
</script>
</audio>
Sobald Sie Zugriff auf die Datei haben, können Sie damit tun, was Sie möchten. Beispielsweise können Sie…
- Hängen Sie es direkt an ein
<audio>
-Element an, damit es abgespielt werden kann. - Auf das Gerät des Nutzers herunterladen
- Laden Sie sie auf einen Server hoch, indem Sie sie an ein
XMLHttpRequest
anhängen. - Übergeben Sie sie an die Web Audio API und wenden Sie Filter darauf an.
Die Methode, über das Eingabeelement auf Audiodaten zuzugreifen, ist zwar weit verbreitet, aber die am wenigsten ansprechende Option. Wir möchten wirklich auf das Mikrofon zugreifen und eine gute Nutzererfahrung direkt auf der Seite bieten.
Interaktiver Zugriff auf das Mikrofon
Moderne Browser können eine direkte Verbindung zum Mikrofon herstellen, sodass wir Funktionen entwickeln können, die vollständig in die Webseite integriert sind. Der Nutzer verlässt den Browser dabei nie.
Zugriff auf das Mikrofon erhalten
Wir können direkt auf das Mikrofon zugreifen, indem wir eine API in der WebRTC-Spezifikation namens getUserMedia()
verwenden. getUserMedia()
fordert den Nutzer auf, auf seine verbundenen Mikrofone und Kameras zuzugreifen.
Bei Erfolg gibt die API ein Stream
zurück, das die Daten von der Kamera oder dem Mikrofon enthält. Wir können es dann entweder an ein <audio>
-Element, einen WebRTC-Stream oder einen Web Audio-AudioContext
anhängen oder mit der MediaRecorder
API speichern.
Um Daten vom Mikrofon zu erhalten, legen wir einfach audio: true
im constraints-Objekt fest, das an die getUserMedia()
API übergeben wird.
<audio id="player" controls></audio>
<script>
const player = document.getElementById('player');
const handleSuccess = function (stream) {
if (window.URL) {
player.srcObject = stream;
} else {
player.src = stream;
}
};
navigator.mediaDevices
.getUserMedia({audio: true, video: false})
.then(handleSuccess);
</script>
Wenn Sie ein bestimmtes Mikrofon auswählen möchten, können Sie zuerst die verfügbaren Mikrofone auflisten.
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices = devices.filter((d) => d.kind === 'audioinput');
});
Sie können dann die deviceId
übergeben, die Sie beim Aufrufen von getUserMedia
verwenden möchten.
navigator.mediaDevices.getUserMedia({
audio: {
deviceId: devices[0].deviceId,
},
});
Allein ist das nicht so nützlich. Wir können nur die Audiodaten nehmen und wiedergeben.
Zugriff auf die Rohdaten des Mikrofons
Um auf die Rohdaten des Mikrofons zuzugreifen, müssen wir den von getUserMedia()
erstellten Stream verwenden und die Daten dann mit der Web Audio API verarbeiten. Die Web Audio API ist eine einfache API, die Eingabequellen verwendet und diese Quellen mit Knoten verbindet, die die Audiodaten verarbeiten können (z. B. die Verstärkung anpassen) und schließlich mit einem Lautsprecher, damit der Nutzer sie hören kann.
Einer der Knoten, die Sie verbinden können, ist ein AudioWorkletNode
. Mit diesem Knoten haben Sie die Möglichkeit, Audio auf niedriger Ebene benutzerdefiniert zu verarbeiten. Die eigentliche Audioverarbeitung erfolgt in der process()
-Callback-Methode in der AudioWorkletProcessor
.
Rufen Sie diese Funktion auf, um Eingaben und Parameter zu übergeben und Ausgaben abzurufen.
Weitere Informationen finden Sie unter Enter Audio Worklet.
<script>
const handleSuccess = async function(stream) {
const context = new AudioContext();
const source = context.createMediaStreamSource(stream);
await context.audioWorklet.addModule("processor.js");
const worklet = new AudioWorkletNode(context, "worklet-processor");
source.connect(worklet);
worklet.connect(context.destination);
};
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
.then(handleSuccess);
</script>
// processor.js
class WorkletProcessor extends AudioWorkletProcessor {
process(inputs, outputs, parameters) {
// Do something with the data, e.g. convert it to WAV
console.log(inputs);
return true;
}
}
registerProcessor("worklet-processor", WorkletProcessor);
Die Daten in den Puffern sind die Rohdaten des Mikrofons. Sie haben mehrere Möglichkeiten, was Sie mit diesen Daten tun können:
- Direkt auf den Server hochladen
- Lokal speichern
- Konvertieren Sie sie in ein spezielles Dateiformat wie WAV und speichern Sie sie dann auf Ihren Servern oder lokal.
Daten vom Mikrofon speichern
Die einfachste Möglichkeit, die Daten des Mikrofons zu speichern, ist die Verwendung der MediaRecorder
API.
Die MediaRecorder
API verwendet den von getUserMedia
erstellten Stream und speichert die Daten im Stream dann schrittweise am gewünschten Zielort.
<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
const downloadLink = document.getElementById('download');
const stopButton = document.getElementById('stop');
const handleSuccess = function(stream) {
const options = {mimeType: 'audio/webm'};
const recordedChunks = [];
const mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.addEventListener('dataavailable', function(e) {
if (e.data.size > 0) recordedChunks.push(e.data);
});
mediaRecorder.addEventListener('stop', function() {
downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
downloadLink.download = 'acetest.wav';
});
stopButton.addEventListener('click', function() {
mediaRecorder.stop();
});
mediaRecorder.start();
};
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
.then(handleSuccess);
</script>
In unserem Fall speichern wir die Daten direkt in einem Array, das wir später in ein Blob
umwandeln können. Dieses kann dann verwendet werden, um die Daten auf unserem Webserver oder direkt auf dem Speicher des Geräts des Nutzers zu speichern.
Verantwortungsvoll um Erlaubnis zur Verwendung des Mikrofons bitten
Wenn der Nutzer Ihrer Website noch keinen Zugriff auf das Mikrofon gewährt hat, wird er vom Browser aufgefordert, Ihrer Website die Berechtigung für das Mikrofon zu erteilen, sobald Sie getUserMedia
aufrufen.
Nutzer sind genervt, wenn sie auf ihrem Gerät aufgefordert werden, den Zugriff auf leistungsstarke Geräte zu gewähren. Sie blockieren die Anfrage häufig oder ignorieren sie, wenn sie den Kontext, in dem die Aufforderung erstellt wurde, nicht verstehen. Als Best Practice wird empfohlen, den Zugriff auf das Mikrofon erst dann anzufordern, wenn er zum ersten Mal benötigt wird. Sobald der Nutzer den Zugriff gewährt hat, wird er nicht noch einmal gefragt. Wenn er den Zugriff jedoch ablehnt, können Sie ihn nicht noch einmal um die Berechtigung bitten.
Mit der Permissions API prüfen, ob Sie bereits Zugriff haben
Die getUserMedia
-API gibt Ihnen keine Informationen darüber, ob Sie bereits Zugriff auf das Mikrofon haben. Das ist ein Problem, denn um eine ansprechende Benutzeroberfläche zu bieten, über die der Nutzer Ihnen Zugriff auf das Mikrofon gewähren kann, müssen Sie Zugriff auf das Mikrofon anfordern.
In einigen Browsern lässt sich das Problem mit der Permission API beheben. Mit der navigator.permission
API können Sie den Status des Zugriffs auf bestimmte APIs abfragen, ohne noch einmal eine Aufforderung zu senden.
Wenn Sie abfragen möchten, ob Sie Zugriff auf das Mikrofon des Nutzers haben, können Sie {name: 'microphone'}
an die Abfragemethode übergeben. Diese gibt dann Folgendes zurück:
granted
: Der Nutzer hat Ihnen zuvor Zugriff auf das Mikrofon gewährt.prompt
: Der Nutzer hat Ihnen keinen Zugriff gewährt und wird dazu aufgefordert, wenn SiegetUserMedia
aufrufen.denied
: Das System oder der Nutzer hat den Zugriff auf das Mikrofon explizit blockiert. Sie können nicht darauf zugreifen.
Sie können jetzt schnell prüfen, ob Sie die Benutzeroberfläche anpassen müssen, um den Aktionen Rechnung zu tragen, die der Nutzer ausführen muss.
navigator.permissions.query({name: 'microphone'}).then(function (result) {
if (result.state == 'granted') {
} else if (result.state == 'prompt') {
} else if (result.state == 'denied') {
}
result.onchange = function () {};
});