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:

  1. Schreiben Sie einen Frame aus dem <video>-Element in das <canvas>-Element.
  2. Lesen Sie die Daten aus dem <canvas>-Element und manipulieren Sie sie.
  3. Schreiben Sie die manipulierten Daten auf Ihr "Anzeige"-<canvas> (das effektiv dasselbe Element sein kann).
  4. 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:

html
<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.

js
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:

js
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

html
<video
  id="my-video"
  controls
  src="https://jplayer.org/video/m4v/Big_Buck_Bunny_Trailer.m4v"></video>

JavaScript

js
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

html
<video id="my-video" controls src="my-video.mp4" type="video/mp4"></video>

JavaScript

js
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

js
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

js
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);

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

Referenz