npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fritill/nuxt-video-player

v1.0.3

Published

Nuxt video player module with HLS and DASH streaming support

Readme

Video Player Module

Lightweight Nuxt module that registers DX video player components, composables, and i18n locales. Use DXVideoPlayer as the main entry point and consume the exposed refs (videoElement, controls, streaming, keyMomentsState) via defineExpose when needed.

Usage (quick)

  • Install the module and add to nuxt.config under modules (config key: videoPlayer).
  • Pass a source { type: 'hls' | 'dash' | 'file', src, drm? } to DXVideoPlayer plus optional poster, keyMoments, autoplay, muted.
  • Listen to emits: ready, play, pause, ended, timeupdate(time), error(err).
  • App config overrides: set appConfig.videoPlayer.ui to merge custom class names from types/ui.ts.

Architecture at a glance

  • Components: runtime/components/DXVideoPlayer* is the primary UI; helper controls and key-moment panel live in the same folder. Legacy KeyMoments.vue/ProgressBar.vue are pending consolidation.
  • Composables: controls (useVideoControls), streaming adapters (useVideoStreaming), UI config (useVideoPlayerUI), key moments, progress bar, frame preview, and context helpers.
  • Types & i18n: shared contracts in runtime/types, locales in runtime/i18n/locale (en/ar).

Refactoring Plan (Clean, DRY, Expandable)

Phase 1: Core Architecture & State Management

Goal: Establish single source of truth for state and eliminate duplication

