Audio- und Videomanipulation
Die Schönheit des Webs besteht darin, dass Sie Technologien kombinieren können, um neue Formen zu schaffen. Mit nativen Audio- und Video-Möglichkeiten im Browser können wir diese Datenströme mit Technologien wie <canvas>
, WebGL oder der Web Audio API nutzen, um Audio und Video direkt zu modifizieren. Beispielsweise kann man Audio mit Hall-/Kompressions-Effekten bearbeiten oder Filter wie Graustufen/Sepia auf Video anwenden. Dieser Artikel bietet eine Referenz, die erklärt, was Sie tun müssen.
Videomanipulation
Die Fähigkeit, die Pixelwerte aus jedem Frame eines Videos zu lesen, kann sehr nützlich sein.
Video und Canvas
Das <canvas>
-Element bietet eine Oberfläche, um Grafiken auf Webseiten zu zeichnen. Es ist sehr leistungsfähig und kann eng mit Video gekoppelt werden.
Die allgemeine Technik ist:
- Schreiben Sie einen Frame aus dem
<video>
-Element in das<canvas>
-Element. - Lesen Sie die Daten aus dem
<canvas>
-Element und manipulieren Sie sie. - Schreiben Sie die manipulierten Daten auf Ihr "Anzeige"-
<canvas>
(das effektiv dasselbe Element sein kann). - Anhalten und wiederholen.
Zum Beispiel wollen wir ein Video in Graustufen anzeigen. In diesem Fall zeigen wir sowohl das Quellvideo als auch die Ausgabeframes in Graustufen an. Normalerweise, wenn Sie eine Funktion "Video in Graustufen abspielen" implementieren würden, würden Sie wahrscheinlich display: none
zum Stil für das <video>
-Element hinzufügen, um das Quellvideo von der Anzeige fernzuhalten, während nur das Canvas die veränderten Frames zeigt.
HTML
Wir können unseren Videoplayer und das <canvas>
-Element wie folgt 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 bearbeitet die 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 ziemlich einfaches Beispiel dafür, wie man Videoframes mithilfe eines Canvas manipuliert. Aus Effizienzgründen sollten Sie in Erwägung ziehen, requestAnimationFrame()
anstelle von setTimeout()
zu verwenden, wenn Sie auf Browsern laufen, die diese Funktion unterstützen.
Das gleiche Ergebnis können Sie erzielen, indem Sie die grayscale()
CSS-Funktion auf das Quell-<video>
-Element anwenden.
Hinweis: Aufgrund möglicher Sicherheitsprobleme, wenn Ihr Video auf einer anderen Domain als Ihr Code liegt, müssen Sie CORS (Cross-Origin Resource Sharing) auf Ihrem Videoserver aktivieren.
Video und WebGL
WebGL ist eine leistungsstarke API, die Canvas nutzt, um hardwarebeschleunigte 3D- oder 2D-Szenen zu zeichnen. Sie können WebGL und das <video>
-Element kombinieren, um Videotexturen zu erstellen, was bedeutet, dass Sie Video in 3D-Szenen einfügen können.
Hinweis: Den Quellcode dieses Demos auf GitHub finden Sie (sehen Sie es live ebenfalls).
Wiedergabegeschwindigkeit
Wir können auch die Geschwindigkeit, mit der Audio und Video abgespielt werden, mithilfe eines Attributs der <audio>
- und <video>
-Elemente mit dem Namen playbackRate
anpassen. playbackRate
ist eine Zahl, die ein Vielfaches darstellt, das auf die Wiedergabegeschwindigkeit angewendet wird, 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, jedoch in beiden Fällen die Wiedergabegeschwindigkeit ändert, aber nicht die Tonhöhe. Um die Tonhöhe des Audios 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: Probieren Sie das playbackRate-Beispiel live aus.
Audiomanipulation
Abgesehen von playbackRate
verwenden Sie zum Manipulieren von Audio typischerweise die Web Audio API.
Eine Audioquelle auswählen
Die Web Audio API kann Audio aus verschiedenen Quellen empfangen, es verarbeiten und zur Ausgabe an einen AudioDestinationNode
zurücksenden, was das Ausgabegerät darstellt, zu dem der Ton nach der Verarbeitung gesendet wird.
Wenn die Audioquelle ist… | Verwenden Sie diesen Web Audio-Knotentyp |
---|---|
Ein Audiotrack aus einem HTML <audio> - oder <video> -Element |
MediaElementAudioSourceNode |
Ein einfacher roher Audiodatenpuffer im Speicher | AudioBufferSourceNode |
Ein Oszillator, der eine Sinuswelle oder eine andere berechnete Wellenform erzeugt | OscillatorNode |
Ein Audiotrack aus WebRTC (wie das Mikrofoneingangssignal, das Sie durch getUserMedia() erhalten können |
MediaStreamAudioSourceNode |
Audiofilter
Die Web Audio API verfügt über viele verschiedene Filter/Effekte, die auf Audio angewendet werden können, beispielsweise 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 Ihr Video zur Vermeidung von Sicherheitsproblemen auf derselben Domain wie Ihr Code sein.
Gemeinsame Audiofilter
Dies sind einige gebräuchliche Arten von Audiofiltern, die Sie anwenden können:
- Low Pass: Lässt Frequenzen unterhalb der Grenzfrequenz durch und dämpft Frequenzen oberhalb der Grenzfrequenz.
- High Pass: Lässt Frequenzen oberhalb der Grenzfrequenz durch und dämpft Frequenzen unterhalb der Grenzfrequenz.
- Band Pass: Lässt einen Frequenzbereich durch und dämpft die Frequenzen unterhalb und oberhalb dieses Frequenzbereichs.
- Low Shelf: Lässt alle Frequenzen durch, fügt jedoch einen Schub (oder eine Dämpfung) zu den niedrigeren Frequenzen hinzu.
- High Shelf: Lässt alle Frequenzen durch, fügt jedoch einen Schub (oder eine Dämpfung) zu den höheren Frequenzen hinzu.
- Peaking: Lässt alle Frequenzen durch, fügt jedoch einen Schub (oder eine Dämpfung) zu einem Bereich von Frequenzen hinzu.
- Notch: Lässt alle Frequenzen durch, außer für eine bestimmte Gruppe von Frequenzen.
- All Pass: Lässt alle Frequenzen durch, ändert jedoch die Phasenbeziehung zwischen den verschiedenen Frequenzen.
Hinweis: Siehe BiquadFilterNode
für weitere Informationen.
Faltung und Impulse
Es ist auch möglich, Impulsantworten auf Audio anzuwenden, indem der ConvolverNode
verwendet wird. Eine Impulsantwort ist der Klang, der nach einem kurzen Tonimpuls (wie einem Händeklatschen) erzeugt wird. Eine Impulsantwort wird die Umgebung widerspiegeln, in der der Impuls erzeugt wurde (zum Beispiel ein Echo, das entsteht, wenn man in einem Tunnel in die Hände klatscht).
Beispiel
const convolver = context.createConvolver();
convolver.buffer = this.impulseResponseBuffer;
// Connect the graph.
source.connect(convolver);
convolver.connect(context.destination);
Siehe diesen CodePen für ein angewandtes (aber sehr, sehr albernes; wie, kleine Kinder werden kichern, weil es albern ist) Beispiel.
Räumliches Audio
Wir können Audio auch mithilfe eines Panner-Knotens positionieren. Ein Panner-Knoten—PannerNode
—lässt uns ein Quell-Kegel sowie Positionierungs- und Directional-Elemente definieren, alles im dreidimensionalen Raum, definiert durch dreidimensionale kartesische Koordinaten.
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 (sehen Sie es live ebenfalls).
JavaScript-Codecs
Es ist auch möglich, Audio auf niedriger Ebene mit JavaScript zu manipulieren. Dies kann nützlich sein, wenn Sie eigene Audiocodecs erstellen möchten.
Derzeit existieren Bibliotheken für folgende Formate:
Hinweis: Bei Audiocogs können Sie einige Demos ausprobieren; Audiocogs bietet auch ein Framework, Aurora.js, das Ihnen helfen soll, eigene Codecs in JavaScript zu erstellen.
Beispiele
Siehe auch
Tutorials
- Videomanipulation mit Canvas
- HTML-wiedergabeRate erklärt
- Verwendung der Web Audio API
- Grundlagen der räumlichen Audiowiedergabe
- Verwendung von Videoframes als WebGL-Textur (Sie können auch die THREE.js WebGL-Bibliothek (und andere) verwenden, um diesen Effekt zu erzielen)
- Texturen in WebGL animieren
- Entwicklung von Spieleaudio 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