Embedding and the Player API
The iframe
<iframe src="https://media.kokai.studio/embed/123456789?color=1ab7ea&title=0"
width="640" height="360" frameborder="0"
allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media"
allowfullscreen></iframe>A responsive wrapper keeps the aspect ratio without a fixed height. The Share dialog on any video generates both forms for you.
<div style="padding:56.25% 0 0 0;position:relative;">
<iframe src="https://media.kokai.studio/embed/123456789"
style="position:absolute;top:0;left:0;width:100%;height:100%;"
frameborder="0" allow="autoplay; fullscreen; picture-in-picture"
allowfullscreen></iframe>
</div>
<script src="https://media.kokai.studio/player.js"></script>URL parameters
| Parameter | Default | Meaning |
|---|---|---|
autoplay | 0 | Start playing immediately. Browsers force muted autoplay; the player falls back to muted automatically. |
autopause | 1 | Pause this player when another player on the same page starts. |
background | 0 | Hero mode: autoplay, loop, muted, no controls, no interaction. |
byline | 1 | Show the uploader's name in the top overlay. Only when the site is set to name uploaders. |
color | 1ab7ea | Accent colour as a hex value, with or without the #. |
controls | 1 | Show the control bar. The owner's per-video control settings apply on top: a parameter can hide more, never show more. |
dnt | 0 | Do not track: no play is recorded for this session. |
keyboard | 1 | Enable keyboard shortcuts while the player has focus. |
loop | 0 | Restart when the video ends. |
muted | 0 | Start muted. |
pip | 1 | Show the picture-in-picture button. |
playsinline | 1 | Play inline on mobile instead of going fullscreen. |
portrait | 1 | Show the uploader's avatar in the top overlay. Only when the site is set to name uploaders. |
quality | auto | Force a starting quality: 240p, 360p, 540p, 720p, 1080p, 2160p. |
speed | 1 | Show the playback speed menu. |
texttrack | - | Language code of a caption track to enable, e.g. en. |
title | 1 | Show the video title in the top overlay. |
t | 0 | Start offset. Accepts 90, 1m30s or 00:01:30. |
h | - | Unlisted hash, required for unlisted videos. |
Controlling the player
Load https://media.kokai.studio/player.js on the parent page. It exposes a global VideoPlayer whose methods and events match the Vimeo Player SDK, so most code written against that library works unchanged.
<script src="https://media.kokai.studio/player.js"></script>
<script>
const player = new VideoPlayer(document.querySelector('iframe'));
player.on('play', () => console.log('playing'));
player.on('timeupdate', d => progress.value = d.percent);
await player.ready();
await player.setCurrentTime(30);
await player.play();
const [title, duration] = await Promise.all([
player.getVideoTitle(),
player.getDuration(),
]);
</script>You can also build the iframe from a container element:
const player = new VideoPlayer(document.getElementById('holder'), {
id: 123456789,
origin: 'https://media.kokai.studio',
color: '1ab7ea',
muted: 1,
});Methods
play()pause()unload()getCurrentTime()setCurrentTime(seconds)getDuration()getPaused()getEnded()getVolume()setVolume(0-1)getMuted()setMuted(bool)getLoop()setLoop(bool)getPlaybackRate()setPlaybackRate(rate)getQualities()getQuality()setQuality('720p'|'auto')getTextTracks()enableTextTrack(lang)disableTextTrack()getVideoTitle()getVideoId()getVideoUrl()getVideoWidth()getVideoHeight()getVideoEmbedCode()getBuffered()getColor()requestFullscreen()exitFullscreen()requestPictureInPicture()
Events
readyplayplayingpauseendedtimeupdateprogressseekingseekedvolumechangeratechangequalitychangetexttrackchangefullscreenchangeenterpictureinpictureleavepictureinpictureloadedbufferstartbufferenderror
Raw postMessage
If you would rather not load the helper, talk to the iframe directly. Messages are JSON strings in both directions.
iframe.contentWindow.postMessage(JSON.stringify({ method: 'play' }), 'https://media.kokai.studio');
iframe.contentWindow.postMessage(JSON.stringify({ method: 'addEventListener', value: 'timeupdate' }), 'https://media.kokai.studio');
window.addEventListener('message', e => {
const msg = JSON.parse(e.data);
if (msg.event === 'timeupdate') console.log(msg.data.seconds);
if (msg.method === 'getDuration') console.log(msg.value);
});Restricting where a video can be embedded
Each video has an embed setting: anywhere, only on a list of domains, or nowhere. The domain check runs server-side against the Referer of the iframe request, so a blocked domain gets a placeholder rather than the player.