12k
All articles

So fügen Sie Videowiedergabe zu Vue-Apps hinzu

Fügen Sie Videowiedergabe zu Vue-Apps mit nativen HTML5-Videos, wiederverwendbaren Komponenten oder Video.js für HLS, Untertitel, Autoplay und Cleanup hinzu.

OpenReplay Team
OpenReplay Team
So fügen Sie Videowiedergabe zu Vue-Apps hinzu

Es gibt drei Möglichkeiten, Videowiedergabe zu einer Vue-App hinzuzufügen, und welche die richtige ist, hängt davon ab, wie viel Kontrolle Sie benötigen: Verwenden Sie das native HTML5-<video>-Element für einen einfachen eingebetteten Clip, greifen Sie zu Video.js, wenn Sie adaptives Streaming, Untertitel oder breite Formatunterstützung benötigen, und setzen Sie eine fertige Komponente wie @videojs-player/vue ein, wenn Sie Video.js-Funktionen wollen, ohne den Player selbst zu verdrahten.

Der Clip läuft in der Regel einwandfrei auf dem Rechner, auf dem Sie ihn gebaut haben. Dann öffnet ein Tester die Seite auf einem iPhone und sie springt in den Vollbildmodus, oder Autoplay tut in Chrome stillschweigend gar nichts und niemand kann sagen, warum. Dieser Leitfaden geht daher alle drei Ansätze mit kopierfertigem Vue-3-<script setup>-Code durch und behandelt die Fehler, die erst auf dem Gerät einer anderen Person auftreten.

Die wichtigsten Erkenntnisse

  • Für einen einfachen eingebetteten Clip mit Standardsteuerelementen genügt das native HTML5-<video>-Element, gebunden mit :src, controls und poster — ganz ohne Bibliothek.
  • In Vue 3 mit <script setup> greifen Sie das Element über eine Template-ref() ab und rufen die native Media-API auf videoRef.value innerhalb von onMounted auf, niemals über document.querySelector.
  • Video.js wird ohne Styling gerendert, solange Sie nicht video.js/dist/video-js.css importieren — der mit Abstand häufigste Grund dafür, dass ein Video.js-Player in Vue kaputt aussieht.
  • Immer wenn Sie Video.js initialisieren, rufen Sie player.dispose() in onBeforeUnmount (Vue 3) auf. Wird das ausgelassen, bleiben Player und zugehöriges DOM bei jedem Unmount als Leak zurück.
  • Browser blockieren Autoplay mit Ton: Für zuverlässiges Autoplay müssen Sie sowohl muted als auch autoplay setzen und zusätzlich playsinline ergänzen, damit iOS Safari inline abspielt, statt den Vollbildmodus zu erzwingen.

Wie wählen Sie einen Ansatz für den Vue-Videoplayer aus?

Wählen Sie natives <video>, wenn Sie keine eigene UI und kein adaptives Streaming brauchen; wählen Sie einen eigenen Wrapper, wenn Sie maßgeschneiderte Steuerelemente bei voller Kontrolle wollen; wählen Sie Video.js oder dessen Komponenten-Wrapper, wenn Sie HLS, Untertitel oder viele Formate benötigen. Diese drei Kriterien entscheiden: Brauchen Sie eine eigene UI, brauchen Sie adaptives Streaming (HLS/DASH), und wie viele Abhängigkeiten können Sie verkraften?

AnsatzZusätzliche AbhängigkeitenAufwand für eigene UIHLS / UntertitelWählen Sie dies, wenn
Natives <video>KeineSie bauen jedes Steuerelement selbstNur natives HLS (Safari)Einfacher Clip, minimales Bundle
Eigene Wrapper-KomponenteKeineVolle Kontrolle über SlotsNur natives HLSMaßgeschneiderte UI, app-weit wiederverwendet
Video.js / @videojs-player/vuevideo.js (+ Wrapper)Skin oder OverrideJa, integriertFormatvielfalt, Streaming, Tracks

Natives HTML5-<video> in Vue (hier anfangen)

