I’m using the following HTML, CSS and Javascript to disguise a video player as an audio player.
It works perfectly in Firefox but in Chrome pressing the play button does not actually play anything.
What is preventing it from working in chrome and how can I get it to work in Chrome too?
Update:
I want to expand on a observation that I think maybe helpful (A special thank you to @AHaworth for making a similar observation in the comments):
If I remove iframe { display: none; }
& the video player initially loads alongside the audio player, the audio player controls (still) has NO effect on the video player. However, if I click play on the video player and then hide it completely using CSS I am now able to fully control the video player through the audio player.. even though the video player is completely hidden.
This observation is similar to @AHaworth in the comments “The error in the console that seems most relevant is the one saying that can’t play the video because the user has not interacted.”
So the right approach is to force “interactivity” but how?
Check out the CodePen here.
let player;
const playBtn = document.getElementById('play');
const rewindBtn = document.getElementById('rewind');
const forwardBtn = document.getElementById('forward');
const progressBar = document.getElementById('progress-bar');
const currentTimeEl = document.getElementById('current-time');
const endTimeEl = document.getElementById('end-time');
const speedControl = document.getElementById('speed-control');
const volumeBtn = document.getElementById('volume-btn');
const volumeSlider = document.getElementById('volume-slider');
let duration = 0;
window.addEventListener('load', function() {
player = new playerjs.Player(document.getElementById("bunny-stream-embed"));
player.on('ready', () => {
console.log('Player is ready');
player.getDuration(d => {
duration = d;
endTimeEl.innerText = formatTime(duration);
progressBar.max = duration;
});
// Set initial volume to 70%
player.setVolume(70);
volumeSlider.value = 70;
updateVolumeIcon(0.7);
// Set up event listeners after player is ready
setupEventListeners();
});
player.on('timeupdate', (data) => {
currentTimeEl.innerText = formatTime(data.seconds);
progressBar.value = data.seconds;
});
player.on('play', () => {
playBtn.innerHTML = '❚❚'; // Pause icon
});
player.on('pause', () => {
playBtn.innerHTML = '►'; // Play icon
});
});
function setupEventListeners() {
playBtn.addEventListener('click', () => {
player.getPaused(paused => {
if (paused) {
player.play();
} else {
player.pause();
}
});
});
rewindBtn.addEventListener('click', () => {
player.getCurrentTime(currentTime => {
player.setCurrentTime(Math.max(0, currentTime - 15));
});
});
forwardBtn.addEventListener('click', () => {
player.getCurrentTime(currentTime => {
player.setCurrentTime(Math.min(duration, currentTime + 15));
});
});
progressBar.addEventListener('input', (e) => {
const time = parseFloat(e.target.value);
player.setCurrentTime(time);
});
volumeSlider.addEventListener('input', (e) => {
const volume = e.target.value;
player.setVolume(volume);
updateVolumeIcon(volume);
});
speedControl.addEventListener('click', () => {
const speedOptions = [1, 1.25, 1.5, 2];
let currentSpeed = parseFloat(speedControl.innerText.replace('x', ''));
const newSpeed = speedOptions[(speedOptions.indexOf(currentSpeed) + 1) % speedOptions.length];
speedControl.innerText = `${newSpeed}x`;
player.setPlaybackRate(newSpeed);
});
volumeBtn.addEventListener('click', () => {
player.getVolume(volume => {
if (volume > 0) {
player.setVolume(0);
volumeSlider.value = 0;
} else {
player.setVolume(70);
volumeSlider.value = 70;
}
updateVolumeIcon(volume > 0 ? 0 : 0.7);
});
});
}
function updateVolumeIcon(volume) {
if (volume > 0.5) {
volumeBtn.innerHTML = '🔊';
} else if (volume > 0) {
volumeBtn.innerHTML = '🔉';
} else {
volumeBtn.innerHTML = '🔇';
}
}
function formatTime(seconds) {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
}
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
iframe {
display: none;
}
.audio-player {
background-color: #1e3d59;
color: white;
width: 100%;
max-width: 800px;
border-radius: 10px;
overflow: hidden;
}
.player-top {
display: flex;
align-items: center;
padding: 20px;
}
.cover {
width: 60px;
height: 60px;
border-radius: 5px;
margin-right: 15px;
}
.info {
flex-grow: 1;
}
.title {
margin: 0;
font-size: 18px;
}
.author {
margin: 5px 0 0;
font-size: 14px;
opacity: 0.8;
}
.bookmark {
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
}
.player-bottom {
background-color: #102c43;
padding: 15px 20px;
}
.progress {
display: flex;
align-items: center;
margin-bottom: 15px;
}
#progress-bar {
flex-grow: 1;
margin: 0 10px;
cursor: pointer;
}
.controls {
display: flex;
justify-content: space-between;
align-items: center;
}
.control-btn {
background: none;
border: none;
color: white;
font-size: 16px;
cursor: pointer;
}
.play-pause {
font-size: 24px;
}
.playback-rate,
.volume-control {
display: flex;
align-items: center;
}
#volume-slider {
width: 80px;
margin-left: 10px;
}
input[type="range"] {
-webkit-appearance: none;
background: transparent;
}
input[type="range"]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
background: #ffffff50;
border-radius: 2px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
background: white;
border-radius: 50%;
cursor: pointer;
margin-top: -4px;
}
<script type="text/javascript" src="https:////assets.mediadelivery.net/playerjs/player-0.1.0.min.js"></script>
<iframe id="bunny-stream-embed" src="https://iframe.mediadelivery.net/embed/197133/dc48a09e-d9bb-420a-83d7-72dc2304c034?autoplay=false&preload=true" width="720" height="400" frameborder="0" allow="autoplay"></iframe>
<div class="audio-player">
<div class="player-top">
<img class="cover" src="https://images.blinkist.io/images/books/5bf9dc9c6cee070007cab481/1_1/470.jpg" alt="Book Cover">
<div class="info">
<h2 class="title">Atomic Habits</h2>
<p class="author">James Clear</p>
</div>
<button class="bookmark">★</button>
</div>
<div class="player-bottom">
<div class="progress">
<span id="current-time">00:00</span>
<input id="progress-bar" type="range" min="0" max="100" value="0">
<span id="end-time">00:00</span>
</div>
<div class="controls">
<button id="rewind" class="control-btn">← 15</button>
<button id="play" class="control-btn play-pause">►</button>
<button id="forward" class="control-btn">15 →</button>
<div class="playback-rate">
<button id="speed-control" class="control-btn">1x</button>
</div>
<div class="volume-control">
<button id="volume-btn" class="control-btn">🔊</button>
<input type="range" id="volume-slider" min="0" max="100" value="70">
</div>
</div>
</div>
</div>
<script src="script.js"></script>
Alan Moore is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
8