diff --git a/packages/core/package.json b/packages/core/package.json
index 6f1a65d8b..c4f0dc6e5 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -50,6 +50,7 @@
"@videojs/spf": "workspace:*",
"@videojs/store": "workspace:*",
"@videojs/utils": "workspace:*",
+ "@moq/watch": "^0.2.2",
"hls.js": "^1.6.7"
},
"devDependencies": {
diff --git a/packages/core/src/dom/media/moq/canvas.ts b/packages/core/src/dom/media/moq/canvas.ts
new file mode 100644
index 000000000..695753acd
--- /dev/null
+++ b/packages/core/src/dom/media/moq/canvas.ts
@@ -0,0 +1,335 @@
+import * as Watch from '@moq/watch';
+
+const Moq = Watch.Lite;
+
+const EMPTY_TIME_RANGES = createTimeRanges([]);
+
+const TEMPLATE = document.createElement('template');
+
+TEMPLATE.innerHTML = /*html*/ `
+
+
+`;
+
+// Close everything when this element is garbage collected.
+// There's no destructor for web components so this is the best we can do.
+const cleanup = new FinalizationRegistry((signals) => signals.close());
+
+/**
+ * WebCodecs-backed MoQ media element.
+ *
+ * Creates a `