Der schnellste Weg, Videowiedergabe in Vue hinzuzufügen, ist ein natives <video>-Element mit über :src, poster und preload gebundenen Props, ergänzt um eine Template-ref(), um die HTMLMediaElement-API aufzurufen: play(), pause() und .muted. Binden Sie in Vue 3 <script setup> native Media-Events wie timeupdate, loadedmetadata und ended direkt im Template, damit Vue die Listener für Sie registriert und wieder entfernt.

<script setup>
import { ref } from 'vue'

const videoRef = ref(null)
const playing = ref(false)
const muted = ref(false)
const current = ref(0)
const duration = ref(0)

function togglePlay() {
  const el = videoRef.value
  el.paused ? el.play() : el.pause()
}

function toggleMute() {
  const el = videoRef.value
  el.muted = !el.muted
  muted.value = el.muted
}
</script>

<template>
  <video
    ref="videoRef"
    src="/media/clip.mp4"
    poster="/media/poster.jpg"
    preload="metadata"
    playsinline
    @play="playing = true"
    @pause="playing = false"
    @ended="playing = false"
    @loadedmetadata="duration = $event.target.duration"
    @timeupdate="current = $event.target.currentTime"
  />
  <div>
    <button @click="togglePlay">{{ playing ? 'Pause' : 'Play' }}</button>
    <button @click="toggleMute">{{ muted ? 'Unmute' : 'Mute' }}</button>
    <span>{{ current.toFixed(0) }}s / {{ duration.toFixed(0) }}s</span>
  </div>
</template>

Die Template-ref="videoRef" löst sich zum DOM-Element auf videoRef.value auf. Greifen Sie darauf innerhalb von Handlern oder in onMounted zu, nicht bevor die Komponente gemountet ist. In der Options API lauten die Entsprechungen this.$refs.videoRef und der mounted-Hook. Wenn Sie Listener manuell mit addEventListener registrieren, entfernen Sie sie in onUnmounted; die Bindung über @event im Template vermeidet diese Fehlerklasse vollständig.

Wiederverwendbare eigene Player-Komponente

Um Player-Logik in einer App wiederzuverwenden, kapseln Sie das native <video> in einer Komponente, die ihre Steuerelemente und ihren Zustand über einen Scoped Slot nach außen gibt, sodass jede Verwendung ihre eigenen Buttons und ihre eigene Fortschrittsleiste zusammenstellen kann, ohne die Wiedergabelogik zu duplizieren.

<!-- VideoPlayer.vue -->
<script setup>
import { ref } from 'vue'
defineProps({ src: String, poster: String })
const emit = defineEmits(['timeupdate', 'ended'])

const videoRef = ref(null)
const playing = ref(false)

function togglePlay() {
  const el = videoRef.value
  el.paused ? el.play() : el.pause()
}
</script>

<template>
  <video
    ref="videoRef"
    :src="src"
    :poster="poster"
    playsinline
    @play="playing = true"
    @pause="playing = false"
    @timeupdate="emit('timeupdate', $event.target.currentTime)"
    @ended="emit('ended')"
  />
  <slot name="controls" :playing="playing" :toggle-play="togglePlay" />
</template>

Die Konsumenten ziehen playing und togglePlay aus den Slot-Props und rendern die UI, die sie jeweils brauchen. Ein Basis-Player kann so sowohl ein minimales Embed mit reinem Play-Button als auch einen vollwertigen Player mit Fortschrittsleiste bedienen — die Medienlogik bleibt an einer einzigen Stelle.

<VideoPlayer src="/media/clip.mp4" @ended="onEnded">
  <template #controls="{ playing, togglePlay }">
    <button @click="togglePlay">{{ playing ? 'Pause' : 'Play' }}</button>
  </template>
</VideoPlayer>

Wann sollten Sie Video.js einsetzen?

Setzen Sie Video.js ein, wenn Sie HLS/adaptives Streaming, Untertitel und Text-Tracks, ein einheitliches Skin oder eine Formatvielfalt jenseits dessen benötigen, was natives <video> garantiert. Installieren Sie video.js, rendern Sie ein <video class="video-js">, initialisieren Sie videojs(ref, options) in onMounted und importieren Sie das Stylesheet sowie räumen Sie den Player beim Unmount auf.

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue'
import videojs from 'video.js'
import 'video.js/dist/video-js.css' // required, or the player renders unstyled

