Signatur
Beschreibung
Die Eigenschaft stream des Interfaces MediaStreamAudioDestinationNode (nicht AudioContext, wie es manchmal falsch heißt) gibt einen MediaStream zurück. Dieser enthält genau einen MediaStreamTrack vom Typ "audio". Die Spur hat so viele Kanäle wie der Knoten (channelCount, standardmäßig 2).
Über diese Eigenschaft verlässt ein bearbeitetes Audiosignal den Web-Audio-Graphen und geht an andere Medien-APIs weiter. Typische Einsatzfälle:
- Aufnahme mit
MediaRecorder, z. B. eines Synthesizers oder einer abgemischten Tonspur. - Versand über WebRTC mit
RTCPeerConnection.addTrack(), z. B. ein Mikrofon mit Effekten oder Rauschunterdrückung. - Kombination mit einer Videospur aus
canvas.captureStream()zu einem gemeinsamen Audio-Video-Stream.
Die Eigenschaft ist schreibgeschützt. Sie liefert bei jedem Zugriff dasselbe MediaStream-Objekt. Das Signal fließt nur, solange der zugehörige AudioContext läuft (state === "running").
Rückgabewert
MediaStream mit genau einem Audio-MediaStreamTrack. Er gibt in Echtzeit wieder, was an den Knoten geleitet wird.Beispiele
Oszillator-Ton mit MediaRecorder aufnehmen
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const dest = ctx.createMediaStreamDestination();
osc.frequency.value = 440;
osc.connect(dest);
osc.start();
const recorder = new MediaRecorder(dest.stream);
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = () => {
const blob = new Blob(chunks, { type: recorder.mimeType });
const audio = new Audio(URL.createObjectURL(blob));
audio.controls = true;
document.body.append(audio);
console.log('Aufnahme fertig:', blob.size, 'Bytes');
};
recorder.start();
setTimeout(() => {
recorder.stop();
osc.stop();
}, 2000);
Aufbau des Streams prüfen
const ctx = new AudioContext();
const dest = ctx.createMediaStreamDestination();
const tracks = dest.stream.getAudioTracks();
console.log(tracks.length); // Anzahl der Audiospuren
console.log(tracks[0].kind); // Art der Spur
console.log(dest.channelCount); // Kanäle des Knotens
console.log(dest.stream === dest.stream); // immer dasselbe Objekt
Mikrofon mit Effekt über WebRTC senden
const sendProcessedMic = async (peerConnection) => {
const ctx = new AudioContext();
const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });
const source = ctx.createMediaStreamSource(micStream);
const filter = ctx.createBiquadFilter();
filter.type = 'highpass';
filter.frequency.value = 120; // Brummen unterdrücken
const dest = ctx.createMediaStreamDestination();
source.connect(filter).connect(dest);
const [track] = dest.stream.getAudioTracks();
peerConnection.addTrack(track, dest.stream);
return track;
};
const pc = new RTCPeerConnection();
sendProcessedMic(pc).then((track) => console.log('Gesendet:', track.label));
Canvas-Video und Web-Audio zusammenführen
const canvas = document.querySelector('canvas');
const ctx = new AudioContext();
const dest = ctx.createMediaStreamDestination();
const osc = ctx.createOscillator();
osc.connect(dest);
osc.start();
const combined = new MediaStream([
...canvas.captureStream(30).getVideoTracks(),
...dest.stream.getAudioTracks(),
]);
const recorder = new MediaRecorder(combined, { mimeType: 'video/webm' });
recorder.start();
console.log(combined.getTracks().map((t) => t.kind));
// Wichtig · Fallstricke
- Autoplay-Richtlinie: Ein
AudioContextstartet oft im Zustand"suspended". Solange er angehalten ist, enthält der Stream nur Stille. Rufectx.resume()deshalb nach einer Nutzeraktion auf, z. B. nach einem Klick. - Kein Lautsprecher-Ausgang: Was an diesen Knoten geleitet wird, ist nicht zu hören. Wer das Signal gleichzeitig abhören will, verbindet die Quelle zusätzlich mit
ctx.destination. - Kanalanzahl: Die Spur übernimmt die Kanalanzahl des Knotens (
channelCount, Standard 2). Um sie zu ändern, übergibst du die gewünschte Anzahl beim Erzeugen, z. B.new MediaStreamAudioDestinationNode(ctx, { channelCount: 1 }). - Kein
OfflineAudioContext: Der Knoten funktioniert nur in einem Echtzeit-AudioContext. Beim Erzeugen in einemOfflineAudioContextwird ein Fehler ausgelöst. - Ressourcen freigeben: Beende nicht mehr benötigte Spuren mit
track.stop()und schließe den Kontext mitctx.close(). Sonst laufen Audioverarbeitung und gegebenenfalls das Mikrofon weiter. - Kompatibilität: Wird von Chrome, Edge, Firefox und Safari (ab 14.1) unterstützt. Das Aufnahmeformat von
MediaRecorderunterscheidet sich je nach Browser:audio/webmoderaudio/mp4. Prüfe es mitMediaRecorder.isTypeSupported().