@opensite/img
High‑performance, native‑like dynamic img rendering engine for the OpenSite ecosystem. It accepts a numeric mediaId, fetches the optimal variants from the DashTrack CDN, and renders the best source for the viewer’s device and browser. It wraps the srcset variants list inside a <picture> tag and can be treated like a standard html <img> tag.
Key points
- Renders a plain
<picture> element (no wrapper, no default styles).
- Accepts all native
<img> props and ref; drop‑in replacement.
- Chooses the best source: Webp → jpg → png.
Installation
Core (required):
pnpm install @opensite/img
Quick Start
Minimal (progressive playback, tiny bundle):
import { Image } from '@opensite/img';
export function Hero({ mediaId }: { mediaId: number }) {
return (
<Image
mediaId={mediaId}
className="hero-video"
/>
);
}
TODO: CONTINUE WRITING OUT DOCS FROM HERE - @opensite/video's README.md below for an example
Upgrade to adaptive streaming only on user interaction (e.g., first play):
<Video mediaId={mediaId} controls streamingOnInteraction />
Force adaptive streaming immediately (if available):
<Video mediaId={mediaId} controls adaptiveStreaming />
Prefer a progressive codec/size (optional):
<Video mediaId={mediaId} preferCodec="WEBM" preferSize="medium" />
Poster behavior:
poster={"https://…"} → use provided URL.
poster={false} → disable poster entirely.
- Poster omitted → auto‑use
cover.url from CDN payload if provided.
Props
Required
mediaId: number — DashTrack media record ID used to fetch the media snapshot.
Optional
cdnHost?: string — Override CDN origin. Default: https://cdn.ing.
adaptiveStreaming?: boolean — Immediately attach HLS/DASH adapter when applicable.
streamingOnInteraction?: boolean — Progressive first, upgrade on first play.
streamingUpgrade?: boolean — Allow upgrades at all (default: true). Set false to force progressive.
preferCodec?: 'HLS' | 'DASH' | 'WEBM' | 'MP4' — Preferred codec when multiple are present.
preferSize?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' — Preferred progressive size variant.
poster?: string | false — Poster override or disable; omitted defaults to CDN cover.url.
onImageData?: (data: ImageData) => void — Callback when CDN payload is loaded.
- All native
<video> attributes (e.g., controls, muted, playsInline, style, className, etc.).
Direct src fallback
- You can omit
mediaId and provide src to play a direct progressive asset (MP4/WebM). In this mode, no CDN request is performed and streaming adapters are not attached.
Ref
- The component forwards a
ref to the underlying <video> element for direct control and event subscriptions.
CDN Integration
- Default fetch URL:
https://cdn.ing/assets/videos/<mediaId>.
- Override origin via
cdnHost prop; path shape is fixed by the module.
- The response is cached at the module level to avoid redundant network calls.
Expected payload (subset)
type ImageData = {
id: number;
cover?: { url: string; width?: number; height?: number };
variants_data: {
variants: {
HLS?: { cdn_master_playlist_url: string; rungs?: { bandwidth?: number; resolution?: string; codecs?: string }[] };
DASH?: { cdn_manifest_url: string; rungs?: { bandwidth?: number; resolution?: string; codecs?: string }[] };
PROGRESSIVE_MP4?: Partial<Record<'tiny'|'small'|'medium'|'large'|'xlarge', string>>;
WEBM?: Partial<Record<'tiny'|'small'|'medium'|'large'|'xlarge', string>>;
};
};
};
Source Selection Logic
Order of preference (auto mode)
- Native HLS (Safari/iOS) via
application/vnd.apple.mpegurl.
- Progressive WebM (modern browsers) by preferred/available size.
- Progressive MP4 (universal fallback) by preferred/available size.
- If only streaming manifests exist and not natively supported, attach
hls.js or dashjs when allowed.
You can override with preferCodec and preferSize as hints; the component will still ensure the final result is playable on the current browser.
Streaming Options
adaptiveStreaming — Attach streaming adapter immediately if an HLS or DASH manifest exists and the browser needs an adapter.
streamingOnInteraction — Keep progressive first, then upgrade on first play event (recommended to minimize initial JS).
streamingUpgrade={false} — Disable all upgrades and stick to progressive assets.
Adapters (dynamic imports)
- HLS (non‑Safari):
hls.js via src/streaming/hls-adapter.
- DASH:
dashjs via src/streaming/dash-adapter.
These imports happen only when required by the chosen streaming path.
Styling & Layout
- The component renders a plain
<video> element.
- No wrapper
<div> and no default CSS are applied.
- Style it exactly as you would a native tag (e.g., with
className, inline style, utility classes, etc.).
Example
<Video mediaId={mediaId} className="w-full h-auto rounded-xl shadow" />
SSR & Environments
- All network requests and capability detection happen in
useEffect, so nothing runs on the server.
- On the server, the component renders a bare
<video>; sources are applied after mount.
- If immediate poster visibility is required with potential network latency, pass
poster explicitly so it shows before the CDN payload loads.
TypeScript
Types are exported from the root module:
import type { ImageData, PreferredCodec, PreferredSize } from '@opensite/video';
Useful types
ImageData, Variants, VariantRung
BrowserCapabilities, SelectedSource
PreferredCodec, PreferredSize
Tree‑Shakable Exports
Recommended
import { Video } from '@opensite/video';
Sub‑paths (advanced)
@opensite/video/core — capability/source helpers
@opensite/video/streaming/hls — HLS adapter (dynamic import normally handles this)
@opensite/video/streaming/dash — DASH adapter (dynamic import normally handles this)
Package.json sets sideEffects: false and an exports map for optimal tree‑shaking.
Examples
Hero/Background (progressive only)
<Video mediaId={mediaId} autoPlay muted loop controls={false} preload="metadata" streamingUpgrade={false} />
Interactive B‑Roll (upgrade on play)
<Video mediaId={mediaId} controls streamingOnInteraction />
Short‑Form (full streaming)
<Video mediaId={mediaId} controls adaptiveStreaming />
Custom poster and sizing
<Video mediaId={mediaId} poster="https://cdn.example.com/posters/123.jpg" style={{ aspectRatio: '16 / 9', width: '100%' }} />
Using a ref
const ref = useRef<HTMLVideoElement>(null);
<Video mediaId={mediaId} controls ref={ref} />
ref.current?.play();
Accessibility (reduced motion)
const prefersReducedMotion = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;
<Video mediaId={mediaId} autoPlay={!prefersReducedMotion} muted loop />
Browser Support
- Safari/iOS: native HLS supported.
- Chrome/Edge/Firefox: progressive WebM/MP4; optional HLS/DASH via adapters.
- The component automatically chooses the best playable source.
Troubleshooting
- No video appears
- Check
mediaId and network tab for the CDN request.
- Verify your CDN returns at least one progressive asset or a streaming manifest.
- Streaming doesn’t start on non‑Safari
- Install
hls.js and/or dashjs.
- Ensure
adaptiveStreaming or streamingOnInteraction is set.
- Poster not shown
- If
poster is omitted and the payload has no cover.url, no poster will be used.
Architecture Notes
- Capability detection and source selection are in
src/core/.
- Streaming adapters (HLS/DASH) live in
src/streaming/ and are imported dynamically.
- CDN integration is isolated in
src/utils/api.ts with lightweight caching.
- The module follows the patterns outlined in
ECOSYSTEM_GUIDELINES.md.
Contributing
- Keep the component free of wrappers and default CSS.
- Preserve progressive‑first behavior; treat streaming as an upgrade.
- Maintain tree‑shakability and small initial bundle size.
- When extending functionality (e.g., custom controls), ensure features are optional and tree‑shakable.
License
Private module for the OpenSite ecosystem.