const videoRef = ref(null)
let player = null

const options = {
  autoplay: false,
  controls: true,
  preload: 'auto',
  fluid: true,
  sources: [{ src: '/media/clip.mp4', type: 'video/mp4' }]
}

onMounted(() => {
  player = videojs(videoRef.value, options)
})

onBeforeUnmount(() => {
  if (player) player.dispose()
})
</script>

<template>
  <video ref="videoRef" class="video-js" playsinline />
</template>

Zwei Dinge lassen sich hier leicht falsch machen: Der Name der Template-ref muss mit dem übereinstimmen, was Sie in onMounted auslesen (ein nicht zusammenpassendes Paar aus videoJsPlayer/videoPlayer wirft einen Fehler), und dispose() gehört bei Vue 3 in onBeforeUnmount. beforeDestroy ist ein Vue-2-Hook, und Vue 2 hat am 31. Dezember 2023 sein End of Life erreicht. Die aktuelle stabile Linie ist Video.js 8.x, mit 8.24.0, veröffentlicht im August 2026. Ein modulares Video.js 10 befindet sich in der Beta-Phase und ist noch nicht allgemein verfügbar: Die Zeitleiste des v10-Repositorys führt die allgemeine Verfügbarkeit weiterhin als in Arbeit befindlich auf, wobei Parität für Video.js Core und contrib bis Ende 2026 angestrebt wird. Bleiben Sie für den Produktivbetrieb bei 8.x und halten Sie die Installation ungepinnt: npm install video.js.

Fertige Komponente: @videojs-player/vue

Der Weg mit dem wenigsten Code zu Video.js in Vue 3 ist @videojs-player/vue, ein sofort einsatzbereites <video-player> mit reaktiven Props (src, sources, poster, controls, loop, volume, fluid, playsinline, tracks) und einem { player, state }-Scoped-Slot für eigene Steuerelemente. Initialisierung und Teardown werden intern übernommen, sodass ein HLS-Clip nur ein einzeiliger Austausch der Quelle ist.

<script setup>
import { VideoPlayer } from '@videojs-player/vue'
import 'video.js/dist/video-js.css'
</script>

<template>
  <video-player
    src="https://example.com/stream/playlist.m3u8"
    poster="/media/poster.jpg"
    controls
    fluid
    playsinline
    :volume="0.6"
    @ready="(payload) => console.log(payload.state)"
  >
    <template #default="{ player, state }">
      <button @click="state.playing ? player.pause() : player.play()">
        {{ state.playing ? 'Pause' : 'Play' }}
      </button>
    </template>
  </video-player>
</template>

Ein Vorbehalt, den Sie vor dem Einsatz kennen sollten: Dies ist zwar der Standard-Wrapper für Vue 3, aber sein npm-Release ist bei v1.0.0 aus dem Jahr 2022 stehen geblieben, und Dependency-Scanner markieren ihn als schwach gepflegt. Der veröffentlichte Peer-Dependency-Bereich verlangt weiterhin video.js 7.x, sodass die Kombination mit Video.js 8 bei der Installation eine Peer-Dependency-Warnung erzeugt. Wenn Sie Vue 2 einsetzen, verwenden Sie den Legacy-Build vue-video-player, der im Legacy-Abschnitt des Repositorys verlinkt ist. Aktuelle Releases von @videojs-player/vue richten sich ausschließlich an Vue 3.

Checkliste Vue-spezifischer Stolperfallen

