Videos
How to upload and embed videos
Two steps and one decision. The decision — which project to upload into — determines the encryption, domain rules and player appearance the video inherits, so make it first.
Updated 11 August 2026
Before you start
- Create a project, or know which existing project the video belongs in. Settings are per project, not per video.
- If the video must be protected, turn on encryption and add your domains before uploading — see "How to turn on video encryption".
- Have the source file to hand. Upload the highest-quality master you have; DynTube derives the streaming versions from it.
Step 1 — upload the video
- Open the project you want the video in.
- Choose Upload, then select the source file. Several files can be queued at once.
- Leave the page open until each upload reports that it has been received. Closing the tab mid-transfer cancels that transfer.
- Wait for processing. The video shows as processing while the streaming versions and thumbnails are generated, and becomes ready when playback is available.
Processing time depends on the duration and resolution of the source, and on how much is queued ahead of it. A video can be renamed, described and given a thumbnail while it is still processing; it simply cannot be played yet.
Uploading from your own system instead
If uploads should happen from your application rather than by hand, use the API. Server-side upload from a URL or from a file, and browser-side upload through an HTML form, are all documented in the developer reference.
Step 2 — embed the video
- Open the video in the dashboard and choose Embed.
- Copy the iframe snippet — it is the one marked Recommended.
- Paste it into your page, your CMS block or your course platform’s embed field.
Both snippets are generated for you, already filled in with that video’s embed key. The examples below show the same shape with the key written as YOUR_EMBED_KEY, so you can read what each part does before you paste your own.
<div style="position:relative;width:100%;overflow:hidden;padding-top:56.25%">
<iframe
style="position:absolute;top:0;left:0;bottom:0;right:0;width:100%;height:100%;border:none"
allow="autoplay; fullscreen"
allowfullscreen
src="https://dyn.tube/embed/video/YOUR_EMBED_KEY?playerId=dyntube-YOUR_EMBED_KEY"
title="Your video title"></iframe>
</div>The outer div is what makes this responsive: it fills the width available and its 56.25% top padding reserves a 16:9 box, while the iframe is pinned to all four sides of it. Width follows the column it sits in; the ratio stays fixed. Nothing else on the page is required — there is no script to add, and each video is its own self-contained snippet.
Change the title attribute to something that describes the video. Screen readers announce it, and “Video” tells a listener nothing.
Optional — the JavaScript embed
The dashboard also offers a JavaScript version. It is the same iframe, plus a module script that attaches the DyntubePlayer SDK to it so your own code can hold a reference to the player. Use it when you need that reference; otherwise the iframe above is the better choice, because it still loads the player but needs no extra SDK module and no initialisation step.
<iframe id="dyntube-YOUR_EMBED_KEY"
src="https://dyn.tube/embed/video/YOUR_EMBED_KEY?playerId=dyntube-YOUR_EMBED_KEY"
allow="autoplay; fullscreen; encrypted-media; picture-in-picture"
allowfullscreen
style="width:100%;aspect-ratio:16/9;border:0"></iframe>
<script type="module">
import { DyntubePlayer } from "https://embed.dyntube.com/v2/embed-sdk.js";
const player = new DyntubePlayer("#dyntube-YOUR_EMBED_KEY", { playerId: "dyntube-YOUR_EMBED_KEY" });
await player.ready;
</script>Three things have to agree here: the iframe id, the CSS selector passed to DyntubePlayer, and the playerId option. The generated snippet sets all three to dyntube- followed by the embed key. Awaiting player.ready tells you the player has finished initialising. The script is a module, so it must be served as one; a rich-text field that strips script tags will silently drop it and leave the plain iframe behind — which still plays.
What goes in the snippet
| Part | Value | Notes |
|---|---|---|
| Embed key | The video’s EmbedKey | Required. It is the only identifier in the snippet, and the dashboard fills it in for you. If the dashboard says the video is missing its embed key, it will not generate embed code for that video — ask support rather than hand-building a URL. |
| Embed URL | https://dyn.tube/embed/video/YOUR_EMBED_KEY | The canonical player URL for a single video. Your account may be served from a different player host; copy the URL the dashboard gives you rather than typing this one. |
| playerId | dyntube-YOUR_EMBED_KEY | Appended by the generator to both snippets, and reused as the iframe id and the SDK’s playerId in the JavaScript version. |
| allow | autoplay; fullscreen (plus encrypted-media and picture-in-picture on the SDK snippet) | Browser permissions granted to the iframe. Removing fullscreen or allowfullscreen disables the fullscreen button. |
| title | Your own text | The accessible name of the iframe. The generator seeds it with the video’s title. |
Checking it worked
- Open the page on your own site and confirm playback starts.
- If the video is protected, open the same embed from a domain that is not on your allowed list. It should fail to play. That refusal is the test that matters.
- Check the page on a phone. The wrapper should scale to the column width without a horizontal scrollbar, keeping its 16:9 shape.
If it does not play
| What you see | Likely cause | What to do |
|---|---|---|
| Playback is refused with "Sorry, video playback isn't available on this host!" | The embedding host does not match the effective allowed-domain list, so playback authorization answers 403 (domain_denied). An empty list means no domain restriction; only a non-empty list that does not match refuses. | Add the host the page is actually served from — including any live, staging or preview host — to the allowed domains that apply to this video. |
| Nothing renders at all | The iframe was altered or stripped when it was pasted, or a content-security policy is blocking frames from the player host. | Compare what is live against the copied snippet, and allow the player host in your frame-src policy. |
| The box has no height | The wrapper div — or its padding-top — was dropped, so nothing reserves the 16:9 area. | Paste the whole snippet, wrapper included. The iframe is absolutely positioned and has no size of its own without it. |
| Video reports as processing | The streaming versions are not ready yet. | Wait for the status to become ready. Longer or higher-resolution sources take longer. |
| Plays on your site but not inside your course platform | The platform sanitises the field you pasted into, stripping the iframe, its style attribute or the module script. | Use a custom-HTML or embed block rather than a rich-text field. |
| The SDK never initialises | The iframe id, the DyntubePlayer selector and the playerId option no longer match, or the module script was stripped. | Re-copy the JavaScript snippet so all three carry the same dyntube- prefixed embed key. |
Limitations to be aware of
- Domain restrictions protect embeds, not viewers. Someone already authorised can still record their own screen.
- Changing a project’s encryption setting affects videos uploaded afterwards. Re-check existing videos rather than assuming they were updated.
- Moving a video to another project changes which project’s access and restriction settings apply to it, from the moment it is moved. Where the destination project overrides them, its allowed domains and country rules take effect instead of the account defaults, so an embed that played before the move can change behaviour or stop playing. Re-test the real embed page after any move.
- Embed code needs the video’s embed key. A video without one shows a notice in the embed dialog instead of a snippet, and cannot be embedded until that is resolved.
Something missing or wrong here? Tell us and we will correct it. New to DynTube? Start with uploading and embedding.