Audio- und Videomanipulation
Die Schönheit des Webs liegt darin, dass Sie Technologien kombinieren können, um neue Formen zu schaffen. Da Audio und Video nativ im Browser verfügbar sind, können wir diese Datenströme mit Technologien wie <canvas>
, WebGL oder der Web Audio API verwenden, um Audio und Video direkt zu modifizieren, zum Beispiel um Hall-/Kompressionseffekte zu Audio oder Graustufen-/Sepiatöne zu Video hinzuzufügen. Dieser Artikel bietet eine Referenz, um zu erklären, was dafür notwendig ist.
Videomanipulation
Die Fähigkeit, die Pixelwerte jedes Videoframes zu lesen, kann sehr nützlich sein.
Video und Canvas
Das <canvas>
-Element bietet eine Fläche, um Grafiken auf Webseiten zu zeichnen; es ist sehr leistungsfähig und kann eng mit Video gekoppelt werden.
Die allgemeine Technik besteht darin:
- Ein Frame vom
<video>
-Element zum<canvas>
-Element zu schreiben. - Die Daten aus dem
<canvas>
-Element zu lesen und zu manipulieren. - Die manipulierten Daten zu Ihrem "Display"-
<canvas>
zu schreiben (was effektiv dasselbe Element sein kann). - Anhalten und Wiederholen.
Zum Beispiel, lassen Sie uns ein Video verarbeiten, um es in Graustufen anzuzeigen. In diesem Fall zeigen wir sowohl das Quellvideo als auch die ausgegebenen Graustufenframes. Normalerweise würden Sie bei einer Implementierung einer "Video in Graustufen abspielen"-Funktion wahrscheinlich display: none
zum Stil des <video>
-Elements hinzufügen, um das Quellvideo daran zu hindern, auf dem Bildschirm angezeigt zu werden, während nur das Canvas mit den veränderten Frames angezeigt wird.
HTML
Wir können unseren Videoplayer und das <canvas>
-Element folgendermaßen einrichten:
<video id="my-video" controls width="480" height="270" crossorigin="anonymous">
<source
src="https://jplayer.org/video/webm/Big_Buck_Bunny_Trailer.webm"
type="video/webm" />
<source
src="https://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"
type="video/mp4" />
</video>
<canvas id="my-canvas" width="480" height="270"></canvas>
JavaScript
Dieser Code kümmert sich um die Änderung der Frames.
const processor = {
timerCallback() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
setTimeout(() => {
this.timerCallback();
}, 16); // roughly 60 frames per second
},
doLoad() {
this.video = document.getElementById("my-video");
this.c1 = document.getElementById("my-canvas");
this.ctx1 = this.c1.getContext("2d");
this.video.addEventListener(
"play",
() => {
this.width = this.video.width;
this.height = this.video.height;
this.timerCallback();
},
false,
);
},
computeFrame() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
const frame = this.ctx1.getImageData(0, 0, this.width, this.height);
const l = frame.data.length / 4;
for (let i = 0; i < l; i++) {
const grey =
(frame.data[i * 4 + 0] +
frame.data[i * 4 + 1] +
frame.data[i * 4 + 2]) /
3;
frame.data[i * 4 + 0] = grey;
frame.data[i * 4 + 1] = grey;
frame.data[i * 4 + 2] = grey;
}
this.ctx1.putImageData(frame, 0, 0);
return;
},
};
Sobald die Seite geladen ist, können Sie aufrufen
processor.doLoad();
Ergebnis
Dies ist ein Beispiel, wie man Videoframes mit einem Canvas manipuliert. Für bessere Effizienz sollten Sie in Erwägung ziehen, requestAnimationFrame()
anstelle von setTimeout()
zu verwenden, wenn es von den Browsern unterstützt wird.
Das gleiche Ergebnis erzielen Sie, indem Sie die grayscale()
CSS-Funktion auf das Quell-<video>
-Element anwenden.
Hinweis: Aufgrund potenzieller Sicherheitsprobleme, falls sich Ihr Video auf einer anderen Domain als Ihr Code befindet, müssen Sie CORS (Cross Origin Resource Sharing) auf Ihrem Videoserver aktivieren.
Video und WebGL
WebGL ist eine leistungsstarke API, die Canvas verwendet, um hardwarebeschleunigte 3D- oder 2D-Szenen zu zeichnen. Sie können WebGL und das <video>
-Element kombinieren, um Videotexturen zu erzeugen, was bedeutet, dass Sie Video in 3D-Szenen integrieren können.
Hinweis: Den Quellcode dieses Demos auf GitHub finden Sie (live ansehen).
Wiedergabegeschwindigkeit
Wir können auch die Geschwindigkeit, mit der Audio und Video abgespielt werden, anpassen, indem wir ein Attribut des <audio>
- und <video>
-Elements namens playbackRate
verwenden. playbackRate
ist eine Zahl, die ein Vielfaches der Wiedergabegeschwindigkeit repräsentiert. Zum Beispiel steht 0,5 für halbe Geschwindigkeit, während 2 für doppelte Geschwindigkeit steht.
Beachten Sie, dass die playbackRate
-Eigenschaft sowohl mit <audio>
als auch <video>
funktioniert, aber in beiden Fällen die Wiedergabegeschwindigkeit, jedoch nicht die Tonhöhe, ändert. Um die Tonhöhe zu manipulieren, müssen Sie die Web Audio API verwenden. Siehe die AudioBufferSourceNode.playbackRate
-Eigenschaft.
HTML
<video
id="my-video"
controls
src="https://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"></video>
JavaScript
const myVideo = document.getElementById("my-video");
myVideo.playbackRate = 2;
Bearbeitbares Beispiel
Hinweis: Versuchen Sie das playbackRate-Beispiel live.
Audiomanipulation
Abgesehen von playbackRate
, zur Manipulation von Audio werden Sie typischerweise die Web Audio API verwenden.
Eine Audioquelle auswählen
Die Web Audio API kann Audio aus verschiedenen Quellen empfangen, es verarbeiten und dann an einen AudioDestinationNode
senden, der das Ausgabegerät repräsentiert, an das der verarbeitete Ton gesendet wird.
Wenn die Audioquelle ist… | Verwenden Sie diesen Web Audio Knotentyp |
---|---|
Eine Audiospur eines HTML-<audio> - oder <video> -Elements |
MediaElementAudioSourceNode |
Ein einfacher roher Audiodatenpuffer im Speicher | AudioBufferSourceNode |
Ein Oszillator, der eine Sinuswelle oder eine andere berechnete Wellenform erzeugt | OscillatorNode |
Eine Audiospur von WebRTC (z. B. das Mikrofoneingangssignal, das Sie mit getUserMedia() erhalten können) |
MediaStreamAudioSourceNode |
Audiofilter
Die Web Audio API bietet eine Vielzahl von Filtern/Effekten, die auf Audio angewendet werden können, zum Beispiel mit dem BiquadFilterNode
.
HTML
<video id="my-video" controls src="my-video.mp4" type="video/mp4"></video>
JavaScript
const context = new AudioContext();
const audioSource = context.createMediaElementSource(
document.getElementById("my-video"),
);
const filter = context.createBiquadFilter();
audioSource.connect(filter);
filter.connect(context.destination);
// Configure filter
filter.type = "lowshelf";
filter.frequency.value = 1000;
filter.gain.value = 25;
Bearbeitbares Beispiel
Hinweis: Wenn Sie CORS nicht aktiviert haben, sollte sich Ihr Video aus Sicherheitsgründen auf derselben Domain wie Ihr Code befinden.
Häufige Audiofilter
Dies sind einige gängige Arten von Audiofiltern, die Sie anwenden können:
- Tiefpass: Lässt Frequenzen unterhalb der Grenzfrequenz durch und dämpft Frequenzen oberhalb der Grenzfrequenz.
- Hochpass: Lässt Frequenzen oberhalb der Grenzfrequenz durch und dämpft Frequenzen unterhalb der Grenzfrequenz.
- Bandpass: Lässt einen Frequenzbereich durch und dämpft die Frequenzen unterhalb und oberhalb dieses Frequenzbereichs.
- Tiefenregal: Lässt alle Frequenzen durch, fügt jedoch eine Verstärkung (oder Dämpfung) der niedrigeren Frequenzen hinzu.
- Höhenregal: Lässt alle Frequenzen durch, fügt jedoch eine Verstärkung (oder Dämpfung) der höheren Frequenzen hinzu.
- Peaking: Lässt alle Frequenzen durch, fügt jedoch eine Verstärkung (oder Dämpfung) eines Frequenzbereichs hinzu.
- Notch: Lässt alle Frequenzen durch, außer für einen Satz von Frequenzen.
- All Pass: Lässt alle Frequenzen durch, ändert jedoch die Phasenbeziehung zwischen den verschiedenen Frequenzen.
Hinweis:
Weitere Informationen finden Sie im BiquadFilterNode
.
Faltung und Impulse
Es ist auch möglich, Impulsantworten auf Audio anzuwenden, indem man den ConvolverNode
verwendet. Eine Impulsantwort ist der Klang, der nach einem kurzen Klangimpuls (wie einem Händeklatschen) entsteht. Eine Impulsantwort wird die Umgebung kennzeichnen, in der der Impuls erzeugt wurde (zum Beispiel ein Echo, das durch das Klatschen der Hände in einem Tunnel entsteht).
Beispiel
const convolver = context.createConvolver();
convolver.buffer = this.impulseResponseBuffer;
// Connect the graph.
source.connect(convolver);
convolver.connect(context.destination);
Sehen Sie sich dieses CodePen für ein angewandtes (aber sehr, sehr albernes) Beispiel an; wie etwa ein Beispiel, bei dem kleine Kinder lachen.
Räumliches Audio
Wir können auch Audio mit einem Panner-Knoten positionieren. Ein Panner-Knoten—PannerNode
—ermöglicht es uns, einen Quellkegel sowie Positions- und Richtungselemente zu definieren, alles im 3D-Raum, der mithilfe von 3D-Koordinaten im kartesischen System definiert wird.
Beispiel
const panner = context.createPanner();
panner.coneOuterGain = 0.2;
panner.coneOuterAngle = 120;
panner.coneInnerAngle = 0;
panner.connect(context.destination);
source.connect(panner);
source.start(0);
// Position the listener at the origin.
context.listener.setPosition(0, 0, 0);
Hinweis: Ein Beispiel befindet sich in unserem GitHub-Repository (live ansehen).
JavaScript-Codecs
Es ist auch möglich, Audio auf niedrigem Niveau mit JavaScript zu manipulieren. Dies kann nützlich sein, wenn Sie Audio-Codecs erstellen möchten.
Bibliotheken existieren derzeit für die folgenden Formate:
Hinweis: Bei Audiocogs können Sie einige Demos ausprobieren; Audiocogs bietet auch ein Framework an, Aurora.js, welches Ihnen helfen soll, Ihre eigenen Codecs in JavaScript zu erstellen.
Beispiele
Siehe auch
Leitfäden
- Manipulation von Videos mit Canvas
- HTML playbackRate erklärt
- Verwendung der Web Audio API
- Grundlagen der Web-Audio-Raumklang
- Verwendung von Videoframes als WebGL-Textur (Sie können auch die THREE.js WebGL-Bibliothek (und andere) verwenden, um diesen Effekt zu erzielen)
- Animation von Texturen in WebGL
- Entwicklung von Spielaudio mit der Web Audio API (Raumeffekte und Filter) (2012)
Referenz
- Die
<audio>
- und<video>
-Elemente - Die
HTMLMediaElement
API - Das
<canvas>
-Element - Web Audio API
- AudioContext
- Weitere Informationen zu Räumlichem Audio
- Webmedientechnologien