Signatur
Beschreibung
Der Konstruktor MediaStreamAudioDestinationNode() erzeugt einen Ausgabeknoten der Web Audio API. Anders als AudioContext.destination (die Lautsprecher) schreibt dieser Knoten das eingehende Audiosignal in einen MediaStream. Dieser Stream steht über die Eigenschaft stream zur Verfügung und enthält genau einen MediaStreamTrack der Art "audio".
Man braucht ihn immer dann, wenn bearbeitetes oder synthetisch erzeugtes Audio den Web-Audio-Graphen verlassen und an andere Media-APIs gehen soll: zum Aufnehmen mit MediaRecorder, zum Senden über RTCPeerConnection (WebRTC), zum Mischen mit einem Video-Stream aus canvas.captureStream() oder zum Abspielen über ein <audio>-Element per srcObject.
Funktional ist der Konstruktor gleichwertig zur Fabrikmethode AudioContext.createMediaStreamDestination(). Er hat aber den Vorteil, dass sich Kanal-Optionen gleich beim Erzeugen über das options-Objekt setzen lassen. Der Knoten hat einen Eingang und keinen Ausgang. Man verbindet also andere Knoten zu ihm hin, nicht von ihm weg.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $context Pflicht | AudioContext | Der AudioContext, zu dem der Knoten gehören soll. Ein OfflineAudioContext ist nicht erlaubt. |
|
| $options | object | {} | Optionales Objekt mit Kanal-Einstellungen (siehe folgende Einträge). |
| $options.channelCount | number | 2 | Anzahl der Kanäle für das Herauf- und Heruntermischen am Eingang, z. B. 1 für Mono. |
| $options.channelCountMode | "max" | "clamped-max" | "explicit" | "explicit" | Legt fest, wie die Kanalzahl des Eingangs bestimmt wird. |
| $options.channelInterpretation | "speakers" | "discrete" | "speakers" | Legt fest, wie Kanäle beim Heraufmischen und Heruntermischen zugeordnet werden. |
Rückgabewert
stream liefert den erzeugten MediaStream mit einer Audiospur.Beispiele
Knoten erzeugen und Stream auslesen
const ctx = new AudioContext();
const dest = new MediaStreamAudioDestinationNode(ctx, { channelCount: 1 });
const osc = new OscillatorNode(ctx, { frequency: 440 });
osc.connect(dest);
osc.start();
console.log(dest.stream instanceof MediaStream);
console.log(dest.stream.getAudioTracks().length);
console.log(dest.channelCount);
Bearbeitetes Mikrofon-Audio mit MediaRecorder aufnehmen
const recordFiltered = async (durationMs = 5000) => {
const ctx = new AudioContext();
const mic = await navigator.mediaDevices.getUserMedia({ audio: true });
const source = new MediaStreamAudioSourceNode(ctx, { mediaStream: mic });
const filter = new BiquadFilterNode(ctx, { type: 'lowpass', frequency: 1200 });
const dest = new MediaStreamAudioDestinationNode(ctx);
source.connect(filter).connect(dest);
const recorder = new MediaRecorder(dest.stream);
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
const done = new Promise((resolve) => {
recorder.onstop = () => resolve(new Blob(chunks, { type: recorder.mimeType }));
});
recorder.start();
setTimeout(() => {
recorder.stop();
mic.getTracks().forEach((t) => t.stop());
}, durationMs);
const blob = await done;
console.log('Aufnahme fertig:', blob.size, 'Bytes');
return URL.createObjectURL(blob);
};
document.querySelector('#rec').addEventListener('click', async () => {
const url = await recordFiltered();
document.querySelector('audio').src = url;
});
Synthetisches Audio über WebRTC senden
const ctx = new AudioContext();
const dest = new MediaStreamAudioDestinationNode(ctx);
const osc = new OscillatorNode(ctx, { type: 'sine', frequency: 880 });
const gain = new GainNode(ctx, { gain: 0.2 });
osc.connect(gain).connect(dest);
osc.start();
const pc = new RTCPeerConnection();
const [track] = dest.stream.getAudioTracks();
pc.addTrack(track, dest.stream);
console.log(pc.getSenders()[0].track.kind);
Audio mit Canvas-Video zu einem Stream kombinieren
const canvas = document.querySelector('canvas');
const ctx = new AudioContext();
const dest = new MediaStreamAudioDestinationNode(ctx);
new OscillatorNode(ctx).connect(dest);
const combined = new MediaStream([
...canvas.captureStream(30).getVideoTracks(),
...dest.stream.getAudioTracks()
]);
console.log(combined.getTracks().map((t) => t.kind));
// Wichtig · Fallstricke
- Kein OfflineAudioContext: Der Knoten funktioniert nur mit einem echten
AudioContext. Mit einemOfflineAudioContextwird ein Fehler geworfen. Offline gerendertes Audio gibt man stattdessen über denAudioBufferausstartRendering()aus. - Autoplay-Richtlinie: Ein
AudioContext, der ohne Nutzerinteraktion erzeugt wurde, startet oft im Zustand"suspended". Dann ist der Stream still. Rufectx.resume()in einem Klick-Handler auf. - Nicht hörbar: Was mit dem Knoten verbunden ist, geht nicht automatisch an die Lautsprecher. Wenn du mithören willst, verbinde die Quelle zusätzlich mit
ctx.destination. - Nur eine Spur:
streamenthält immer genau eine Audiospur. Mehrere Knoten ergeben mehrere unabhängige Streams. - Kompatibilität: Die Fabrikmethode
createMediaStreamDestination()gibt es schon länger. Die Konstruktor-Form ist in allen aktuellen Browsern (Chrome, Edge, Firefox, Safari 14.1+) verfügbar. Für sehr alte Browser nimm die Fabrikmethode. - Das Aufnahmeformat von
MediaRecorder(z. B.audio/webmoderaudio/mp4) unterscheidet sich je nach Browser. Prüfe es mitMediaRecorder.isTypeSupported().