
Einrichtung
# Clone repository
git clone github.com/MatthiasPeltzer/vidply.git
cd vidply
# Install dependencies
npm install
# Build production files
npm run build
# Start dev server
npm run dev
Der Entwicklungsserver läuft unter localhost
Verzeichnisstruktur
vidply/
├── build/ # Build scripts
│ ├── build.js # TypeScript bundling (esbuild → ESM + IIFE)
│ ├── build-css.js # CSS build (clean-css)
│ ├── watch.js # Watch mode
│ └── clean.js # Clean dist
├── demo/ # Demo pages
│ ├── demo.html # Main demo
│ ├── playlist-audio.html # Audio playlist demo
│ ├── playlist-video.html # Video playlist demo
│ ├── hls-test.html # HLS streaming demo
│ ├── dash-test.html # DASH streaming demo
│ └── single-player-dash.html # Single DASH player demo
├── dist/ # Built files (generated)
│ ├── prod/vidply.esm.min.js # ES Module (production)
│ ├── legacy/vidply.min.js # IIFE (production)
│ ├── types/index.d.ts # TypeScript declarations
│ └── vidply.min.css # Styles (production)
├── docs/ # Documentation
├── src/ # Source code (strict TypeScript)
│ ├── core/
│ │ └── Player.ts # Main Player class
│ ├── controls/
│ │ ├── ControlBar.ts # Control bar UI (incl. download button, buffering spinner)
│ │ ├── CaptionManager.ts # Caption handling
│ │ ├── KeyboardManager.ts # Keyboard shortcuts
│ │ ├── SettingsDialog.ts # Settings menu
│ │ └── TranscriptManager.ts
│ ├── features/
│ │ └── PlaylistManager.ts # Playlist support
│ ├── i18n/
│ │ ├── i18n.ts # i18n system
│ │ ├── translations.ts # Translation loader
│ │ └── languages/ # Built-in languages
│ │ ├── en.ts
│ │ ├── de.ts
│ │ ├── es.ts
│ │ ├── fr.ts
│ │ └── ja.ts
│ ├── icons/
│ │ └── Icons.ts # SVG icon definitions
│ ├── renderers/
│ │ ├── HTML5Renderer.ts # Native HTML5 video/audio
│ │ ├── YouTubeRenderer.ts # YouTube iframe API
│ │ ├── VimeoRenderer.ts # Vimeo Player API
│ │ ├── SoundCloudRenderer.ts# SoundCloud Widget API
│ │ ├── HLSRenderer.ts # hls.js integration + native iOS bridge
│ │ └── DASHRenderer.ts # dash.js integration
│ ├── styles/
│ │ └── vidply.css # Main stylesheet
│ ├── types/ # Shared TypeScript types
│ │ ├── options.ts # PlayerOptions
│ │ └── globals.d.ts # Ambient declarations (Hls, dashjs, …)
│ ├── utils/
│ │ ├── DOMUtils.ts # DOM helpers
│ │ ├── EventEmitter.ts # Event system
│ │ ├── TimeUtils.ts # Time formatting
│ │ ├── FocusUtils.ts # Focus management
│ │ ├── MenuUtils.ts # Menu helpers
│ │ ├── StorageManager.ts # localStorage wrapper
│ │ └── ...
│ └── index.ts # Main entry point
├── index.html # Development page
├── tsconfig.json # Strict TypeScript config
├── package.json
└── server.js # Dev server
NPM-Skripte
| Skript | Beschreibung |
|---|---|
npm run build | Alles erstellen (TypeScript-Bundles + Typen + CSS) |
npm run build:js | TypeScript mit esbuild bündeln (ESM + IIFE) |
npm run build:types | Typdeklarationen .d.ts Typdeklarationen an dist/types/ |
npm run build:css | Nur CSS erstellen |
npm run typecheck | tsc --noEmit Strenge Typprüfung im src/ |
npm run watch | Watch-Modus (automatischer Neuaufbau) |
npm run dev | Entwicklungsserver starten |
npm run clean | Verzeichnis „dist“ bereinigen |
npm run start | Erstellen + Entwicklungsserver starten |
npm run test | Vitest-Unit-Tests |
npm run test:e2e | Playwright-End-to-End-Tests |
Build-System
TypeScript-Bundles (esbuild)
build/build.js verwendet die TypeScript-Quelldateien direkt (esbuild übernimmt die Transpilation) und erzeugt:
| Datei | Format | Verwendung |
|---|---|---|
dev/vidply.esm.js | ES-Modul | Entwicklung |
prod/vidply.esm.min.js | ES-Modul | Produktion |
legacy/vidply.js | IIFE | Entwicklung |
legacy/vidply.min.js | IIFE | Produktion |
Funktionen:
- Code-Splitting (Renderer werden bei Bedarf geladen)
- Tree Shaking
- Source Maps (Entwicklung)
- Minifizierung (Produktion)
Typdeklarationen (tsc)
npm run build:types Läufe tsc --emitDeclarationOnly gegen tsconfig.build.json und gibt aus:
| Datei | Verwenden |
|---|---|
dist/types/index.d.ts | Öffentlichen Typ-Eintrag, referenziert von package.json#types |
dist/types/**/*.d.ts | Modulbezogene Deklarationen für „tree-shakable“ benannte Importe |
CSS (clean-css)
build/build-css.js erzeugt:
| Datei | Verwendung |
|---|---|
vidply.css | Entwicklung |
vidply.min.css | Produktion |
Architektur
Kernkomponenten
Player
├── ControlBar # UI controls
│ ├── PlayButton
│ ├── ProgressBar
│ ├── VolumeControl
│ ├── DownloadButton # opt-in via downloadButton/downloadUrl
│ ├── PipButton # native PiP, or pin/unpin custom floating player when floating: true
│ ├── SettingsButton
│ └── FullscreenButton
├── BufferingOverlay # Centered loading spinner (.vidply-loading)
├── CaptionManager # Captions/subtitles
├── KeyboardManager # Keyboard shortcuts
├── TranscriptManager # Interactive transcript
├── FloatingPlayerManager # Custom in-page miniplayer ("own PiP"), opt-in via floating: true
├── Renderer # Media playback
│ ├── HTML5Renderer
│ ├── YouTubeRenderer
│ ├── VimeoRenderer
│ ├── SoundCloudRenderer
│ ├── HLSRenderer # hls.js + native iOS TextTrack bridge
│ └── DASHRenderer
└── PlaylistManager # Playlist handling
Ereignisablauf
User Action → KeyboardManager/ControlBar → Player → Renderer → DOM
↓
EventEmitter → External Listeners
Renderer-Auswahl
// src/core/Player.ts
selectRenderer(src: string): RendererCtor {
if (isYouTubeUrl(src)) return YouTubeRenderer;
if (isVimeoUrl(src)) return VimeoRenderer;
if (src.includes('soundcloud.com')) return SoundCloudRenderer;
if (isHLSUrl(src)) return HLSRenderer; // hls.js (or native HLS on iOS/iPadOS)
if (isDASHUrl(src)) return DASHRenderer;
return HTML5Renderer;
}
Der HLS-Renderer entscheidet selbst, ob
hls.js(Chrome / Firefox / Edge / Desktop-Safari) oder die native<video>HLS-Unterstützung (iOS / iPadOS, wo MSE nicht verfügbar ist). Auf dem nativen Pfad bindet er dieTextTrackin die Benutzeroberfläche von VidPly für Untertitel, Transkripte und Qualität ein, sodass die Funktionsparität erhalten bleibt.
Hinzufügen von Funktionen
Neue Schaltfläche
- Zur Steuerleiste hinzufügen (
src/controls/ControlBar.ts):
createMyButton(): HTMLButtonElement {
const button = document.createElement('button');
button.className = 'vidply-button vidply-my-button';
button.setAttribute('aria-label', i18n.t('player.myButton'));
button.innerHTML = Icons.myIcon;
button.addEventListener('click', () => this.player.myAction());
return button;
}
- Symbol hinzufügen (
src/icons/Icons.ts):
export const Icons = {
// ...existing icons
myIcon: `<svg>...</svg>`,
} as const;
- Übersetzung hinzufügen (
src/i18n/languages/en.ts):
export default {
player: {
// ...existing
myButton: 'My Button',
}
};
- Zur Player-API hinzufügen (
src/core/Player.ts):
myAction(): void {
this.emit('myaction');
}
Neuer Renderer
- Renderer erstellen (
src/renderers/MyRenderer.ts):
import type { Player } from '../core/Player';
export class MyRenderer {
constructor(public player: Player) {}
async init(): Promise<void> { /* ... */ }
async load(src: string): Promise<void> { /* ... */ }
play(): void { /* ... */ }
pause(): void { /* ... */ }
seek(time: number): void { /* ... */ }
setVolume(vol: number): void { /* ... */ }
getCurrentTime(): number { /* ... */ }
getDuration(): number { /* ... */ }
destroy(): void { /* ... */ }
}
- Im Player registrieren:
import { MyRenderer } from '../renderers/MyRenderer';
// In selectRenderer()
if (isMyServiceUrl(src)) return MyRenderer;
Neue Sprache
- Sprachdatei erstellen (
src/i18n/languages/pt.ts):
export default {
player: {
play: 'Reproduzir',
pause: 'Pausar',
// ... all translations
}
};
- Registrieren (
src/i18n/translations.ts):
import pt from './languages/pt';
export const translations = {
en, de, es, fr, ja,
pt,
};
CSS-Architektur
Variablen
:root {
/* Colors */
--vidply-primary-color: #3b82f6;
--vidply-background: rgba(0, 0, 0, 0.8);
--vidply-text-color: #ffffff;
/* Sizing */
--vidply-button-size: 40px;
--vidply-icon-size: 20px;
/* Spacing */
--vidply-gap-sm: 4px;
--vidply-gap-md: 8px;
--vidply-gap-lg: 12px;
}
BEM-Namenskonvention
.vidply-player { } /* Block */
.vidply-player--fullscreen { } /* Modifier */
.vidply-controls { } /* Block */
.vidply-controls__left { } /* Element */
.vidply-button { } /* Block */
.vidply-button--active { } /* Modifier */
Barrierefreiheit
/* High contrast mode */
@media (forced-colors: active) {
.vidply-button {
border: 1px solid currentColor;
}
}
/* Focus visible */
.vidply-button:focus-visible {
outline: 2px solid var(--vidply-primary-color);
outline-offset: 2px;
}
/* Touch targets */
.vidply-button {
min-width: 44px;
min-height: 44px;
}
Testen
Manuelles Testen
- Öffnen
localhostnachnpm run dev - Test-Demos:
demo/demo.html- Voller Funktionsumfangdemo/playlist-audio.html- Audio-Wiedergabelistendemo/playlist-video.html- Video-Playlistsdemo/hls-test.html- HLS-Streamingdemo/dash-test.html- DASH-Streaming
Barrierefreiheitstests
- Tastatur: Navigation ausschließlich über die Tastatur
- Bildschirmleseprogramm: Testen mit NVDA/VoiceOver
- Hoher Kontrast: Windows HCM aktivieren
- Mobilgeräte: Touch-Interaktionen testen
Browser-Tests
| Browser | Priorität |
|---|---|
| Chrome | Hoch |
| Firefox | Hoch |
| Safari | Hoch |
| Edge | Mittel |
| iOS Safari | Hoch |
| Android Chrome | Mittel |
Plugin-System
EventEmitter
// Player extends EventEmitter
player.on('play', () => console.log('Playing'));
player.on('pause', () => console.log('Paused'));
player.on('timeupdate', (time) => console.log(time));
// Custom events
player.emit('mycustomevent', { data: 'value' });
Verfügbare Ereignisse
| Ereignis | Daten | Beschreibung |
|---|---|---|
ready | - | Player initialisiert |
play | - | Wiedergabe gestartet |
pause | - | Wiedergabe angehalten |
ended | - | Wiedergabe beendet |
timeupdate | Zeit | Aktuelle Zeit geändert |
volumechange | Lautstärke | Lautstärke geändert |
playbackspeedchange | Geschwindigkeit | Geschwindigkeit geändert |
fullscreenchange | istVollbild | Vollbild umgeschaltet |
hlsmanifestparsed | Daten | HLS-Manifest analysiert |
dashqualitychanged | Daten | DASH-Qualität geändert |
textcuesupdate | - | Neue Text-Cues verfügbar (HLS/DASH) |
captionsenabled | Spur | Untertitel aktiviert |
captionsdisabled | - | Untertitel deaktiviert |
playlisttrackchange | Element | Titel in der Wiedergabeliste geändert |
error | Fehler | Es ist ein Fehler aufgetreten |
Debugging
Debug-Modus aktivieren
const player = new Player('#video', { debug: true });
Konsolenprotokollierung
if (this.options.debug) {
console.log('[VidPly]', message, data);
}
Häufige Probleme
| Problem | Schritte zur Fehlerbehebung |
|---|---|
| Player wird nicht initialisiert | Überprüfen Sie das data-vidply Attribut; Konsolenfehler prüfen |
| Renderer wird nicht geladen | Überprüfe das Format der Quell-URL; überprüfe die Netzwerkanfragen |
| Untertitel werden nicht angezeigt | VTT-Syntax überprüfen; CORS prüfen |
| Tastatur funktioniert nicht | Überprüfen Sie keyboard: true; Fokus überprüfen |
Dokumentationsdateien
| Datei | Inhalt |
|---|---|
| GETTING_STARTED.md | Grundlegende Einrichtung |
| USAGE.md | Detaillierte API-Nutzung |
| PLAYLIST.md | Wiedergabelisten-Funktionen |
| TRANSCRIPT.md | Transkriptionssystem |
| KEYBOARD.md | Tastaturkürzel |
| BUILD.md | Details zum Build-System |
| CHANGELOG.md | Versionshistorie |
| Benutzerhandbuch.md | Integrationshandbuch |
Kurzreferenz
Wichtige Dateien
| Was | Wo |
|---|---|
| Einstiegspunkt | src/index.ts |
| Player-Klasse | src/core/Player.ts |
| Typ der Spieleroptionen | src/types/options.ts |
| Steuerleiste | src/controls/ControlBar.ts |
| Untertitel | src/controls/CaptionManager.ts |
| Tastatur | src/controls/KeyboardManager.ts |
| i18n | src/i18n/i18n.ts |
| Stile | src/styles/vidply.css |
| Symbole | src/icons/Icons.ts |
| TypeScript-Konfiguration | tsconfig.json |
Build-Ausgabe
| Datei | Format | Größe |
|---|---|---|
vidply.esm.min.js | ESM | ~45 KB |
vidply.min.js | IIFE | ~50 KB |
vidply.min.css | CSS | ~15 KB |
Externe Abhängigkeiten
| Abhängigkeit | Zweck | Geladen |
|---|---|---|
| hls.js | HLS-Streaming (Chrome / Firefox / Edge / Desktop-Safari) | On-Demand (CDN) |
| dash.js | DASH-Streaming | On-Demand (CDN) |
| YouTube-IFrame-API | YouTube-Wiedergabe | On-Demand |
| Vimeo-Player-API | Vimeo-Wiedergabe | Auf Abruf |
| SoundCloud-Widget-API | SoundCloud-Wiedergabe | Auf Abruf |
Mitwirken
- Repository forken
- Feature-Branch erstellen:
git checkout -b feature/my-feature - Änderungen vornehmen
- Gründlich testen
- Erstellen:
npm run build - Committen:
git commit -m 'Add my feature' - Push:
git push origin feature/my-feature - Pull-Anfrage öffnen
Code-Stil
- Strict TypeScript (
strict: true,noImplicitAny,strictNullChecks) - BEM-CSS-Namenskonvention
- Aussagekräftige Variablennamen
- Kommentiere nicht offensichtliche Absichten (nicht, was der Code tut)
- Füge ARIA-Attribute zu jedem interaktiven Element hinzu
- Ausführen
npm run typecheckundnpm run testvor dem Commit
Version: 1.1.7 | Lizenz: GPL-2.0-oder-später