py-player
v0.2.0
Published
A dependency-free Web Component media player with audio visualization, video controls, and 7 layout presets
Maintainers
Readme
py-player
A dependency-free Web Component media player with audio visualization, video controls, 7 layout presets, 7 themes, and i18n support.
Installation
CDN
<script src="https://unpkg.com/py-player/dist/py-player.min.js"></script>Or jsDelivr:
<script src="https://cdn.jsdelivr.net/npm/py-player/dist/py-player.min.js"></script>npm
npm install py-playerimport 'py-player'Quick Start
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/py-player/dist/py-player.min.js"></script>
</head>
<body>
<py-audio
src="https://example.com/podcast.mp3"
title="My Podcast"
theme="auto"
></py-audio>
</body>
</html>Elements
| Element | Description |
|---------|-------------|
| <py-audio> | Audio player with real-time frequency visualization |
| <py-video> | Video player with fullscreen, PiP, volume, speed |
| <py-player> | Smart wrapper — auto-detects media type |
Layouts
All 7 layout presets work with any theme:
Normal (default)
<py-audio src="audio.mp3" layout="normal" title="My Player"></py-audio>Minimal
<py-audio src="audio.mp3" layout="minimal"></py-audio>Album Art
<py-audio
src="audio.mp3"
layout="album-art"
poster="cover.jpg"
artist="Artist Name"
title="Track Title"
></py-audio>Compact
<py-audio src="audio.mp3" layout="compact" title="Now Playing"></py-audio>Podcast
<py-audio
src="podcast.mp3"
layout="podcast"
title="Episode 42"
poster="episode.jpg"
skip-back="15"
skip-forward="30"
tracks='[
{"name":"Intro","time":"0:00"},
{"name":"Main","time":"2:30"},
{"name":"Outro","time":"28:00"}
]'
></py-audio>Visualizer
<py-audio
src="music.mp3"
layout="visualizer"
theme="midnight"
accent="#ff6b6b"
></py-audio>Playlist-first
<py-audio
src="music.mp3"
layout="playlist-first"
tracks='[
{"name":"Track 1","time":"0:00"},
{"name":"Track 2","time":"3:30"},
{"name":"Track 3","time":"7:00"}
]'
></py-audio>Video Player
<py-video
src="https://example.com/video.mp4"
poster="thumbnail.jpg"
title="My Video"
theme="dark"
></py-video>Controls include: play/pause, progress seek, volume slider, speed selector (0.5x–2x), Picture-in-Picture, fullscreen.
Playlist & Chapters
Single-file chapters
<py-audio
src="podcast.mp3"
tracks='[
{"name": "Intro", "time": "0:00"},
{"name": "Main", "time": "2:30"},
{"name": "Outro", "time": "28:00"}
]'
></py-audio>Multi-file playlist
<py-audio tracks='[
{
"name": "Episode 1",
"src": "ep1.mp3",
"chapters": [
{"name": "Intro", "time": "0:00"},
{"name": "Main", "time": "3:00"}
]
},
{
"name": "Episode 2",
"src": "ep2.mp3"
}
]'></py-audio>M3U playlist
<py-audio playlist="https://example.com/playlist.m3u"></py-audio>Theming
Preset themes
<py-audio src="audio.mp3" theme="dark"></py-audio>
<py-audio src="audio.mp3" theme="midnight" accent="#7c4dff"></py-audio>
<py-audio src="audio.mp3" theme="nord"></py-audio>
<py-audio src="audio.mp3" theme="sunset"></py-audio>
<py-audio src="audio.mp3" theme="forest"></py-audio>Available themes: auto light dark midnight nord sunset forest
CSS variables
py-audio {
--py-accent: #e07b39;
--py-bg: #1a1a2e;
--py-radius: 16px;
}CSS Parts
py-audio::part(btn-play) {
border-radius: 50%;
background: linear-gradient(135deg, #ff6b6b, #feca57);
}
py-audio::part(progress-fill) {
background: #e07b39;
}i18n
<py-audio
src="audio.mp3"
strings='{"nowPlaying":"Đang phát","playlist":"Danh sách"}'
></py-audio>Or via JS:
player.setStrings({
nowPlaying: 'Đang phát',
trackCount: '{count} bài',
play: 'Phát',
pause: 'Tạm dừng',
})JavaScript API
const player = document.querySelector('py-audio')
// Playback
player.play()
player.pause()
console.log(player.paused)
console.log(player.currentTime)
console.log(player.duration)
player.currentTime = 60
// Tracks
player.setTracks([
{ name: 'Chapter 1', time: '0:00' },
{ name: 'Chapter 2', time: '5:30' },
])
// M3U
player.loadPlaylist('https://example.com/playlist.m3u')
// Events
player.addEventListener('py-play', () => console.log('playing'))
player.addEventListener('py-pause', () => console.log('paused'))
player.addEventListener('py-track-change', (e) => console.log(e.detail))
player.addEventListener('py-time-update', (e) => console.log(e.detail))
player.addEventListener('py-error', (e) => console.error(e.detail))Video API
const video = document.querySelector('py-video')
video.volume = 0.5
video.playbackRate = 1.5
video.muted = false
video.requestFullscreen()
video.requestPiP()
video.addEventListener('py-fullscreen', (e) => console.log(e.detail.active))Attributes
| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| src | string | — | Media URL |
| title | string | — | Player title |
| theme | string | auto | Color theme |
| accent | string | #378ADD | Accent color |
| tracks | string | — | JSON tracks array |
| playlist | string | — | M3U/M3U8 URL |
| layout | string | normal | Layout preset |
| allow-upload | bool | — | Enable file upload |
| show-playlist | bool | — | Show playlist on minimal and album-art layouts |
| strings | string | — | JSON string overrides |
| poster | string | — | Artwork/thumbnail URL |
| artist | string | — | Artist name |
| skip-back | number | 15 | Podcast skip back seconds |
| skip-forward | number | 30 | Podcast skip forward seconds |
Browser Support
Requires Custom Elements v1, Shadow DOM v1, Web Audio API, Fullscreen API, and Picture-in-Picture API.
Practical minimum: Chrome 111+, Firefox 113+, Safari 16.4+, Edge 111+
Contributing
- Fork the repository
- Install dependencies:
npm install - Run tests:
npm test - Build:
npm run build - Start dev mode:
npm run dev - View docs:
npm run docs:dev
Please follow existing code style and include tests for any new functionality.
License
MIT