1.1 State Unification ✅

  • [x] Decision: Keep useVideoControls as primary state (it's closer to video element), remove useVideoPlayer
  • [x] Move analytics/stats tracking from useVideoPlayer into separate composables/analytics/useVideoAnalytics.ts
  • [x] Move playlist/source management from useVideoPlayer into composables/core/useVideoPlaylist.ts
  • [x] Delete useVideoPlayer.ts once its features are extracted

1.2 Context System ✅

  • [x] Fix context mismatch: DXVideoPlayer.vue uses string 'video-controls' but useVideoControlsContext.ts uses Symbol
  • [x] Standardize on Symbol-based keys in composables/core/context/keys.ts:
    • VIDEO_CONTROLS_KEY
    • VIDEO_STREAMING_KEY
    • VIDEO_UI_KEY
    • VIDEO_KEY_MOMENTS_KEY
  • [x] Create typed provider composables:
    • useProvideVideoControls(controls)
    • useProvideVideoStreaming(streaming)
    • useProvideVideoUI(ui)
    • useProvideKeyMoments(keyMoments)
  • [x] Update DXVideoPlayer.vue to use new provider helpers
  • [x] Ensure all child components use useVideoControlsContext() instead of prop drilling

Phase 2: Shared Utilities & DRY

Goal: Extract reusable helpers and eliminate code duplication

2.1 Core Utilities (composables/core/utils/) ✅

  • [x] Create timeFormatting.ts:
    • formatTime(seconds: number): string (HH:MM:SS or MM:SS)
    • parseTimeToSeconds(timeString: string): number
    • formatDuration(seconds: number): { hours, minutes, seconds }
  • [x] Create fullscreenHelpers.ts:
    • requestFullscreen(element: HTMLElement): Promise<void>
    • exitFullscreen(): Promise<void>
    • getFullscreenElement(): Element | null
    • isFullscreen(element: HTMLElement): boolean
    • Handle webkit prefixes centrally
  • [x] Create keyboardShortcuts.ts:
    • type KeyboardShortcut = { code: string; handler: () => void; preventDefault?: boolean }
    • createKeyboardHandler(shortcuts: KeyboardShortcut[]): (e: KeyboardEvent) => void
    • Define default video shortcuts map

2.2 Remove Duplications ✅

  • [x] Replace all inline formatTime with imported utility
  • [x] Replace fullscreen logic in useVideoControls with imported helpers
  • [x] Consolidate keyboard handling using new keyboard shortcuts system

Phase 3: Component Architecture

Goal: Clean component hierarchy and remove legacy components

3.1 Key Moments Consolidation ✅

  • [x] Decide on component structure:
    • Keep: DXVideoPlayer/KeyMomentsPanel.vue (main panel)
    • Keep: DXVideoPlayer/KeyMoments/Item.vue (moment item)
    • Keep: DXVideoPlayer/KeyMoments/Header.vue (panel header)
    • Delete: KeyMoments.vue (legacy, replace usage with KeyMomentsPanel)
  • [x] Complete Control/KeyMomentsToggle.vue implementation
  • [x] Ensure useKeyMoments composable is consumed via context
  • [x] Share key moments state between progress bar hover and panel

3.2 Progress Bar Enhancement ✅

  • [x] Ensure ProgressBar.vue uses useVideoControlsContext() for state (now Progress/Bar.vue)
  • [x] Extract progress calculation logic to composables/core/progress/useProgressCalculations.ts (integrated in useProgressBar)
  • [x] Use shared time formatting utilities
  • [x] Document hover tooltip frame preview integration (separate HoverTooltip.vue)

3.3 Control Buttons Modernization ✅

  • [x] Refactor ControlButtons.vue to use context instead of props where possible
  • [x] Extract settings menu into separate component:
    • Create DXVideoPlayer/Control/SettingsMenu.vue - Combined speed & quality menu
    • Use current design/implementation but as standalone component
    • Menu should include both speed and quality sections
    • Import and use in ControlButtons.vue or make it a sibling component
  • [x] Create/verify individual control components in DXVideoPlayer/Control/:
    • PlayPause.vue (using Toggle.vue)
    • Volume.vue
    • Time.vue
    • Fullscreen.vue (using Toggle.vue)
    • KeyMomentsToggle.vue
  • [x] Route all styling through useVideoPlayerUI config
  • [x] Add slot support for custom controls on the right side of control bar
    • Define #controls-right slot in ControlButtons.vue with typed scoped props
    • Provides access to controls, streaming, and keyMoments contexts

3.4 On-Video Interactive Controls

  • [ ] Create overlay control components in DXVideoPlayer/Overlay/:
    • CenterPlayButton.vue - Large play/pause button in center of video
    • SeekButtons.vue - Forward/backward 5sec buttons overlaid on video
  • [ ] Implement double-tap zones:
    • Left side: seek backward 5 seconds
    • Right side: seek forward 5 seconds
    • Center: toggle play/pause
  • [ ] Add touch-friendly hit areas for mobile
  • [ ] Animate seek feedback (show "+5s" or "-5s" indicator)
  • [ ] Make overlay controls configurable via props

3.5 Playlist Navigation UI

  • [ ] Create DXVideoPlayer/Playlist/ components:
    • NextVideoPopup.vue - Popup showing next video preview
    • PreviousVideoPopup.vue - Popup showing previous video preview
    • PlaylistControls.vue - Next/Previous buttons for control bar
  • [ ] Popup should display:
    • Video thumbnail
    • Video title/name
    • Video duration
    • Auto-advance countdown (if enabled)
  • [ ] Add playlist navigation to control bar (when playlist is active)
  • [ ] Connect to useVideoPlaylist composable from Phase 1
  • [ ] Add keyboard shortcuts: 'N' for next, 'P' for previous

Phase 4: Streaming & Source Management

Goal: Clean separation of concerns for video initialization

4.1 Streaming Adapters

  • [ ] Create composables/streaming/adapters/:
    • hlsAdapter.ts - HLS initialization, quality selection, DRM
    • dashAdapter.ts - DASH initialization, quality selection, DRM
    • fileAdapter.ts - Native HTML5 video playback
  • [ ] Define typed DRM config interfaces in types/player.ts:
    • DRMConfig { licenseUrl, headers, certificateUrl? }
    • HLSDRMConfig extends DRMConfig
    • DASHDRMConfig extends DRMConfig
  • [ ] Refactor useVideoStreaming.ts:
    • Use adapters for init logic
    • Enforce cleanup → init pattern on source change
    • Return consistent quality/error interfaces

4.2 Initialization Flow

  • [ ] Extract video initialization from DXVideoPlayer.vue into composables/core/useVideoInitializer.ts
  • [ ] Handle autoplay/mute/volume settings in one place
  • [ ] Centralize error handling and emit patterns
  • [ ] Support source change watchers cleanly

Phase 5: UI System & Theming

Goal: Consistent, configurable styling system

5.1 UI Configuration

  • [ ] Audit all components for hardcoded classes (e.g., "absolute inset-0 flex...")
  • [ ] Move all class strings to useVideoPlayerUI config structure
  • [ ] Define UI config schema in types/ui.ts:
    interface VideoPlayerUIConfig {
      root: { base, video, overlay }
      controls: { container, button, progressBar }
      keyMoments: { panel, item, marker }
      playlist: { popup, thumbnail, controls }
      overlay: { centerPlay, seekButtons }
      // ... etc
    }
  • [ ] Document class override examples in README

5.3 Control Visibility & Feature Toggles

  • [ ] Add comprehensive props to DXVideoPlayer for control visibility:
    interface ControlsConfig {
      showPlayPause?: boolean
      showVolume?: boolean
      showSpeed?: boolean
      showQuality?: boolean
      showFullscreen?: boolean
      showKeyMoments?: boolean
      showProgressBar?: boolean
      showTime?: boolean
      showPlaylist?: boolean
      // On-video controls
      showCenterPlayButton?: boolean
      showSeekButtons?: boolean
      seekButtonSeconds?: number // default: 5
    }
  • [ ] Add props to disable specific functions (not just hide):
    interface DisabledFeatures {
      disableSeek?: boolean
      disableVolumeChange?: boolean
      disableSpeedChange?: boolean
      disableQualityChange?: boolean
      disableFullscreen?: boolean
      disableKeyboardShortcuts?: boolean
    }
  • [ ] Merge both into single controls prop:
    <DXVideoPlayer
      :source="source"
      :controls="{
        showSpeed: false,
        showQuality: false,
        disableSeek: true,
        seekButtonSeconds: 10
      }"
    />
  • [ ] Apply visibility/disabled logic in all control components
  • [ ] Document all available control options in README

