{"id":12968,"library":"cloudflare-video-element","title":"Cloudflare Video Custom Element","description":"The `cloudflare-video-element` package provides a custom web component that wraps the Cloudflare video player, offering an API designed to closely mirror the standard HTMLMediaElement. Currently stable at version 1.3.5, this package is part of the `@muxinc/media-elements` monorepo, which sees frequent updates across its various media element packages, though direct updates to `cloudflare-video-element` specifically might be less frequent. Its primary differentiator is providing a familiar `<video>` tag-like interface for Cloudflare streams, promoting reusability and encapsulation within modern web applications. It also boasts seamless integration with `Media Chrome` for consistent player UI, and ships with TypeScript types for enhanced developer experience. Developers can use it directly in HTML after a simple JavaScript import, benefiting from standard browser events and properties.","status":"active","version":"1.3.5","language":"javascript","source_language":"en","source_url":"https://github.com/muxinc/media-elements","tags":["javascript","cloudflare","video","player","web component","custom element","typescript"],"install":[{"cmd":"npm install cloudflare-video-element","lang":"bash","label":"npm"},{"cmd":"yarn add cloudflare-video-element","lang":"bash","label":"yarn"},{"cmd":"pnpm add cloudflare-video-element","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Provides a base class for custom media elements, abstracting common `HTMLMediaElement` behaviors and ensuring API compatibility. This package likely extends or utilizes it internally.","package":"custom-media-element","optional":false}],"imports":[{"note":"This is a side-effect import that registers the `<cloudflare-video>` custom element with the browser. It does not export a named class for direct instantiation. Ensure this script runs before your custom element is rendered in the DOM.","wrong":"const CloudflareVideoElement = require('cloudflare-video-element');","symbol":"cloudflare-video-element","correct":"import 'cloudflare-video-element';"},{"note":"While the custom element is registered via a side-effect import, you can import its TypeScript type for better type checking when interacting with the element programmatically via `document.querySelector<CloudflareVideoElement>('cloudflare-video')`.","wrong":"import { CloudflareVideoElement } from 'cloudflare-video-element';","symbol":"CloudflareVideoElement (type)","correct":"import type { CloudflareVideoElement } from 'cloudflare-video-element';"}],"quickstart":{"code":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Cloudflare Video Element Quickstart</title>\n    <!-- Load from CDN (or bundle your npm import) -->\n    <script type=\"module\" src=\"https://cdn.jsdelivr.net/npm/cloudflare-video-element@latest/+esm\"></script>\n    <style>\n        cloudflare-video {\n            width: 100%;\n            max-width: 640px;\n            display: block; /* Custom elements are inline by default */\n            margin: 20px auto;\n            border: 1px solid #ccc;\n            background-color: #000;\n        }\n    </style>\n</head>\n<body>\n    <h1>Cloudflare Video Element Demo</h1>\n    <p>This demonstrates the <code>&lt;cloudflare-video&gt;</code> custom element playing a Cloudflare stream,\n       with standard HTMLMediaElement controls and API.</p>\n\n    <cloudflare-video controls autoplay muted loop\n        src=\"https://watch.videodelivery.net/bfbd585059e33391d67b0f1d15fe6ea4\"\n        style=\"--media-accent-color: #007bff;\"\n    ></cloudflare-video>\n\n    <p>Programmatic control example:</p>\n    <button id=\"playButton\">Play</button>\n    <button id=\"pauseButton\">Pause</button>\n    <button id=\"muteButton\">Toggle Mute</button>\n    <span id=\"currentTime\">0:00</span> / <span id=\"duration\">0:00</span>\n\n    <script type=\"module\">\n        const videoElement = document.querySelector('cloudflare-video');\n        const playButton = document.getElementById('playButton');\n        const pauseButton = document.getElementById('pauseButton');\n        const muteButton = document.getElementById('muteButton');\n        const currentTimeSpan = document.getElementById('currentTime');\n        const durationSpan = document.getElementById('duration');\n\n        if (videoElement) {\n            playButton.addEventListener('click', () => videoElement.play());\n            pauseButton.addEventListener('click', () => videoElement.pause());\n            muteButton.addEventListener('click', () => videoElement.muted = !videoElement.muted);\n\n            videoElement.addEventListener('timeupdate', () => {\n                currentTimeSpan.textContent = formatTime(videoElement.currentTime);\n            });\n\n            videoElement.addEventListener('durationchange', () => {\n                durationSpan.textContent = formatTime(videoElement.duration);\n            });\n\n            videoElement.addEventListener('loadedmetadata', () => {\n                durationSpan.textContent = formatTime(videoElement.duration);\n            });\n        }\n\n        function formatTime(seconds) {\n            const minutes = Math.floor(seconds / 60);\n            const remainingSeconds = Math.floor(seconds % 60);\n            return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;\n        }\n    </script>\n</body>\n</html>","lang":"typescript","description":"This quickstart demonstrates how to include and use the `<cloudflare-video>` custom element in an HTML page, both declaratively and with basic programmatic control using JavaScript, mimicking the standard HTMLMediaElement API."},"warnings":[{"fix":"Rely on the side-effect import to register the element globally, then use it as a standard HTML tag: `<cloudflare-video src=\"...\"></cloudflare-video>`. For programmatic access, use `document.querySelector('cloudflare-video')`.","message":"The primary way to use `cloudflare-video-element` is through a side-effect import (`import 'cloudflare-video-element';`) which registers the custom element. This means there is no named export for a `CloudflareVideoElement` class to import and instantiate directly in JavaScript. The element is intended for declarative use in HTML.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure the import script is loaded and executed early in your application, ideally in the `<head>` with `type=\"module\"`, or before the custom element appears in the `<body>`. If using a bundler, ensure the import statement is at the root of your application's entry point.","message":"Like all custom elements, `cloudflare-video-element` must be defined in the browser's `CustomElementRegistry` before any instances of the element are encountered in the DOM. If your script loads asynchronously or after your HTML renders, the element may not display correctly or will appear as an unknown tag.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Implement client-only rendering for the custom element or use hydration techniques if you are in an SSR framework. For example, in React, you might use `useEffect` to mount the element on the client, or conditionally render it based on `typeof window !== 'undefined'`.","message":"As a browser-specific custom element relying on DOM APIs, `cloudflare-video-element` is not directly compatible with server-side rendering (SSR) environments. Attempting to render this element on the server will result in errors related to missing DOM APIs.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the `import 'cloudflare-video-element';` statement or the CDN script tag is present only once in your application's lifecycle, typically at your main entry point or in the HTML head.","cause":"The `cloudflare-video-element` script, which registers the custom element, has been loaded or imported multiple times.","error":"Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': the name \"cloudflare-video\" has already been used with this Registry."},{"fix":"Verify that your `import 'cloudflare-video-element';` statement or `<script type=\"module\" src=\"...\"></script>` tag is loaded and executed *before* the `<cloudflare-video>` element appears in the document. Place script tags in the `<head>` or use deferred/async loading strategies carefully.","cause":"You are attempting to use the `<cloudflare-video>` tag in your HTML before the JavaScript responsible for registering this custom element has executed.","error":"The custom element <cloudflare-video> has not been defined."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":""}