Lit — это легковесный фреймворк для создания веб-компонентов, основанных на стандартных технологиях Web Components. Он обеспечивает декларативное обновление DOM через шаблоны и реактивные свойства, что позволяет создавать сложные интерфейсы, включая медиа-компоненты, с минимальным количеством кода.
Для интеграции видео можно использовать стандартный HTML-элемент
<video> внутри Lit-компонента, при этом свойства и
события элемента можно связывать с реактивными свойствами класса.
import { LitElement, html, css } from 'lit';
import { property } from 'lit/decorators.js';
class VideoPlayer extends LitElement {
static styles = css`
video {
width: 100%;
border-radius: 8px;
background: #000;
}
`;
@property({ type: String }) src = '';
@property({ type: Boolean }) autoplay = false;
@property({ type: Boolean }) controls = true;
render() {
return html`
<video
src="${this.src}"
?autoplay="${this.autoplay}"
?controls="${this.controls}">
</video>
`;
}
}
customElements.define('video-player', VideoPlayer);
Ключевые моменты:
@property) автоматически обновляют
DOM при изменении значений.WebCodecs предоставляет низкоуровневый API для работы с видео- и аудиопотоками, позволяя декодировать и кодировать медиа практически в реальном времени. В Lit-компонентах WebCodecs можно использовать для расширенного управления медиаконтентом.
class CodecVideoPlayer extends LitElement {
@property({ type: String }) videoUrl = '';
private videoFrameQueue = [];
private decoder;
connectedCallback() {
super.connectedCallback();
this.initDecoder();
}
async initDecoder() {
const response = await fetch(this.videoUrl);
const buffer = await response.arrayBuffer();
this.decoder = new VideoDecoder({
output: frame => this.queueFrame(frame),
error: e => console.error('Decoder error:', e)
});
const config = {
codec: 'vp8',
codedWidth: 640,
codedHeight: 480
};
this.decoder.configure(config);
this.decoder.decode(new EncodedVideoChunk({ type: 'key', timestamp: 0, data: new Uint8Array(buffer) }));
}
queueFrame(frame) {
this.videoFrameQueue.push(frame);
this.requestUpdate();
}
render() {
return html`
<canvas id="videoCanvas" width="640" height="480"></canvas>
`;
}
updated() {
const canvas = this.renderRoot.getElementById('videoCanvas');
const ctx = canvas.getContext('2d');
while (this.videoFrameQueue.length > 0) {
const frame = this.videoFrameQueue.shift();
ctx.drawImage(frame, 0, 0);
frame.close();
}
}
}
customElements.define('codec-video-player', CodecVideoPlayer);
Ключевые моменты:
VideoDecoder используется для декодирования видео в
формате VP8/VP9/H.264.output получает VideoFrame, который
можно отобразить на <canvas>.close(), чтобы не
создавать утечки памяти.WebCodecs также поддерживает аудиодекодеры
(AudioDecoder) и позволяет работать с аудиопотоками
напрямую, что полезно для создания визуализаторов или обработчиков звука
в реальном времени.
class AudioPlayer extends LitElement {
@property({ type: String }) audioUrl = '';
private audioDecoder;
private audioContext = new AudioContext();
connectedCallback() {
super.connectedCallback();
this.initDecoder();
}
async initDecoder() {
const response = await fetch(this.audioUrl);
const buffer = await response.arrayBuffer();
this.audioDecoder = new AudioDecoder({
output: audioData => this.playAudio(audioData),
error: e => console.error('AudioDecoder error:', e)
});
const config = {
codec: 'opus',
sampleRate: 48000,
numberOfChannels: 2
};
this.audioDecoder.configure(config);
this.audioDecoder.decode(new EncodedAudioChunk({ type: 'key', timestamp: 0, data: new Uint8Array(buffer) }));
}
playAudio(audioData) {
const buffer = this.audioContext.createBuffer(
audioData.numberOfChannels,
audioData.numberOfFrames,
audioData.sampleRate
);
for (let i = 0; i < audioData.numberOfChannels; i++) {
audioData.copyTo(buffer.getChannelData(i), { planeIndex: i });
}
const source = this.audioContext.createBufferSource();
source.buffer = buffer;
source.connect(this.audioContext.destination);
source.start();
audioData.close();
}
render() {
return html`<div>Аудиоплеер готов к воспроизведению</div>`;
}
}
customElements.define('audio-player', AudioPlayer);
Ключевые моменты:
AudioDecoder декодирует сжатый аудиопоток (Opus, AAC и
др.) в PCM.AudioContext используется для воспроизведения и
обработки аудио.Lit позволяет легко связывать состояния плеера с DOM:
playing,
paused) для управления кнопками.@property({ type: Boolean }) playing = false;
togglePlay() {
this.playing = !this.playing;
const video = this.renderRoot.querySelector('video');
this.playing ? video.play() : video.pause();
}
Lit позволяет применять локальные стили через css и
использовать Shadow DOM для изоляции. В медиа-компонентах это важно
для:
static styles = css`
:host {
display: block;
max-width: 640px;
margin: auto;
}
button {
background: #444;
color: #fff;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
`;
Эти подходы позволяют строить мощные медиа-компоненты, полностью управляемые через реактивные свойства и события Lit, с возможностью интеграции низкоуровневых WebCodecs для сложной обработки аудио и видео.