5.2 Dark/Light Mode Support

  • [ ] Add theme variants to UI config
  • [ ] Allow appConfig.videoPlayer.ui.theme override
  • [ ] Test with different Tailwind themes

Phase 6: Internationalization

Goal: Full i18n support for all user-facing strings

6.1 String Extraction

  • [ ] Extract all hardcoded strings:
    • Control tooltips: "Play", "Pause", "Mute", "Fullscreen"
    • Key moments: "Key Moments", "Preview"
    • Settings: "Speed", "Quality", "Auto"
    • Status: "Buffering...", "Loading..."
  • [ ] Add to runtime/i18n/locale/en.ts and ar.ts
  • [ ] Use $t() or composable in all components

6.2 Accessibility

  • [ ] Add ARIA labels to all interactive controls
  • [ ] Add role attributes to custom controls
  • [ ] Ensure keyboard navigation works for all controls
  • [ ] Add screen reader announcements for state changes

Phase 7: TypeScript & Type Safety

Goal: Comprehensive type coverage and IntelliSense

7.1 Type Definitions

  • [ ] Ensure all composables export return types:
    • UseVideoControlsReturn
    • UseVideoStreamingReturn
    • UseKeyMomentsReturn
    • UseVideoPlayerUIReturn
  • [ ] Add JSDoc comments to all public APIs
  • [ ] Define strict prop types for all components
  • [ ] Add generic types for extensibility (e.g., custom quality types)

7.2 Type Validation

  • [ ] Add runtime validation for source prop (Zod or similar)
  • [ ] Validate DRM configs at initialization
  • [ ] Provide helpful TypeScript errors for misuse

Phase 8: Testing & Documentation

Goal: Maintainable, well-tested codebase

8.1 Unit Tests

  • [ ] Test utilities:
    • Time formatting edge cases
    • Progress calculations (0%, 100%, NaN handling)
    • Keyboard shortcut handlers
  • [ ] Test composables:
    • State management in useVideoControls
    • Frame preview throttling in useFramePreview
    • Key moments filtering and seeking
  • [ ] Test streaming adapters with mocks

