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 unterstützt werden, können wir diese Datenströme mit Technologien wie <canvas>, WebGL oder Web Audio API verwenden, um Audio und Video direkt zu verändern. Beispielsweise können Sie Audio mit Hall- oder Kompressionseffekten versehen oder Video mit Graustufen- oder Sepiafiltern ausstatten. Dieser Artikel bietet eine Referenz, die erklärt, was Sie tun müssen.

Videomanipulation

Die Fähigkeit, die Pixelwerte von jedem Frame eines Videos auszulesen, kann sehr nützlich sein.

Video und Canvas

Das <canvas>-Element bietet eine Oberfläche zum Zeichnen von Grafiken auf Webseiten; es ist sehr leistungsfähig und kann eng mit Video gekoppelt werden.

Die allgemeine Technik ist:

  1. Schreiben Sie einen Frame vom <video>-Element in das <canvas>-Element.
  2. Lesen Sie die Daten vom <canvas>-Element und manipulieren Sie diese.
  3. Schreiben Sie die manipulierten Daten in Ihr "Anzeige"-<canvas> (das effektiv dasselbe Element sein kann).
  4. Anhalten und wiederholen.

Zum Beispiel, um ein Video in Graustufen anzuzeigen. In diesem Fall zeigen wir sowohl das Quellvideo als auch die ausgegebenen Graustufen-Frames. Normalerweise, wenn Sie eine Funktion "Video in Graustufen abspielen" implementieren würden, würden Sie wahrscheinlich display: none zum Stil des <video>-Elements hinzufügen, um zu verhindern, dass das Quellvideo auf dem Bildschirm angezeigt wird, während nur der Canvas die veränderten Frames zeigt.

HTML

Wir können unseren Videoplayer und das <canvas>-Element so 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 folgendes aufrufen:

js
processor.doLoad();

Ergebnis

Dies ist ein ziemlich einfaches Beispiel, das zeigt, wie man Videoframes mit einer Canvas manipuliert. Aus Effizienzgründen sollten Sie in Betracht ziehen, requestAnimationFrame() anstelle von setTimeout() zu verwenden, wenn Sie auf Browsern arbeiten, die dies unterstützen.

Sie können das gleiche Ergebnis erzielen, indem Sie die grayscale() CSS-Funktion auf das Quell-<video>-Element anwenden.

Hinweis: Aufgrund potenzieller Sicherheitsprobleme, wenn Ihr Video auf einer anderen Domain als Ihr Code vorhanden ist, 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 erstellen, was bedeutet, dass Sie Video in 3D-Szenen einfügen können.

Hinweis: Sie finden den Quellcode dieses Demos auf GitHub (siehe es live ebenfalls).

Wiedergabegeschwindigkeit

Wir können auch die Geschwindigkeit, mit der Audio und Video abgespielt werden, über ein Attribut des <audio>- und <video>-Elements namens playbackRate einstellen. 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 mit <video> funktioniert, aber in beiden Fällen die Wiedergabegeschwindigkeit, jedoch nicht die Tonhöhe ändert. Um die Tonhöhe des Audios zu verändern, 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: Versuchen Sie das playbackRate-Beispiel live.

Audiomanipulation

Abgesehen von playbackRate werden Sie normalerweise die Web Audio API verwenden, um Audio zu manipulieren.

Auswahl einer Audioquelle

Die Web Audio API kann Audio von verschiedenen Quellen empfangen, dieses verarbeiten und an einen AudioDestinationNode senden, der das Ausgabegerät darstellt, an das der Ton nach der Verarbeitung gesendet wird.

Wenn die Audioquelle ist… Verwenden Sie diesen Web Audio Node-Typ
Ein Audiotrack von einem HTML <audio>- oder <video>-Element MediaElementAudioSourceNode
Ein einfacher Roh-Audiodatenpuffer im Speicher AudioBufferSourceNode
Ein Oszillator, der eine Sinuswelle oder eine andere berechnete Wellenform erzeugt OscillatorNode
Ein Audiospur von WebRTC (wie das Mikrofoneingangssignal, das Sie mit getUserMedia() erhalten können. MediaStreamAudioSourceNode

Audiofilter

Die Web Audio API verfügt über viele verschiedene Filter/ Effekte, die anhand des BiquadFilterNode angewendet werden können, zum Beispiel.

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, um Sicherheitsprobleme zu vermeiden, sollte Ihr Video sich auf derselben Domain wie Ihr Code befinden.

Häufige Audiofilter

Dies sind einige häufige Arten von Audiofiltern, die Sie anwenden können:

  • Tiefpass: Lässt Frequenzen unterhalb der Grenzfrequenz passieren und dämpft Frequenzen darüber.
  • Hochpass: Lässt Frequenzen oberhalb der Grenzfrequenz passieren und dämpft Frequenzen darunter.
  • Bandpass: Lässt einen Frequenzbereich passieren und dämpft die Frequenzen darunter und darüber.
  • Tiefstellsieb: Lässt alle Frequenzen durch, fügt jedoch eine Verstärkung (oder Dämpfung) der niedrigeren Frequenzen hinzu.
  • Hochstellsieb: 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.
  • Kerbe: Lässt alle Frequenzen durch, außer für eine Reihe von Frequenzen.
  • Allpass: Lässt alle Frequenzen durch, ändert jedoch die Phasenbeziehung zwischen den verschiedenen Frequenzen.

Hinweis: Weitere Informationen finden Sie unter BiquadFilterNode.

Konvolutionen und Impulse

Es ist auch möglich, Impulsantworten auf Audio unter Verwendung des ConvolverNode anzuwenden. Eine Impulsantwort ist der Ton, der nach einem kurzen Impuls von Geräusch (wie ein Händeklatschen) erzeugt wird. Eine Impulsantwort wird die Umgebung kennzeichnen, in der der Impuls erstellt wurde (zum Beispiel ein Echo, das durch Händeklatschen in einem Tunnel erzeugt wird).

Beispiel

js
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; so, dass kleine Kinder kichern, lustiges) Beispiel an.

Räumliches Audio

Wir können auch Audio mit einem Panner-Node positionieren. Ein Panner-Node—PannerNode—ermöglicht es uns, einen Quellenkegel sowie positionsbezogene und Richtungselemente zu definieren, alles in einem 3D-Raum, der durch 3D-kartesische Koordinaten definiert ist.

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

Hinweis: Sie finden ein Beispiel in unserem GitHub-Repository (siehe es live ebenfalls).

JavaScript-Codecs

Es ist auch möglich, Audio auf einer niedrigen Ebene mit JavaScript zu manipulieren. Dies kann nützlich sein, wenn Sie Audio-Codecs erstellen möchten.

Derzeit existieren Bibliotheken für die folgenden Formate:

Hinweis: Bei Audiocogs können Sie einige Demos ausprobieren; Audiocogs bietet auch ein Framework, Aurora.js, das Ihnen helfen soll, Ihre eigenen Codecs in JavaScript zu erstellen.

Beispiele

Siehe auch

Tutorials

Referenz