Die meisten „Video spielt nicht”-Bugs in Vue lassen sich auf eine Handvoll Plattformregeln zurückführen, die das Code-Review passieren, aber auf echten Geräten scheitern. Insbesondere Fehler bei Autoplay und playsinline bleiben unsichtbar, bis ein Nutzer darauf stößt — genau jene Klasse gerätespezifischer Probleme, die Session Replay aus echten Sessions ans Licht bringt.

  • Beim Unmount aufräumen. Rufen Sie für Video.js player.dispose() auf und entfernen Sie in onUnmounted alle manuell registrierten addEventListener-Handler, sonst leakt jeder Mount-/Unmount-Zyklus.
  • Das CSS importieren. import 'video.js/dist/video-js.css' — andernfalls bleibt der Player ohne Styling.
  • Stummgeschaltetes Autoplay ist Pflicht. Browser blockieren Autoplay mit Ton; setzen Sie sowohl muted als auch autoplay, gemäß der Autoplay-Policy von Chrome.
  • playsinline für iOS. Ohne das playsinline-Attribut öffnet iOS Safari auf dem iPhone das Video meist im Vollbildmodus; auf dem iPad verhält es sich anders.
  • Template-Refs statt DOM-Queries verwenden. Greifen Sie über ref() auf das Element zu, niemals über document.querySelector.

Fangen Sie nativ an: Ein gebundenes <video> liefert Wiedergabe in Minuten und ohne jede Abhängigkeit. Steigen Sie in dem Moment auf Video.js oder @videojs-player/vue um, in dem Sie HLS, Untertitel oder eine einheitliche browserübergreifende UI benötigen — und bauen Sie das dispose()-Cleanup vom ersten Commit an ein, damit daraus nie ein Leak wird, den Sie später jagen müssen.

FAQs

Wie spiele ich einen HLS-Stream (.m3u8) in einer Vue-App ab?

Natives HTML5-Video spielt HLS nur in Safari ab; für browserübergreifendes HLS verwenden Sie daher Video.js oder dessen Wrapper @videojs-player/vue, der HLS-Unterstützung über die videojs-http-streaming-Engine mitbringt. Mit @videojs-player/vue setzen Sie src auf die URL Ihrer .m3u8-Playlist, und die Komponente kümmert sich intern um die Streaming-Engine. In reinem Chrome oder Firefox hat natives Video kein integriertes HLS — der Hauptgrund, zu Video.js zu greifen.

Warum funktioniert Autoplay in meinem Vue-Videoplayer nicht?

Stummgeschaltetes Autoplay ist in der Regel erlaubt, aber Autoplay mit Ton setzt voraus, dass der Nutzer zuvor mit der Website interagiert hat; Chrome erlaubt es außerdem, wenn die Website einen hohen Media Engagement Index aufweist. Safari wendet eine eigene, ähnliche Richtlinie an. Für zuverlässiges Autoplay müssen Sie sowohl muted als auch autoplay am Element oder in den Video.js-Optionen setzen. Dieser Fehler ist im Code-Review unsichtbar, weil er von Browser-Richtlinie und Gerät abhängt, nicht von Ihrem Markup — er zeigt sich also erst, wenn ein echter Nutzer die Seite lädt.

Was ist der Unterschied zwischen @videojs-player/vue und der direkten Verwendung von Video.js?

@videojs-player/vue ist eine sofort einsatzbereite Vue-3-Komponente, die Video.js kapselt, Initialisierung und Teardown intern übernimmt und reaktive Props sowie einen Scoped Slot mit player und state bereitstellt. Bei der direkten Verwendung von Video.js rendern Sie hingegen selbst ein video-Element, rufen videojs() in onMounted auf und geben den Player in onBeforeUnmount selbst wieder frei. Der Wrapper benötigt weniger Code, doch sein npm-Release ist bei v1.0.0 aus dem Jahr 2022 stehen geblieben — direktes Video.js gibt Ihnen mehr Kontrolle über Versionen und Lifecycle.

Kann ich @videojs-player/vue noch mit Vue 2 verwenden?

Nein. Aktuelle Releases von @videojs-player/vue richten sich ausschließlich an Vue 3. Das Paket erhielt seinen heutigen Namen, als React-Unterstützung hinzukam, und dieser Wechsel war für Vue-Nutzer ein Breaking Change. Für Vue 2 benötigen Sie den älteren Build vue-video-player 5.x, den das Repository weiterhin in seinem Legacy-Abschnitt verlinkt. Vue 2 selbst hat am 31. Dezember 2023 sein End of Life erreicht, neue Projekte sollten daher auf Vue 3 setzen.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.