8.2 Component Tests

  • [ ] Test DXVideoPlayer initialization flows
  • [ ] Test control interactions (play/pause, seek, volume)
  • [ ] Test keyboard shortcuts
  • [ ] Test fullscreen transitions

8.3 Stories/Examples

  • [ ] Create Storybook stories or playground:
    • HLS video with DRM
    • DASH video with quality switching
    • File video with key moments
    • Playlist example
  • [ ] Add code examples to README:
    • Basic usage
    • With key moments
    • Custom UI config
    • Playlist mode

Phase 9: Performance & Optimization

Goal: Smooth, efficient playback experience

9.1 Optimization

  • [ ] Audit reactive dependencies (avoid unnecessary re-renders)
  • [ ] Throttle/debounce expensive operations:
    • Progress tooltip updates
    • Frame preview generation
    • Buffer progress calculations
  • [ ] Lazy load streaming libraries (HLS.js, DASH.js) only when needed
  • [ ] Use shallowRef for DOM refs to avoid deep reactivity

9.2 Bundle Size

  • [ ] Code-split streaming adapters
  • [ ] Tree-shake unused i18n locales
  • [ ] Analyze bundle with Nuxt analyze

Phase 10: Extensibility & Plugin System

Goal: Easy to extend without modifying core

10.1 Plugin Architecture

  • [ ] Define plugin interface:
    interface VideoPlayerPlugin {
      name: string
      setup(player: VideoPlayerContext): void
      destroy?(): void
    }
  • [ ] Add plugin registration in module config
  • [ ] Example plugins:
    • Analytics plugin (Google Analytics, Plausible)
    • Chromecast support
    • Picture-in-Picture
    • Custom overlays (ads, watermarks)

10.2 Custom Controls & Slots

  • [ ] Implement comprehensive slot system:
    • #controls-left - Custom controls on left side of control bar
    • #controls-right - Custom controls on right side of control bar (HIGH PRIORITY)
    • #controls-center - Custom controls in center
    • #overlay - Custom overlay content (above video)
    • #playlist-popup - Custom playlist navigation popup
    • #loading - Custom loading/buffering indicator
  • [ ] Provide scoped slot props with player state:
    <template #controls-right="{ controls, streaming, keyMoments }">
      <MyCustomButton @click="controls.skip(30)" />
    </template>
  • [ ] Document how to add custom control buttons with examples
  • [ ] Allow control layout overrides via UI config

Implementation Priority

High Priority (Do First):

  1. Phase 1: State & Context unification
  2. Phase 2: DRY utilities
  3. Phase 3: Component cleanup
    • Priority within Phase 3:
      • 3.1 & 3.2: Foundation (Key Moments, Progress Bar)
      • 3.4: On-Video Controls (center play, seek buttons) - HIGH PRIORITY
      • 3.5: Playlist Navigation UI - HIGH PRIORITY
      • 3.3: Control modernization & slots
  4. Phase 4: Streaming refactor

Medium Priority (Do Next): 5. Phase 5: UI system

  • 5.3: Control Visibility Props - MEDIUM-HIGH PRIORITY
  • 5.1 & 5.2: Theming
  1. Phase 6: i18n & a11y
  2. Phase 7: TypeScript improvements

Low Priority (Nice to Have): 8. Phase 8: Testing & docs 9. Phase 9: Performance 10. Phase 10: Extensibility (already partially addressed in Phase 3 with slots)


Success Criteria

Core Architecture

✅ Single source of truth for state (no duplication between composables) ✅ All components use typed context (no prop drilling) ✅ All utilities are reusable and in core/ ✅ Clean component hierarchy (legacy components removed) ✅ Streaming adapters are modular and tested

User Experience

✅ On-video controls (center play button, seek +5/-5 buttons) ✅ Playlist navigation with preview popups ✅ Fully configurable control visibility ✅ Custom control slots (especially #controls-right) ✅ Combined settings menu component (speed + quality in one menu, extracted from ControlButtons)

Developer Experience

✅ Zero hardcoded strings (full i18n support) ✅ Zero hardcoded classes (all via UI config) ✅ TypeScript errors guide correct usage ✅ Comprehensive docs with copy-paste examples ✅ Ready for plugins and custom extensions ✅ Props to enable/disable any control or feature